Open-source multiplayer game server compatible with the RuneScape client
https://www.openrs2.org/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
557 lines
24 KiB
557 lines
24 KiB
package org.openrs2.cache.midi
|
|
|
|
import io.netty.buffer.ByteBuf
|
|
import io.netty.buffer.ByteBufAllocator
|
|
import org.openrs2.buffer.readVarInt
|
|
import org.openrs2.buffer.writeVarInt
|
|
import javax.sound.midi.MetaMessage
|
|
import javax.sound.midi.MidiEvent
|
|
import javax.sound.midi.Sequence
|
|
import javax.sound.midi.ShortMessage
|
|
|
|
public object Song {
|
|
private const val NOTE_ON = 0
|
|
private const val NOTE_OFF = 1
|
|
private const val CONTROL_CHANGE = 2
|
|
private const val PITCH_WHEEL_CHANGE = 3
|
|
private const val CHANNEL_PRESSURE_CHANGE = 4
|
|
private const val KEY_PRESSURE_CHANGE = 5
|
|
private const val PROGRAM_CHANGE = 6
|
|
private const val END_OF_TRACK = 7
|
|
private const val SET_TEMPO = 23
|
|
|
|
private const val BANK_SELECT_MSB = 0
|
|
private const val BANK_SELECT_LSB = 32
|
|
private const val MODULATION_WHEEL_MSB = 1
|
|
private const val MODULATION_WHEEL_LSB = 33
|
|
private const val CHANNEL_VOLUME_MSB = 7
|
|
private const val CHANNEL_VOLUME_LSB = 39
|
|
private const val PAN_MSB = 10
|
|
private const val PAN_LSB = 42
|
|
private const val NON_REGISTERED_MSB = 99
|
|
private const val NON_REGISTERED_LSB = 98
|
|
private const val REGISTERED_MSB = 101
|
|
private const val REGISTERED_LSB = 100
|
|
private const val DAMPER = 64
|
|
private const val PORTAMENTO = 65
|
|
private const val ALL_SOUND_OFF = 120
|
|
private const val RESET_CONTROLLERS = 121
|
|
private const val ALL_NOTES_OFF = 123
|
|
|
|
private const val META_END_OF_TRACK = 47
|
|
private const val META_SET_TEMPO = 81
|
|
|
|
private const val CONTROLLERS = 128
|
|
|
|
public fun read(buf: ByteBuf): Sequence {
|
|
buf.markReaderIndex()
|
|
|
|
val tracks = buf.getUnsignedByte(buf.writerIndex() - 3).toInt()
|
|
val division = buf.getUnsignedShort(buf.writerIndex() - 2)
|
|
|
|
if (division and 0x8000 != 0) {
|
|
throw IllegalArgumentException("SMPTE unsupported")
|
|
}
|
|
|
|
val sequence = Sequence(Sequence.PPQ, division and 0x7FFF)
|
|
|
|
var events = 0
|
|
var tempoChanges = 0
|
|
var noteOnEvents = 0
|
|
var noteOffEvents = 0
|
|
var controllerEvents = 0
|
|
var pitchWheelEvents = 0
|
|
var channelPressureEvents = 0
|
|
var keyPressureEvents = 0
|
|
var bankSelectEvents = 0
|
|
|
|
for (i in 0 until tracks) {
|
|
while (true) {
|
|
events++
|
|
|
|
val statusAndChannel = buf.readUnsignedByte().toInt()
|
|
if (statusAndChannel == END_OF_TRACK) {
|
|
break
|
|
} else if (statusAndChannel == SET_TEMPO) {
|
|
tempoChanges++
|
|
continue
|
|
}
|
|
|
|
when (val status = statusAndChannel and 0xF) {
|
|
NOTE_ON -> noteOnEvents++
|
|
NOTE_OFF -> noteOffEvents++
|
|
CONTROL_CHANGE -> controllerEvents++
|
|
PITCH_WHEEL_CHANGE -> pitchWheelEvents++
|
|
CHANNEL_PRESSURE_CHANGE -> channelPressureEvents++
|
|
KEY_PRESSURE_CHANGE -> keyPressureEvents++
|
|
PROGRAM_CHANGE -> bankSelectEvents++
|
|
else -> throw IllegalArgumentException("Unsupported status: $status")
|
|
}
|
|
}
|
|
}
|
|
|
|
val deltaTimeBuf = buf.slice()
|
|
for (i in 0 until events) {
|
|
buf.readVarInt()
|
|
}
|
|
|
|
var modulationWheelMsbEvents = 0
|
|
var modulationWheelLsbEvents = 0
|
|
var channelVolumeMsbEvents = 0
|
|
var channelVolumeLsbEvents = 0
|
|
var panMsbEvents = 0
|
|
var panLsbEvents = 0
|
|
var nonRegisteredMsbEvents = 0
|
|
var nonRegisteredLsbEvents = 0
|
|
var registeredMsbEvents = 0
|
|
var registeredLsbEvents = 0
|
|
var otherKnownControllerEvents = 0
|
|
var unknownControllerEvents = 0
|
|
|
|
val controllerBuf = buf.slice()
|
|
|
|
var controller = 0
|
|
for (i in 0 until controllerEvents) {
|
|
controller = (controller + buf.readUnsignedByte()) and 0x7F
|
|
|
|
when (controller) {
|
|
BANK_SELECT_MSB, BANK_SELECT_LSB -> bankSelectEvents++
|
|
MODULATION_WHEEL_MSB -> modulationWheelMsbEvents++
|
|
MODULATION_WHEEL_LSB -> modulationWheelLsbEvents++
|
|
CHANNEL_VOLUME_MSB -> channelVolumeMsbEvents++
|
|
CHANNEL_VOLUME_LSB -> channelVolumeLsbEvents++
|
|
PAN_MSB -> panMsbEvents++
|
|
PAN_LSB -> panLsbEvents++
|
|
NON_REGISTERED_MSB -> nonRegisteredMsbEvents++
|
|
NON_REGISTERED_LSB -> nonRegisteredLsbEvents++
|
|
REGISTERED_MSB -> registeredMsbEvents++
|
|
REGISTERED_LSB -> registeredLsbEvents++
|
|
DAMPER, PORTAMENTO, ALL_SOUND_OFF, RESET_CONTROLLERS, ALL_NOTES_OFF -> otherKnownControllerEvents++
|
|
else -> unknownControllerEvents++
|
|
}
|
|
}
|
|
|
|
val otherKnownControllerBuf = buf.readSlice(otherKnownControllerEvents)
|
|
val keyPressureBuf = buf.readSlice(keyPressureEvents)
|
|
val channelPressureBuf = buf.readSlice(channelPressureEvents)
|
|
val pitchWheelMsbBuf = buf.readSlice(pitchWheelEvents)
|
|
val modulationWheelMsbBuf = buf.readSlice(modulationWheelMsbEvents)
|
|
val channelVolumeMsbBuf = buf.readSlice(channelVolumeMsbEvents)
|
|
val panMsbBuf = buf.readSlice(panMsbEvents)
|
|
val keyBuf = buf.readSlice(noteOnEvents + noteOffEvents + keyPressureEvents)
|
|
val onVelocityBuf = buf.readSlice(noteOnEvents)
|
|
val unknownControllerBuf = buf.readSlice(unknownControllerEvents)
|
|
val offVelocityBuf = buf.readSlice(noteOffEvents)
|
|
val modulationWheelLsbBuf = buf.readSlice(modulationWheelLsbEvents)
|
|
val channelVolumeLsbBuf = buf.readSlice(channelVolumeLsbEvents)
|
|
val panLsbBuf = buf.readSlice(panLsbEvents)
|
|
val bankSelectBuf = buf.readSlice(bankSelectEvents)
|
|
val pitchWheelLsbBuf = buf.readSlice(pitchWheelEvents)
|
|
val nonRegisteredMsbBuf = buf.readSlice(nonRegisteredMsbEvents)
|
|
val nonRegisteredLsbBuf = buf.readSlice(nonRegisteredLsbEvents)
|
|
val registeredMsbBuf = buf.readSlice(registeredMsbEvents)
|
|
val registeredLsbBuf = buf.readSlice(registeredLsbEvents)
|
|
val tempoBuf = buf.readSlice(tempoChanges * 3)
|
|
|
|
// check only the three trailer bytes are remaining
|
|
assert(buf.readableBytes() == 3)
|
|
|
|
buf.resetReaderIndex()
|
|
|
|
var channel = 0
|
|
var key = 0
|
|
var onVelocity = 0
|
|
var offVelocity = 0
|
|
controller = 0
|
|
val values = IntArray(CONTROLLERS)
|
|
var pitchWheel = 0
|
|
var channelPressure = 0
|
|
var keyPressure = 0
|
|
|
|
for (i in 0 until tracks) {
|
|
val track = sequence.createTrack()
|
|
|
|
var time = 0L
|
|
|
|
while (true) {
|
|
time += deltaTimeBuf.readVarInt()
|
|
|
|
val statusAndChannel = buf.readUnsignedByte().toInt()
|
|
if (statusAndChannel == END_OF_TRACK) {
|
|
track.add(MidiEvent(MetaMessage(META_END_OF_TRACK, null, 0), time))
|
|
break
|
|
} else if (statusAndChannel == SET_TEMPO) {
|
|
val tempo = ByteArray(3)
|
|
tempoBuf.readBytes(tempo)
|
|
track.add(MidiEvent(MetaMessage(META_SET_TEMPO, tempo, tempo.size), time))
|
|
continue
|
|
}
|
|
|
|
val status = statusAndChannel and 0xF
|
|
channel = channel xor (statusAndChannel shr 4)
|
|
|
|
val message = when (status) {
|
|
NOTE_ON -> {
|
|
key = (key + keyBuf.readUnsignedByte().toInt()) and 0x7F
|
|
onVelocity = (onVelocity + onVelocityBuf.readUnsignedByte().toInt()) and 0x7F
|
|
ShortMessage(ShortMessage.NOTE_ON, channel, key, onVelocity)
|
|
}
|
|
|
|
NOTE_OFF -> {
|
|
key = (key + keyBuf.readUnsignedByte().toInt()) and 0x7F
|
|
offVelocity = (offVelocity + offVelocityBuf.readUnsignedByte().toInt()) and 0x7F
|
|
ShortMessage(ShortMessage.NOTE_OFF, channel, key, offVelocity)
|
|
}
|
|
|
|
CONTROL_CHANGE -> {
|
|
controller = (controller + controllerBuf.readUnsignedByte()) and 0x7F
|
|
|
|
val valueDelta = when (controller) {
|
|
BANK_SELECT_MSB, BANK_SELECT_LSB -> bankSelectBuf.readUnsignedByte().toInt()
|
|
MODULATION_WHEEL_MSB -> modulationWheelMsbBuf.readUnsignedByte().toInt()
|
|
MODULATION_WHEEL_LSB -> modulationWheelLsbBuf.readUnsignedByte().toInt()
|
|
CHANNEL_VOLUME_MSB -> channelVolumeMsbBuf.readUnsignedByte().toInt()
|
|
CHANNEL_VOLUME_LSB -> channelVolumeLsbBuf.readUnsignedByte().toInt()
|
|
PAN_MSB -> panMsbBuf.readUnsignedByte().toInt()
|
|
PAN_LSB -> panLsbBuf.readUnsignedByte().toInt()
|
|
NON_REGISTERED_MSB -> nonRegisteredMsbBuf.readUnsignedByte().toInt()
|
|
NON_REGISTERED_LSB -> nonRegisteredLsbBuf.readUnsignedByte().toInt()
|
|
REGISTERED_MSB -> registeredMsbBuf.readUnsignedByte().toInt()
|
|
REGISTERED_LSB -> registeredLsbBuf.readUnsignedByte().toInt()
|
|
DAMPER, PORTAMENTO, ALL_SOUND_OFF, RESET_CONTROLLERS, ALL_NOTES_OFF ->
|
|
otherKnownControllerBuf.readUnsignedByte().toInt()
|
|
|
|
else -> unknownControllerBuf.readUnsignedByte().toInt()
|
|
}
|
|
|
|
val value = values[controller] + valueDelta
|
|
values[controller] = value
|
|
ShortMessage(ShortMessage.CONTROL_CHANGE, channel, controller, value and 0x7F)
|
|
}
|
|
|
|
PITCH_WHEEL_CHANGE -> {
|
|
pitchWheel += pitchWheelLsbBuf.readUnsignedByte().toInt()
|
|
pitchWheel += (pitchWheelMsbBuf.readUnsignedByte().toInt() shl 7)
|
|
pitchWheel = pitchWheel and 0x3FFF
|
|
ShortMessage(ShortMessage.PITCH_BEND, channel, pitchWheel and 0x7F, pitchWheel shr 7)
|
|
}
|
|
|
|
CHANNEL_PRESSURE_CHANGE -> {
|
|
channelPressure = (channelPressure + channelPressureBuf.readUnsignedByte().toInt()) and 0x7F
|
|
ShortMessage(ShortMessage.CHANNEL_PRESSURE, channel, channelPressure, 0)
|
|
}
|
|
|
|
KEY_PRESSURE_CHANGE -> {
|
|
key = (key + keyBuf.readUnsignedByte().toInt()) and 0x7F
|
|
keyPressure = (keyPressure + keyPressureBuf.readUnsignedByte().toInt()) and 0x7F
|
|
ShortMessage(ShortMessage.POLY_PRESSURE, channel, key, keyPressure)
|
|
}
|
|
|
|
PROGRAM_CHANGE -> {
|
|
val bankSelect = bankSelectBuf.readUnsignedByte().toInt()
|
|
ShortMessage(ShortMessage.PROGRAM_CHANGE, channel, bankSelect, 0)
|
|
}
|
|
|
|
else -> throw IllegalStateException()
|
|
}
|
|
|
|
track.add(MidiEvent(message, time))
|
|
}
|
|
}
|
|
|
|
// we've consumed the entire buf (checked by an assertion above)
|
|
buf.readerIndex(buf.writerIndex())
|
|
|
|
return sequence
|
|
}
|
|
|
|
public fun write(sequence: Sequence, buf: ByteBuf) {
|
|
if (sequence.divisionType != Sequence.PPQ) {
|
|
throw IllegalArgumentException("SMPTE unsupported")
|
|
}
|
|
|
|
val buffers = Buffers.alloc(buf.alloc())
|
|
try {
|
|
val deltaTimeBuf = buffers.deltaTimeBuf
|
|
val controllerBuf = buffers.controllerBuf
|
|
val otherKnownControllerBuf = buffers.otherKnownControllerBuf
|
|
val keyPressureBuf = buffers.keyPressureBuf
|
|
val channelPressureBuf = buffers.channelPressureBuf
|
|
val pitchWheelMsbBuf = buffers.pitchWheelMsbBuf
|
|
val modulationWheelMsbBuf = buffers.modulationWheelMsbBuf
|
|
val channelVolumeMsbBuf = buffers.channelVolumeMsbBuf
|
|
val panMsbBuf = buffers.panMsbBuf
|
|
val keyBuf = buffers.keyBuf
|
|
val onVelocityBuf = buffers.onVelocityBuf
|
|
val unknownControllerBuf = buffers.unknownControllerBuf
|
|
val offVelocityBuf = buffers.offVelocityBuf
|
|
val modulationWheelLsbBuf = buffers.modulationWheelLsbBuf
|
|
val channelVolumeLsbBuf = buffers.channelVolumeLsbBuf
|
|
val panLsbBuf = buffers.panLsbBuf
|
|
val bankSelectBuf = buffers.bankSelectBuf
|
|
val pitchWheelLsbBuf = buffers.pitchWheelLsbBuf
|
|
val nonRegisteredMsbBuf = buffers.nonRegisteredMsbBuf
|
|
val nonRegisteredLsbBuf = buffers.nonRegisteredLsbBuf
|
|
val registeredMsbBuf = buffers.nonRegisteredMsbBuf
|
|
val registeredLsbBuf = buffers.nonRegisteredLsbBuf
|
|
val tempoBuf = buffers.tempoBuf
|
|
|
|
var prevChannel = 0
|
|
var prevKey = 0
|
|
var prevOnVelocity = 0
|
|
var prevOffVelocity = 0
|
|
var prevController = 0
|
|
var prevPitchWheel = 0
|
|
var prevChannelPressure = 0
|
|
var prevKeyPressure = 0
|
|
val prevValues = IntArray(CONTROLLERS)
|
|
|
|
for (track in sequence.tracks) {
|
|
var prevTime = 0L
|
|
|
|
for (i in 0 until track.size()) {
|
|
val event = track[i]
|
|
|
|
val time = event.tick
|
|
deltaTimeBuf.writeVarInt((time - prevTime).toInt())
|
|
prevTime = time
|
|
|
|
when (val message = event.message) {
|
|
is MetaMessage -> {
|
|
when (val type = message.type) {
|
|
META_END_OF_TRACK -> buf.writeByte(END_OF_TRACK)
|
|
META_SET_TEMPO -> {
|
|
buf.writeByte(SET_TEMPO)
|
|
require(message.data.size == 3)
|
|
tempoBuf.writeBytes(message.data)
|
|
}
|
|
|
|
else -> throw IllegalArgumentException("Unsupported meta type: $type")
|
|
}
|
|
}
|
|
|
|
is ShortMessage -> {
|
|
val command = message.status and 0xF0
|
|
val channel = message.status and 0xF
|
|
|
|
val status = when (command) {
|
|
ShortMessage.NOTE_ON -> NOTE_ON
|
|
ShortMessage.NOTE_OFF -> NOTE_OFF
|
|
ShortMessage.CONTROL_CHANGE -> CONTROL_CHANGE
|
|
ShortMessage.PITCH_BEND -> PITCH_WHEEL_CHANGE
|
|
ShortMessage.CHANNEL_PRESSURE -> CHANNEL_PRESSURE_CHANGE
|
|
ShortMessage.POLY_PRESSURE -> KEY_PRESSURE_CHANGE
|
|
ShortMessage.PROGRAM_CHANGE -> PROGRAM_CHANGE
|
|
else -> throw IllegalArgumentException("Unsupported command: $command")
|
|
}
|
|
|
|
buf.writeByte(((channel xor prevChannel) shl 4) or status)
|
|
prevChannel = channel
|
|
|
|
if (
|
|
command == ShortMessage.NOTE_ON ||
|
|
command == ShortMessage.NOTE_OFF ||
|
|
command == ShortMessage.POLY_PRESSURE
|
|
) {
|
|
val key = message.data1
|
|
keyBuf.writeByte((key - prevKey) and 0x7F)
|
|
prevKey = key
|
|
}
|
|
|
|
when (command) {
|
|
ShortMessage.NOTE_ON -> {
|
|
val onVelocity = message.data2
|
|
onVelocityBuf.writeByte((onVelocity - prevOnVelocity) and 0x7F)
|
|
prevOnVelocity = onVelocity
|
|
}
|
|
|
|
ShortMessage.NOTE_OFF -> {
|
|
val offVelocity = message.data2
|
|
offVelocityBuf.writeByte((offVelocity - prevOffVelocity) and 0x7F)
|
|
prevOffVelocity = offVelocity
|
|
}
|
|
|
|
ShortMessage.CONTROL_CHANGE -> {
|
|
val controller = message.data1
|
|
controllerBuf.writeByte((controller - prevController) and 0x7F)
|
|
prevController = controller
|
|
|
|
val value = message.data2
|
|
val valueDelta = (value - prevValues[controller]) and 0x7F
|
|
|
|
when (controller) {
|
|
BANK_SELECT_MSB, BANK_SELECT_LSB -> bankSelectBuf.writeByte(valueDelta)
|
|
MODULATION_WHEEL_MSB -> modulationWheelMsbBuf.writeByte(valueDelta)
|
|
MODULATION_WHEEL_LSB -> modulationWheelLsbBuf.writeByte(valueDelta)
|
|
CHANNEL_VOLUME_MSB -> channelVolumeMsbBuf.writeByte(valueDelta)
|
|
CHANNEL_VOLUME_LSB -> channelVolumeLsbBuf.writeByte(valueDelta)
|
|
PAN_MSB -> panMsbBuf.writeByte(valueDelta)
|
|
PAN_LSB -> panLsbBuf.writeByte(valueDelta)
|
|
NON_REGISTERED_MSB -> nonRegisteredMsbBuf.writeByte(valueDelta)
|
|
NON_REGISTERED_LSB -> nonRegisteredLsbBuf.writeByte(valueDelta)
|
|
REGISTERED_MSB -> registeredMsbBuf.writeByte(valueDelta)
|
|
REGISTERED_LSB -> registeredLsbBuf.writeByte(valueDelta)
|
|
DAMPER, PORTAMENTO, ALL_SOUND_OFF, RESET_CONTROLLERS, ALL_NOTES_OFF ->
|
|
otherKnownControllerBuf.writeByte(valueDelta)
|
|
|
|
else -> unknownControllerBuf.writeByte(valueDelta)
|
|
}
|
|
|
|
prevValues[controller] = value
|
|
}
|
|
|
|
ShortMessage.PITCH_BEND -> {
|
|
val pitchWheel = message.data1 or (message.data2 shl 7)
|
|
val pitchWheelDelta = (pitchWheel - prevPitchWheel) and 0x3FFF
|
|
pitchWheelLsbBuf.writeByte(pitchWheelDelta and 0x7F)
|
|
pitchWheelMsbBuf.writeByte(pitchWheelDelta shr 7)
|
|
prevPitchWheel = pitchWheel
|
|
}
|
|
|
|
ShortMessage.CHANNEL_PRESSURE -> {
|
|
val channelPressure = message.data1
|
|
channelPressureBuf.writeByte((channelPressure - prevChannelPressure) and 0x7F)
|
|
prevChannelPressure = channelPressure
|
|
}
|
|
|
|
ShortMessage.POLY_PRESSURE -> {
|
|
val keyPressure = message.data2
|
|
keyPressureBuf.writeByte((keyPressure - prevKeyPressure) and 0x7F)
|
|
prevKeyPressure = keyPressure
|
|
}
|
|
|
|
ShortMessage.PROGRAM_CHANGE -> {
|
|
bankSelectBuf.writeByte(message.data1)
|
|
}
|
|
|
|
else -> throw IllegalStateException()
|
|
}
|
|
}
|
|
|
|
else -> throw IllegalArgumentException("Unsupported message type: ${message.javaClass.name}")
|
|
}
|
|
}
|
|
}
|
|
|
|
buf.writeBytes(deltaTimeBuf)
|
|
buf.writeBytes(controllerBuf)
|
|
buf.writeBytes(otherKnownControllerBuf)
|
|
buf.writeBytes(keyPressureBuf)
|
|
buf.writeBytes(channelPressureBuf)
|
|
buf.writeBytes(pitchWheelMsbBuf)
|
|
buf.writeBytes(modulationWheelMsbBuf)
|
|
buf.writeBytes(channelVolumeMsbBuf)
|
|
buf.writeBytes(panMsbBuf)
|
|
buf.writeBytes(keyBuf)
|
|
buf.writeBytes(onVelocityBuf)
|
|
buf.writeBytes(unknownControllerBuf)
|
|
buf.writeBytes(offVelocityBuf)
|
|
buf.writeBytes(modulationWheelLsbBuf)
|
|
buf.writeBytes(channelVolumeLsbBuf)
|
|
buf.writeBytes(panLsbBuf)
|
|
buf.writeBytes(bankSelectBuf)
|
|
buf.writeBytes(pitchWheelLsbBuf)
|
|
buf.writeBytes(nonRegisteredMsbBuf)
|
|
buf.writeBytes(nonRegisteredLsbBuf)
|
|
buf.writeBytes(registeredMsbBuf)
|
|
buf.writeBytes(registeredLsbBuf)
|
|
buf.writeBytes(tempoBuf)
|
|
} finally {
|
|
buffers.release()
|
|
}
|
|
|
|
buf.writeByte(sequence.tracks.size)
|
|
buf.writeShort(sequence.resolution and 0x7FFF)
|
|
}
|
|
|
|
private class Buffers private constructor(
|
|
val deltaTimeBuf: ByteBuf,
|
|
val controllerBuf: ByteBuf,
|
|
val otherKnownControllerBuf: ByteBuf,
|
|
val keyPressureBuf: ByteBuf,
|
|
val channelPressureBuf: ByteBuf,
|
|
val pitchWheelMsbBuf: ByteBuf,
|
|
val modulationWheelMsbBuf: ByteBuf,
|
|
val channelVolumeMsbBuf: ByteBuf,
|
|
val panMsbBuf: ByteBuf,
|
|
val keyBuf: ByteBuf,
|
|
val onVelocityBuf: ByteBuf,
|
|
val unknownControllerBuf: ByteBuf,
|
|
val offVelocityBuf: ByteBuf,
|
|
val modulationWheelLsbBuf: ByteBuf,
|
|
val channelVolumeLsbBuf: ByteBuf,
|
|
val panLsbBuf: ByteBuf,
|
|
val bankSelectBuf: ByteBuf,
|
|
val pitchWheelLsbBuf: ByteBuf,
|
|
val nonRegisteredMsbBuf: ByteBuf,
|
|
val nonRegisteredLsbBuf: ByteBuf,
|
|
val registeredMsbBuf: ByteBuf,
|
|
val registeredLsbBuf: ByteBuf,
|
|
val tempoBuf: ByteBuf
|
|
) {
|
|
fun release() {
|
|
deltaTimeBuf.release()
|
|
controllerBuf.release()
|
|
otherKnownControllerBuf.release()
|
|
keyPressureBuf.release()
|
|
channelPressureBuf.release()
|
|
pitchWheelMsbBuf.release()
|
|
modulationWheelMsbBuf.release()
|
|
channelVolumeMsbBuf.release()
|
|
panMsbBuf.release()
|
|
keyBuf.release()
|
|
onVelocityBuf.release()
|
|
unknownControllerBuf.release()
|
|
offVelocityBuf.release()
|
|
modulationWheelLsbBuf.release()
|
|
channelVolumeLsbBuf.release()
|
|
panLsbBuf.release()
|
|
bankSelectBuf.release()
|
|
pitchWheelLsbBuf.release()
|
|
nonRegisteredMsbBuf.release()
|
|
nonRegisteredLsbBuf.release()
|
|
registeredMsbBuf.release()
|
|
registeredLsbBuf.release()
|
|
tempoBuf.release()
|
|
}
|
|
|
|
companion object {
|
|
fun alloc(alloc: ByteBufAllocator): Buffers {
|
|
val bufs = mutableListOf<ByteBuf>()
|
|
try {
|
|
for (i in 0..22) {
|
|
bufs += alloc.buffer()
|
|
}
|
|
|
|
return Buffers(
|
|
bufs[0].retain(),
|
|
bufs[1].retain(),
|
|
bufs[2].retain(),
|
|
bufs[3].retain(),
|
|
bufs[4].retain(),
|
|
bufs[5].retain(),
|
|
bufs[6].retain(),
|
|
bufs[7].retain(),
|
|
bufs[8].retain(),
|
|
bufs[9].retain(),
|
|
bufs[10].retain(),
|
|
bufs[11].retain(),
|
|
bufs[12].retain(),
|
|
bufs[13].retain(),
|
|
bufs[14].retain(),
|
|
bufs[15].retain(),
|
|
bufs[16].retain(),
|
|
bufs[17].retain(),
|
|
bufs[18].retain(),
|
|
bufs[19].retain(),
|
|
bufs[20].retain(),
|
|
bufs[21].retain(),
|
|
bufs[22].retain()
|
|
)
|
|
} finally {
|
|
bufs.forEach(ByteBuf::release)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|