musicbox wip

This commit is contained in:
minjaesong
2024-04-15 04:27:16 +09:00
parent 9762f38868
commit 96954983f0
3 changed files with 52 additions and 11 deletions

View File

@@ -18,6 +18,9 @@ abstract class AudioBank : Disposable {
abstract val totalSizeInSamples: Long
abstract fun currentPositionInSamples(): Long
open fun sendMessage(msg: String) {}
open fun sendMessage(bits: Long) {}
abstract fun readSamples(bufferL: FloatArray, bufferR: FloatArray): Int
abstract fun reset()

View File

@@ -1,6 +1,5 @@
package net.torvald.terrarum.modulebasegame.audio.audiobank
import com.badlogic.gdx.utils.Queue
import net.torvald.terrarum.App
import net.torvald.terrarum.INGAME
import net.torvald.terrarum.audio.AudioBank
@@ -13,17 +12,17 @@ class AudioBankMusicBox(override var songFinishedHook: (AudioBank) -> Unit = {})
private data class Msg(val tick: Long, val samplesL: FloatArray, val samplesR: FloatArray, var samplesDispatched: Int = 0) // in many cases, samplesL and samplesR will point to the same object
override val name = "spieluhr"
override val samplingRate = 48000
override val samplingRate = 48000 // 122880 // use 122880 to make each tick is 2048 samples
override val channels = 1
private val getSample = // usage: getSample(noteNum 0..60)
InstrumentLoader.load("spieluhr", "basegame", "audio/effects/notes/spieluhr.ogg", 29)
private val SAMEPLES_PER_TICK = samplingRate / App.TICK_SPEED // should be 800 on default setting
private val SAMPLES_PER_TICK = samplingRate / App.TICK_SPEED // should be 800 on default setting
override val totalSizeInSamples = getSample(0).first.size.toLong() // length of lowest-pitch note
private val messageQueue = Queue<Msg>()
private val messageQueue = ArrayList<Msg>()
private fun findSetBits(num: Long): List<Int> {
val result = mutableListOf<Int>()
@@ -38,7 +37,7 @@ class AudioBankMusicBox(override var songFinishedHook: (AudioBank) -> Unit = {})
/**
* Queues the notes such that they are played on the next tick
*/
fun queuePlay(noteBits: Long) {
override fun sendMessage(noteBits: Long) {
if (noteBits == 0L) return
val tick = INGAME.WORLD_UPDATE_TIMER + 1
@@ -54,17 +53,34 @@ class AudioBankMusicBox(override var songFinishedHook: (AudioBank) -> Unit = {})
}
// actually queue it
messageQueue.addLast(Msg(tick, buf, buf))
messageQueue.add(Msg(tick, buf, buf))
}
override fun currentPositionInSamples(): Long {
TODO("Not yet implemented")
}
override fun currentPositionInSamples() = 0L
override fun readSamples(bufferL: FloatArray, bufferR: FloatArray): Int {
val tickCount = INGAME.WORLD_UPDATE_TIMER
val bufferSize = bufferL.size
TODO("Not yet implemented")
// only copy over the past and current messages
messageQueue.filter { it.tick <= tickCount }.forEach {
// copy over the samples
for (i in 0 until minOf(bufferSize, it.samplesL.size - it.samplesDispatched)) {
bufferL[i] += it.samplesL[i + it.samplesDispatched]
bufferR[i] += it.samplesR[i + it.samplesDispatched]
}
it.samplesDispatched += bufferSize
}
// dequeue the finished messages
val messagesToKill = ArrayList<Msg>(messageQueue.filter { it.samplesDispatched >= it.samplesL.size })
if (messagesToKill.isNotEmpty()) messagesToKill.forEach {
messageQueue.remove(it)
}
return bufferSize
}
override fun reset() {
@@ -78,4 +94,23 @@ class AudioBankMusicBox(override var songFinishedHook: (AudioBank) -> Unit = {})
override fun dispose() {
TODO("Not yet implemented")
}
private fun prel(n1: Int, n2: Int, n3: Int, n4: Int, n5: Int): List<Int> {
return listOf(
n1, n2, n3, n4, n5, n3, n4, n5,
n1, n2, n3, n4, n5, n3, n4, n5
)
}
private val testNotes = prel(0,0,0,0,0)+
prel(24,28,31,36,40) +
prel(24, 26,33,28,41) +
prel(23,26,31,38,41) +
prel(24,28,31,36,40) +
prel(24,28,33,40,45) +
prel(24,26,30,33,38) +
prel(23,26,31,38,43) +
prel(23,24,28,31,36) +
prel(21,24,28,31,36)
}

View File

@@ -24,6 +24,8 @@ object InstrumentLoader {
* Will read the sample and create 61 copies of them. Rendered samples will be stored on the CommonResourcePool
* with the naming rule of `"${idBase}_${noteNumber}"`, with format of Pair<FloatArray, FloatArray>
*
* The sample must be in two channels, 48 kHz sampling rate.
*
* If `isDualMono` option is set, two values of a pair will point to the same FloatArray.
*
* @param idBase Base ID string
@@ -77,10 +79,11 @@ object InstrumentLoader {
}
private val TAPS = 8
private val RESAMPLE_RATE = 1.0// 122880.0 / 48000.0
private fun resample(input: FloatArray, output: FloatArray, rate: Double) {
for (sampleIdx in 0 until output.size) {
val t = sampleIdx.toDouble() * rate
val t = sampleIdx.toDouble() * rate * RESAMPLE_RATE
val leftBound = maxOf(0, (t - TAPS + 1).floorToInt())
val rightBound = minOf(input.size - 1, (t + TAPS).ceilToInt())