Midi generation on android device, take 2

This commit is contained in:
dotmg 2026-02-16 22:22:24 +01:00
parent 1eb0a25f0f
commit 2cc1f230f4
3 changed files with 25 additions and 22 deletions

View file

@ -20,7 +20,7 @@ actual class MidiWriterKotlin actual constructor(private val fileRepository: Fil
finalNote -= 12 finalNote -= 12
} }
if (lastPitch.size > voiceNumber && lastPitch[voiceNumber] > 0) { if (lastPitch.size > voiceNumber && lastPitch[voiceNumber] > 0) {
sequence.addNote(channel, lastPitch[voiceNumber], tick) sequence.addSequence(channel, lastPitch[voiceNumber], tick)
} }
var finalVelocity = velocity var finalVelocity = velocity
var midiNote = finalNote var midiNote = finalNote
@ -28,7 +28,7 @@ actual class MidiWriterKotlin actual constructor(private val fileRepository: Fil
midiNote = 40 midiNote = 40
finalVelocity = 0 finalVelocity = 0
} }
sequence.addNote(channel, midiNote, tick, 90, finalVelocity) sequence.addSequence(channel, midiNote, tick, 90, finalVelocity)
while(lastPitch.size <= voiceNumber) { while(lastPitch.size <= voiceNumber) {
lastPitch.add(0) lastPitch.add(0)
@ -44,9 +44,7 @@ actual class MidiWriterKotlin actual constructor(private val fileRepository: Fil
} }
} }
actual fun addMetaMessage(type: Int, tick: Int, nbData: Int, metaByteString: String) { actual fun addMetaMessage(type: Int, tick: Int, nbData: Int, metaByteString: String) {
/*val byteArray = metaByteString.toByteArray() sequence.addMeta( type, tick, nbData, metaByteString)
val metaMessage = MetaMessage(type, byteArray, nbData)
track.add(MidiEvent(metaMessage, tick.toLong()))*/
} }
actual fun process(pitches: List<MidiPitch>) { actual fun process(pitches: List<MidiPitch>) {
val lastTick = 0 val lastTick = 0

View file

@ -5,16 +5,11 @@ class MidiSequence(val resolution: Int = 60) {
// Une liste de pistes, où chaque piste est une liste d'octets (ByteArray) // Une liste de pistes, où chaque piste est une liste d'octets (ByteArray)
val tracks = mutableListOf<MutableList<Byte>>() val tracks = mutableListOf<MutableList<Byte>>()
val out: MutableList<Byte> = mutableListOf<Byte>() val out: MutableList<Byte> = mutableListOf<Byte>()
private var lastTick = mutableListOf<Long>() private var lastTick = 0L
fun getDeltaAndSync(channel: Int, currentTick: Long): Long { fun getDeltaAndSync(channel: Int, currentTick: Long): Long {
// Si le canal demandé dépasse la taille actuelle, on remplit de 0L val delta = currentTick - lastTick
while (lastTick.size <= channel) { lastTick = currentTick
lastTick.add(0L)
}
val delta = currentTick - lastTick[channel]
lastTick[channel] = currentTick
return delta return delta
} }
fun createTrack(): MutableList<Byte> { fun createTrack(): MutableList<Byte> {
@ -44,15 +39,11 @@ class MidiSequence(val resolution: Int = 60) {
} }
} }
fun addNote(channel: Int, pitch: Int, currentTick: Long, type: Int = 80, finalVelocity: Int = 80) { fun addSequence(channel: Int, pitch: Int, currentTick: Long, type: Int = 80, finalVelocity: Int = 100) {
while (tracks.size <= channel) { val myTrack = tracks[0]
tracks.add(mutableListOf<Byte>(0))
}
val myTrack = tracks[channel]
myTrack.addNote(channel, pitch, currentTick, type, finalVelocity) myTrack.addNote(channel, pitch, currentTick, type, finalVelocity)
} }
fun MutableList<Byte>.addNote(channel: Int, pitch: Int, currentTick: Long, type: Int = 80, finalVelocity: Int = 80) { fun MutableList<Byte>.addNote(channel: Int, pitch: Int, currentTick: Long, type: Int = 80, finalVelocity: Int = 100) {
// Calcul du Delta-Time // Calcul du Delta-Time
val delta = getDeltaAndSync(channel, currentTick) val delta = getDeltaAndSync(channel, currentTick)
@ -92,7 +83,7 @@ class MidiSequence(val resolution: Int = 60) {
out.write16Bit(1) out.write16Bit(1)
// 4. Nombre de pistes (16 bits) // 4. Nombre de pistes (16 bits)
out.write16Bit(trackCount) // trackCount = 4 is wrong, why? out.write16Bit(trackCount)
// 5. Division / Résolution (16 bits) // 5. Division / Résolution (16 bits)
// Ticks par noire (votre variable 'resolution') // Ticks par noire (votre variable 'resolution')
@ -125,4 +116,19 @@ class MidiSequence(val resolution: Int = 60) {
writeTrackChunk( track) writeTrackChunk( track)
} }
} }
fun addMeta(type: Int, tick: Int, nbData: Int, metaByteString: String) {
val data = metaByteString.encodeToByteArray()
if (tracks.isEmpty()) {
tracks.add(mutableListOf<Byte>(0))
}
val outTrack = tracks[0]
// Un Meta Message commence toujours par FF, puis le type, puis la longueur
outTrack.add(0x00.toByte()) // Status byte
outTrack.add(0xFF.toByte()) // Status byte
outTrack.add(type.toByte()) // Meta-event type
outTrack.addAll(nbData.toLong().toVLQList())
// Ajout des données
outTrack.addAll(data.toList().take(nbData))
}
} }

View file

@ -10,7 +10,6 @@ actual class MidiWriterKotlin actual constructor(private val fileRepository: Fil
private val sequence = Sequence(Sequence.PPQ, 60) private val sequence = Sequence(Sequence.PPQ, 60)
private val track = sequence.createTrack() private val track = sequence.createTrack()
private var tick: Long = 0 private var tick: Long = 0
//private var nextTick: MidiPitch<Int> = mutableListOf()
private var nextTick: MutableList<MidiPitch> = mutableListOf() private var nextTick: MutableList<MidiPitch> = mutableListOf()
private val noteOn = ShortMessage() private val noteOn = ShortMessage()
private val noteOff = ShortMessage() private val noteOff = ShortMessage()