Skip to content

Commit 81fd16c

Browse files
committed
Fixed build
1 parent 242466b commit 81fd16c

File tree

8 files changed

+76
-146
lines changed

8 files changed

+76
-146
lines changed

core/src/androidMain/kotlin/pl/lemanski/mikroSoundFont/generator/Generator.android.kt

Lines changed: 0 additions & 5 deletions
This file was deleted.

core/src/commonMain/kotlin/pl/lemanski/mikroSoundFont/generator/Generator.kt

Lines changed: 0 additions & 8 deletions
This file was deleted.

core/src/commonMain/kotlin/pl/lemanski/mikroSoundFont/io/midi/MidiFileParser.kt

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
package pl.lemanski.mikroSoundFont.io.midi
22

3-
import pl.lemanski.mikroSoundFont.midi.EventType
4-
import pl.lemanski.mikroSoundFont.midi.MidiEvent
3+
import pl.lemanski.mikroSoundFont.getLogger
4+
import pl.lemanski.mikroSoundFont.midi.MidiMessage
5+
import pl.lemanski.mikroSoundFont.midi.MidiMessage.Type
6+
import pl.lemanski.mikroSoundFont.midi.MidiMessageControlChange
7+
import pl.lemanski.mikroSoundFont.midi.MidiMessageNoteOff
8+
import pl.lemanski.mikroSoundFont.midi.MidiMessageNoteOn
9+
import pl.lemanski.mikroSoundFont.midi.MidiMessageProgramChange
510

611
class MidiFileParser {
7-
fun parseMidiFile(data: ByteArray): List<MidiEvent> {
12+
private val logger = getLogger()
13+
14+
fun parseMidiFile(data: ByteArray): List<MidiMessage> {
815
val header = parseMidiHeader(data)
9-
val events = mutableListOf<MidiEvent>()
16+
val events = mutableListOf<MidiMessage>()
1017

1118
var trackStart = 14 // Header ends at byte 14
1219
repeat(header.numTracks) {
@@ -17,7 +24,7 @@ class MidiFileParser {
1724
return events
1825
}
1926

20-
fun readVariableLengthQuantity(data: ByteArray, index: Int): Pair<Int, Int> {
27+
private fun readVariableLengthQuantity(data: ByteArray, index: Int): Pair<Int, Int> {
2128
var value = 0
2229
var i = index
2330
var byte: Int
@@ -31,7 +38,7 @@ class MidiFileParser {
3138
return Pair(value, i)
3239
}
3340

34-
fun parseMidiHeader(data: ByteArray): MidiFileHeader {
41+
private fun parseMidiHeader(data: ByteArray): MidiFileHeader {
3542
val chunkType = data.sliceArray(0..3).map { it.toInt().toChar() }.joinToString("")
3643
if (chunkType != "MThd") throw IllegalArgumentException("Invalid MIDI header")
3744

@@ -42,8 +49,8 @@ class MidiFileParser {
4249
return MidiFileHeader(format, numTracks, division)
4350
}
4451

45-
fun parseTrack(data: ByteArray, trackStart: Int): List<MidiEvent> {
46-
val events = mutableListOf<MidiEvent>()
52+
fun parseTrack(data: ByteArray, trackStart: Int): List<MidiMessage> {
53+
val events = mutableListOf<MidiMessage>()
4754
var index = trackStart + 8 // Skip "MTrk" and track length
4855
var lastStatusByte = 0
4956

@@ -65,26 +72,45 @@ class MidiFileParser {
6572
val command = lastStatusByte and 0xF0
6673
val channel = lastStatusByte and 0x0F
6774

68-
when (command) {
69-
0x90 -> { // Note On
75+
when (command.toType()) {
76+
Type.NOTE_OFF -> {
7077
val key = data[index].toInt() and 0xFF
71-
val velocity = data[index + 1].toInt() and 0xFF
72-
events.add(MidiEvent(deltaTime.toLong(), EventType.NOTE_ON, listOf(channel, key, velocity)))
78+
events.add(MidiMessageNoteOff(deltaTime, channel, key))
7379
index += 2
7480
}
75-
0x80 -> { // Note Off
81+
Type.NOTE_ON -> {
7682
val key = data[index].toInt() and 0xFF
77-
events.add(MidiEvent(deltaTime.toLong(), EventType.NOTE_OFF, listOf(channel, key)))
83+
val velocity = data[index + 1].toInt() and 0xFF
84+
events.add(MidiMessageNoteOn(deltaTime, channel, key, velocity))
7885
index += 2
7986
}
80-
0xC0 -> { // Program Change
87+
Type.PROGRAM_CHANGE -> {
8188
val program = data[index].toInt() and 0xFF
82-
events.add(MidiEvent(deltaTime.toLong(), EventType.PROGRAM_CHANGE, listOf(channel, program)))
89+
events.add(MidiMessageProgramChange(deltaTime, channel, program))
8390
index++
8491
}
85-
// Add more cases for other types of MIDI events
92+
Type.CONTROL_CHANGE -> {
93+
val control = data[index].toInt() and 0xFF
94+
val value = data[index + 1].toInt() and 0xFF
95+
events.add(MidiMessageControlChange(deltaTime, channel, control, value))
96+
index += 2
97+
}
98+
Type.KEY_PRESSURE -> {
99+
logger.log("KEY_PRESSURE")
100+
}
101+
Type.CHANNEL_PRESSURE -> {
102+
logger.log("CHANNEL_PRESSURE")
103+
}
104+
Type.PITCH_BEND -> {
105+
logger.log("PITCH_BEND")
106+
}
107+
Type.SET_TEMPO -> {
108+
logger.log("SET_TEMPO")
109+
}
86110
}
87111
}
88112
return events
89113
}
114+
115+
private fun Int.toType(): Type = Type.entries.find { it.value == this } ?: throw IllegalArgumentException("Unknown MIDI event: $this")
90116
}

core/src/commonMain/kotlin/pl/lemanski/mikroSoundFont/midi/MidiEvent.kt

Lines changed: 0 additions & 14 deletions
This file was deleted.

core/src/commonMain/kotlin/pl/lemanski/mikroSoundFont/generator/MidiMessage.kt renamed to core/src/commonMain/kotlin/pl/lemanski/mikroSoundFont/midi/MidiMessage.kt

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
package pl.lemanski.mikroSoundFont.generator
1+
package pl.lemanski.mikroSoundFont.midi
22

33
sealed interface MidiMessage {
44
val time: Int
55
val channel: Int
66
val type: Type
7-
var next: MidiMessage?
87

98
enum class Type(val value: Int) {
109
NOTE_OFF(0x80),
@@ -25,7 +24,6 @@ data class MidiMessageNoteOn(
2524
override val channel: Int,
2625
val key: Int,
2726
val velocity: Int,
28-
override var next: MidiMessage?,
2927
) : MidiMessage {
3028
override val type: MidiMessage.Type = MidiMessage.Type.NOTE_ON
3129
}
@@ -36,7 +34,6 @@ data class MidiMessageNoteOff(
3634
override val time: Int,
3735
override val channel: Int,
3836
val key: Int,
39-
override var next: MidiMessage?,
4037
) : MidiMessage {
4138
override val type: MidiMessage.Type = MidiMessage.Type.NOTE_OFF
4239
}
@@ -47,7 +44,6 @@ data class MidiMessageProgramChange(
4744
override val time: Int,
4845
override val channel: Int,
4946
val program: Int,
50-
override var next: MidiMessage?,
5147
) : MidiMessage {
5248
override val type: MidiMessage.Type = MidiMessage.Type.PROGRAM_CHANGE
5349
}
@@ -58,7 +54,6 @@ data class MidiMessagePitchBend(
5854
override val time: Int,
5955
override val channel: Int,
6056
val pitchBend: Int,
61-
override var next: MidiMessage?,
6257
) : MidiMessage {
6358
override val type: MidiMessage.Type = MidiMessage.Type.PITCH_BEND
6459
}
@@ -70,7 +65,6 @@ data class MidiMessageControlChange(
7065
override val channel: Int,
7166
val control: Int,
7267
val controlValue: Int,
73-
override var next: MidiMessage?,
7468
): MidiMessage {
7569
override val type: MidiMessage.Type = MidiMessage.Type.CONTROL_CHANGE
7670
}
Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,49 @@
11
package pl.lemanski.mikroSoundFont.midi
22

33
import pl.lemanski.mikroSoundFont.SoundFont
4+
import pl.lemanski.mikroSoundFont.getLogger
45

56
class MidiSequencer(
6-
private val soundFont: SoundFont
7+
private val soundFont: SoundFont,
8+
private val sampleRate: Int,
9+
private val channelCount: Int,
10+
private val sampleBlockSize: Int
711
) {
12+
private val logger = getLogger()
813
private var currentTime = 0L
9-
private val events = mutableListOf<MidiEvent>()
14+
private val events = mutableListOf<MidiMessage>()
1015

11-
fun loadMidiEvents(midiEvents: List<MidiEvent>) {
16+
fun loadMidiEvents(midiEvents: List<MidiMessage>) {
1217
events.clear()
1318
events.addAll(midiEvents)
1419
}
1520

16-
fun play() {
17-
events.forEach { event ->
18-
currentTime += event.deltaTime
19-
handleEvent(event)
20-
}
21-
}
21+
fun generate(midiMessage: MidiMessage): FloatArray {
22+
var currentTime = 0.0
23+
var audioBuffer = FloatArray(0)
24+
val i = events.iterator()
25+
var message: MidiMessage? = if (i.hasNext()) i.next() else return floatArrayOf()
26+
27+
while (i.hasNext()) {
28+
message?.process()
29+
message = i.next()
2230

23-
private fun handleEvent(event: MidiEvent) {
24-
when (event.eventType) {
25-
EventType.NOTE_ON -> soundFont.noteOn(
26-
event.data[0],
27-
event.data[1],
28-
event.data[2] / 127.0f
29-
)
30-
EventType.NOTE_OFF -> soundFont.noteOff(event.data[0], event.data[1])
31-
EventType.PROGRAM_CHANGE -> soundFont.setBankPreset(
32-
0,
33-
event.data[0],
34-
event.data[1]
35-
)
36-
EventType.CONTROL_CHANGE -> handleControlChange(
37-
event.data[0],
38-
event.data[1],
39-
event.data[2]
40-
)
31+
val targetTime = message.time.toDouble()
32+
33+
while (targetTime >= currentTime) {
34+
currentTime += sampleBlockSize * (1000.0 / sampleRate)
35+
audioBuffer += soundFont.renderFloat(sampleBlockSize, false)
36+
}
4137
}
38+
39+
return audioBuffer
4240
}
4341

44-
private fun handleControlChange(controller: Int, value: Int, channel: Int) {
45-
// Handle pitch bends, volume controls, etc.
42+
private fun MidiMessage.process() {
43+
when (this) {
44+
is MidiMessageNoteOff -> soundFont.noteOff(channel, key)
45+
is MidiMessageNoteOn -> soundFont.noteOn(channel, key, velocity / 127.0f)
46+
else -> logger.log("Unknown message type ${type.name}")
47+
}
4648
}
4749
}

core/src/nativeMain/kotlin/pl/lemanski/mikroSoundFont/generator/Generator.native.kt

Lines changed: 0 additions & 65 deletions
This file was deleted.

core/src/nativeMain/kotlin/pl/lemanski/mikroSoundFont/io/File.native.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ actual fun loadFile(path: String): ByteArray {
1212
val file = fopen(path, "r") ?: throw IllegalArgumentException("Could not open file")
1313
try {
1414
fseek(file, 0, SEEK_END)
15-
val fileSize = ftell(file)
15+
val fileSize = ftell(file).toInt()
1616
rewind(file)
1717
val buffer = ByteArray(fileSize)
1818

0 commit comments

Comments
 (0)