Add MidiMessageHandler for MIDI event handling
Introduced `MidiMessageHandler` to process and handle MIDI messages with customizable handlers for specific byte patterns. This addition improves extensibility and keeps MIDI message processing modular and organized.
This commit is contained in:
@@ -0,0 +1,82 @@
|
|||||||
|
package nl.astraeus.vst.midi
|
||||||
|
|
||||||
|
typealias MidiHandler = (Byte, Byte, Byte) -> Unit
|
||||||
|
|
||||||
|
val Byte.channel: Byte
|
||||||
|
get() {
|
||||||
|
return (this.toInt() and 0x0F).toByte()
|
||||||
|
}
|
||||||
|
|
||||||
|
val Byte.command: Byte
|
||||||
|
get() {
|
||||||
|
return ((this.toInt() and 0xF0) shr 4).toByte()
|
||||||
|
}
|
||||||
|
|
||||||
|
val Byte.channelCommand: Boolean
|
||||||
|
get() {
|
||||||
|
return this.command >= 8 && this.command <= 13
|
||||||
|
}
|
||||||
|
|
||||||
|
class MidiMessageHandler(
|
||||||
|
var channel: Byte = -1
|
||||||
|
) {
|
||||||
|
val singleByteHandlers = mutableMapOf<Byte, MidiHandler>()
|
||||||
|
val doubleByteHandlers = mutableMapOf<Byte, MutableMap<Byte, MidiHandler>>()
|
||||||
|
|
||||||
|
fun addHandler(
|
||||||
|
byte1: Byte,
|
||||||
|
byte2: Byte = 0,
|
||||||
|
handler: MidiHandler
|
||||||
|
) {
|
||||||
|
val b1 = if (byte1.channelCommand) {
|
||||||
|
(byte1.toInt() and 0xF0).toByte()
|
||||||
|
} else {
|
||||||
|
byte1
|
||||||
|
}
|
||||||
|
if (byte2 == 0.toByte()) {
|
||||||
|
singleByteHandlers[b1] = handler
|
||||||
|
} else {
|
||||||
|
val map = doubleByteHandlers.getOrPut(b1) {
|
||||||
|
mutableMapOf()
|
||||||
|
}
|
||||||
|
map[byte2] = handler
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addHandler(
|
||||||
|
byte1: Int,
|
||||||
|
byte2: Int = 0,
|
||||||
|
handler: MidiHandler
|
||||||
|
) = addHandler(
|
||||||
|
byte1.toByte(),
|
||||||
|
byte2.toByte(),
|
||||||
|
handler
|
||||||
|
)
|
||||||
|
|
||||||
|
fun handle(
|
||||||
|
byte1: Byte,
|
||||||
|
byte2: Byte,
|
||||||
|
byte3: Byte
|
||||||
|
) {
|
||||||
|
if (
|
||||||
|
channel < 0 ||
|
||||||
|
!byte1.channelCommand ||
|
||||||
|
(byte1.channelCommand && channel == byte1.channel)
|
||||||
|
) {
|
||||||
|
val b1 = if (byte1.channelCommand) {
|
||||||
|
(byte1.toInt() and 0xF0).toByte()
|
||||||
|
} else {
|
||||||
|
byte1
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doubleByteHandlers.containsKey(b1)) {
|
||||||
|
doubleByteHandlers[b1]?.get(byte2)?.invoke(byte1, byte2, byte3)
|
||||||
|
} else if (singleByteHandlers.containsKey(b1)) {
|
||||||
|
singleByteHandlers[b1]?.invoke(byte1, byte2, byte3)
|
||||||
|
} else {
|
||||||
|
println("Unhandled message: $byte1 $byte2 $byte3")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user