mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-08 04:41:51 +09:00
working musicbox
This commit is contained in:
Binary file not shown.
@@ -12,8 +12,7 @@ class AudioBankMusicBox(override var songFinishedHook: (AudioBank) -> Unit = {})
|
||||
|
||||
override val notCopyable = true
|
||||
|
||||
// TODO don't store samples (1MB each!), store numbers instead and synthesize on readSamples()
|
||||
internal 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
|
||||
internal data class Msg(val tick: Long, val notes: IntArray, val maxlen: Int, var samplesDispatched: Int = 0) { // in many cases, samplesL and samplesR will point to the same object
|
||||
override fun toString(): String {
|
||||
return "Msg(tick=$tick, samplesDispatched=$samplesDispatched)"
|
||||
}
|
||||
@@ -59,19 +58,11 @@ class AudioBankMusicBox(override var songFinishedHook: (AudioBank) -> Unit = {})
|
||||
private fun queue(tick: Long, noteBits: Long) {
|
||||
if (noteBits == 0L) return
|
||||
|
||||
val notes = findSetBits(noteBits)
|
||||
|
||||
val buf = FloatArray(getSample(0).first.size)
|
||||
|
||||
// combine all those samples
|
||||
notes.forEach { note ->
|
||||
getSample(note).first.forEachIndexed { index, fl ->
|
||||
buf[index] += fl
|
||||
}
|
||||
}
|
||||
val notes = findSetBits(noteBits).toIntArray()
|
||||
val maxlen = getSample(notes.first()).first.size
|
||||
|
||||
// actually queue it
|
||||
val msg = Msg(tick, buf, buf)
|
||||
val msg = Msg(tick, notes, maxlen)
|
||||
messageQueue.add(messageQueue.size, msg)
|
||||
}
|
||||
|
||||
@@ -87,9 +78,15 @@ class AudioBankMusicBox(override var songFinishedHook: (AudioBank) -> Unit = {})
|
||||
// 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.notes.forEach { note ->
|
||||
val noteSamples = getSample(note)
|
||||
val start = it.samplesDispatched
|
||||
val end = minOf(start + bufferSize, noteSamples.first.size)
|
||||
|
||||
for (i in start until end) {
|
||||
bufferL[i - start] += noteSamples.first[i]
|
||||
bufferR[i - start] += noteSamples.second[i]
|
||||
}
|
||||
}
|
||||
|
||||
it.samplesDispatched += bufferSize
|
||||
@@ -99,7 +96,7 @@ class AudioBankMusicBox(override var songFinishedHook: (AudioBank) -> Unit = {})
|
||||
var rc = 0
|
||||
while (rc < messageQueue.size) {
|
||||
val it = messageQueue[rc]
|
||||
if (it.samplesDispatched >= it.samplesL.size) {
|
||||
if (it.samplesDispatched >= it.maxlen) {
|
||||
messageQueue.removeAt(rc)
|
||||
rc -= 1
|
||||
}
|
||||
@@ -107,8 +104,6 @@ class AudioBankMusicBox(override var songFinishedHook: (AudioBank) -> Unit = {})
|
||||
rc += 1
|
||||
}
|
||||
|
||||
printdbg(this, "Queuelen: ${messageQueue.size}")
|
||||
|
||||
return bufferSize
|
||||
}
|
||||
|
||||
|
||||
@@ -53,80 +53,84 @@ class FixtureMechanicalTines : Electric {
|
||||
}
|
||||
|
||||
@Transient private var testRollCursor = 0
|
||||
@Transient private val TICK_DIVISOR = 12
|
||||
|
||||
override fun updateSignal() {
|
||||
// TODO update using network port
|
||||
|
||||
|
||||
if (isSignalHigh(0, 1)) {
|
||||
if (INGAME.WORLD_UPDATE_TIMER % TICK_DIVISOR == 0L) {
|
||||
audioBank.sendMessage(testNotes[testRollCursor])
|
||||
testRollCursor = (testRollCursor + 1) % testNotes.size
|
||||
}
|
||||
// advance every tick
|
||||
audioBank.sendMessage(testNotes[testRollCursor])
|
||||
testRollCursor = (testRollCursor + 1) % testNotes.size
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
companion object {
|
||||
@Transient val testNotes =
|
||||
prel(24,28,31,36,40) +
|
||||
prel(24,26,33,38,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) +
|
||||
prel(14,21,26,30,36) +
|
||||
prel(19,23,26,31,35) +
|
||||
prel(19,22,28,31,37) +
|
||||
prel(17,21,26,33,38) +
|
||||
prel(17,20,26,29,35) +
|
||||
prel(16,19,24,31,36) +
|
||||
prel(16,17,21,24,29) +
|
||||
prel(14,17,21,24,29) +
|
||||
prel( 7,14,19,23,29) +
|
||||
prel(12,16,19,24,28) +
|
||||
prel(12,19,22,24,28) +
|
||||
prel( 5,17,21,24,28) +
|
||||
prel( 6,12,21,24,27) +
|
||||
prel( 8,17,23,24,26) +
|
||||
prel( 7,17,19,23,26) +
|
||||
prel( 7,16,19,24,28) +
|
||||
prel( 7,14,19,24,29) +
|
||||
prel( 7,14,19,23,29) +
|
||||
prel( 7,15,21,24,30) +
|
||||
prel( 7,16,19,24,31) +
|
||||
prel( 7,14,19,24,29) +
|
||||
prel( 7,14,19,23,29) +
|
||||
prel( 0,12,19,22,28) +
|
||||
end1( 0,12,17,21,24,29,21,17,14) +
|
||||
end2( 0,11,31,35,38,41,26,29,28) +
|
||||
end3( 0,12,28,31,36)
|
||||
@Transient private val TICK_DIVISOR = 10
|
||||
|
||||
@Transient val testNotes = List(16*TICK_DIVISOR) { 0L } +
|
||||
prel(24,28,31,36,40) +
|
||||
prel(24,26,33,38,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) +
|
||||
prel(14,21,26,30,36) +
|
||||
prel(19,23,26,31,35) +
|
||||
prel(19,22,28,31,37) +
|
||||
prel(17,21,26,33,38) +
|
||||
prel(17,20,26,29,35) +
|
||||
prel(16,19,24,31,36) +
|
||||
prel(16,17,21,24,29) +
|
||||
prel(14,17,21,24,29) +
|
||||
prel( 7,14,19,23,29) +
|
||||
prel(12,16,19,24,28) +
|
||||
prel(12,19,22,24,28) +
|
||||
prel( 5,17,21,24,28) +
|
||||
prel( 6,12,21,24,27) +
|
||||
prel( 8,17,23,24,26) +
|
||||
prel( 7,17,19,23,26) +
|
||||
prel( 7,16,19,24,28) +
|
||||
prel( 7,14,19,24,29) +
|
||||
prel( 7,14,19,23,29) +
|
||||
prel( 7,15,21,24,30) +
|
||||
prel( 7,16,19,24,31) +
|
||||
prel( 7,14,19,24,29) +
|
||||
prel( 7,14,19,23,29) +
|
||||
prel( 0,12,19,22,28) +
|
||||
end1( 0,12,17,21,24,29,21,17,14) +
|
||||
end2( 0,11,31,35,38,41,26,29,28) +
|
||||
end3( 0,12,28,31,36) + List(16*TICK_DIVISOR - 5) { 0L }
|
||||
|
||||
private fun prel(n1: Int, n2: Int, n3: Int, n4: Int, n5: Int): List<Long> {
|
||||
return listOf(
|
||||
return toPianoRoll(
|
||||
1L shl n1, 1L shl n2, 1L shl n3, 1L shl n4, 1L shl n5, 1L shl n3, 1L shl n4, 1L shl n5,
|
||||
1L shl n1, 1L shl n2, 1L shl n3, 1L shl n4, 1L shl n5, 1L shl n3, 1L shl n4, 1L shl n5)
|
||||
}
|
||||
|
||||
private fun end1(n1: Int, n2: Int, n3: Int, n4: Int, n5: Int, n6: Int, n7: Int, n8: Int, n9: Int): List<Long> {
|
||||
return listOf(
|
||||
return toPianoRoll(
|
||||
1L shl n1, 1L shl n2, 1L shl n3, 1L shl n4, 1L shl n5, 1L shl n6, 1L shl n5, 1L shl n4,
|
||||
1L shl n5, 1L shl n7, 1L shl n8, 1L shl n7, 1L shl n8, 1L shl n9, 1L shl n8, 1L shl n9)
|
||||
}
|
||||
|
||||
private fun end2(n1: Int, n2: Int, n3: Int, n4: Int, n5: Int, n6: Int, n7: Int, n8: Int, n9: Int): List<Long> {
|
||||
return listOf(
|
||||
return toPianoRoll(
|
||||
1L shl n1, 1L shl n2, 1L shl n3, 1L shl n4, 1L shl n5, 1L shl n6, 1L shl n5, 1L shl n4,
|
||||
1L shl n5, 1L shl n4, 1L shl n3, 1L shl n4, 1L shl n7, 1L shl n8, 1L shl n9, 1L shl n7)
|
||||
}
|
||||
|
||||
private fun end3(vararg ns: Int): List<Long> {
|
||||
return listOf(ns.map { 1L shl it }.fold(0L) { acc, note -> acc or note }) + List(15) { 0L }
|
||||
return ns.map { 1L shl it } // arpeggiate
|
||||
}
|
||||
|
||||
private fun toPianoRoll(vararg notes: Long) = List<Long>(notes.size * TICK_DIVISOR) {
|
||||
if (it % TICK_DIVISOR == 0) notes[it / TICK_DIVISOR] else 0
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Reference in New Issue
Block a user