Fix lack of placed rests at the very end of MIDI tracks

This commit is contained in:
2020-03-14 18:00:27 +01:00
parent 5dd703682a
commit c5ac06a6f6

View File

@@ -14,13 +14,22 @@ object MidiSequencer {
const val NOTE_OFF = 0x80 const val NOTE_OFF = 0x80
const val NOTE_ON = 0x90 const val NOTE_ON = 0x90
const val PROGRAM_CHANGE = 0xC0 const val PROGRAM_CHANGE = 0xC0
const val CONTROL_CHANGE = 0xB0
}
private object Data1 {
const val ALL_NOTES_OFF = 0x7B
}
private object Data2 {
const val ZERO = 0x00
} }
fun playChannels(channels: Map<Int, List<List<Any>>>, config: Map<String, Any>) { fun playChannels(channels: Map<Int, List<List<Any>>>, config: Map<String, Any>) {
val sequence = Sequence(Sequence.PPQ, PPQ) val sequence = Sequence(Sequence.PPQ, PPQ)
channels.forEach { (channel, lines) -> channels.forEach { (channel, lines) ->
lines.forEach { line -> playLine(line, channel, sequence) } lines.forEach { line -> playLine(line, channel-1, sequence) }
} }
sequencer.sequence = sequence sequencer.sequence = sequence
@@ -48,7 +57,7 @@ object MidiSequencer {
private fun playLine(line: List<Any>, channel: Int, sequence: Sequence) { private fun playLine(line: List<Any>, channel: Int, sequence: Sequence) {
val track = sequence.createTrack() val track = sequence.createTrack()
line.fold(0L) { noteOnTick, item -> val lastTick = line.fold(0L) { noteOnTick, item ->
when (item) { when (item) {
is Note -> { is Note -> {
note(item, channel, noteOnTick, track) note(item, channel, noteOnTick, track)
@@ -58,6 +67,8 @@ object MidiSequencer {
else -> throw ShouldNeverReachThisLineException() else -> throw ShouldNeverReachThisLineException()
} }
} }
track.add(allNotesOff(channel, lastTick))
} }
private fun command(instruction: String, channel: Int, beginTick: Long, track: Track): Long { private fun command(instruction: String, channel: Int, beginTick: Long, track: Track): Long {
@@ -91,6 +102,10 @@ object MidiSequencer {
return event(Command.NOTE_OFF, channel, note.intPitch() + 12, 127, tick) return event(Command.NOTE_OFF, channel, note.intPitch() + 12, 127, tick)
} }
private fun allNotesOff(channel: Int, tick: Long): MidiEvent {
return event(Command.CONTROL_CHANGE, channel, Data1.ALL_NOTES_OFF, Data2.ZERO, tick)
}
private fun event(command: Int, channel: Int, data1: Int, data2: Int, tick: Long): MidiEvent { private fun event(command: Int, channel: Int, data1: Int, data2: Int, tick: Long): MidiEvent {
val message = ShortMessage(command, channel, data1, data2) val message = ShortMessage(command, channel, data1, data2)
return MidiEvent(message, tick) return MidiEvent(message, tick)