From a592e9188205f55edb591544dfe19db23d920fd8 Mon Sep 17 00:00:00 2001 From: rnentjes Date: Mon, 16 Dec 2024 20:13:41 +0100 Subject: [PATCH] Update MIDI message handling and version increment Refactored MIDI message classes to improve modularity and flexibility, introducing separate classes for distinct MIDI message types. Updated `build.gradle.kts` version to `0.2.0` to reflect these changes. Removed `.idea/.name` file as part of cleanup. --- .idea/artifacts/midi_arrays_js_0_1_0.xml | 8 ++ .idea/artifacts/midi_arrays_js_0_2_0.xml | 8 ++ .idea/artifacts/midi_arrays_jvm_0_1_0.xml | 8 ++ .idea/artifacts/midi_arrays_jvm_0_2_0.xml | 8 ++ build.gradle.kts | 20 ++++- .../nl/astraeus/midi/message/MidiMessage.kt | 2 +- .../message/SortedTimedMidiMessageList.kt | 78 +++++++++++++++++++ .../message/SortedTimedMidiMessageListTest.kt | 61 +++++++++++++++ 8 files changed, 188 insertions(+), 5 deletions(-) create mode 100644 .idea/artifacts/midi_arrays_js_0_1_0.xml create mode 100644 .idea/artifacts/midi_arrays_js_0_2_0.xml create mode 100644 .idea/artifacts/midi_arrays_jvm_0_1_0.xml create mode 100644 .idea/artifacts/midi_arrays_jvm_0_2_0.xml create mode 100644 src/commonMain/kotlin/nl/astraeus/midi/message/SortedTimedMidiMessageList.kt create mode 100644 src/commonTest/kotlin/nl/astraeus/midi/message/SortedTimedMidiMessageListTest.kt diff --git a/.idea/artifacts/midi_arrays_js_0_1_0.xml b/.idea/artifacts/midi_arrays_js_0_1_0.xml new file mode 100644 index 0000000..bda9003 --- /dev/null +++ b/.idea/artifacts/midi_arrays_js_0_1_0.xml @@ -0,0 +1,8 @@ + + + $PROJECT_DIR$/build/libs + + + + + \ No newline at end of file diff --git a/.idea/artifacts/midi_arrays_js_0_2_0.xml b/.idea/artifacts/midi_arrays_js_0_2_0.xml new file mode 100644 index 0000000..0df1632 --- /dev/null +++ b/.idea/artifacts/midi_arrays_js_0_2_0.xml @@ -0,0 +1,8 @@ + + + $PROJECT_DIR$/build/libs + + + + + \ No newline at end of file diff --git a/.idea/artifacts/midi_arrays_jvm_0_1_0.xml b/.idea/artifacts/midi_arrays_jvm_0_1_0.xml new file mode 100644 index 0000000..07546db --- /dev/null +++ b/.idea/artifacts/midi_arrays_jvm_0_1_0.xml @@ -0,0 +1,8 @@ + + + $PROJECT_DIR$/build/libs + + + + + \ No newline at end of file diff --git a/.idea/artifacts/midi_arrays_jvm_0_2_0.xml b/.idea/artifacts/midi_arrays_jvm_0_2_0.xml new file mode 100644 index 0000000..5fc2b20 --- /dev/null +++ b/.idea/artifacts/midi_arrays_jvm_0_2_0.xml @@ -0,0 +1,8 @@ + + + $PROJECT_DIR$/build/libs + + + + + \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index f877807..3cff8ec 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ plugins { } group = "nl.astraeus" -version = "0.2.0" +version = "0.3.0" repositories { mavenCentral() @@ -28,11 +28,23 @@ kotlin { api("nl.astraeus:typed-byte-arrays:0.2.6") } } - val commonTest by getting + val commonTest by getting { + dependencies { + implementation(kotlin("test-common")) + } + } val jvmMain by getting - val jvmTest by getting + val jvmTest by getting { + dependencies { + implementation(kotlin("test")) + } + } val jsMain by getting - val jsTest by getting + val jsTest by getting { + dependencies { + implementation(kotlin("test-js")) + } + } } } diff --git a/src/commonMain/kotlin/nl/astraeus/midi/message/MidiMessage.kt b/src/commonMain/kotlin/nl/astraeus/midi/message/MidiMessage.kt index 6ce71d3..ae8c222 100644 --- a/src/commonMain/kotlin/nl/astraeus/midi/message/MidiMessage.kt +++ b/src/commonMain/kotlin/nl/astraeus/midi/message/MidiMessage.kt @@ -50,7 +50,7 @@ class TimedMidiMessage() : MidiMessage( Type("midi", DataType.BLOB, 48), ) { var timeToPlay by double("timeToPlay") - var midi by blob("data") + var midi by blob("midi") init { this.type = MidiMessageTypes.MIDI_DATA.typeId diff --git a/src/commonMain/kotlin/nl/astraeus/midi/message/SortedTimedMidiMessageList.kt b/src/commonMain/kotlin/nl/astraeus/midi/message/SortedTimedMidiMessageList.kt new file mode 100644 index 0000000..bdde88f --- /dev/null +++ b/src/commonMain/kotlin/nl/astraeus/midi/message/SortedTimedMidiMessageList.kt @@ -0,0 +1,78 @@ +package nl.astraeus.midi.message + +class SortedTimedMidiMessageList( + val reservedSize: Int = 1024 +) { + val list = Array(reservedSize) { TimedMidiMessage(0.0) } + var full = false + var readPointer = 0 + var writePointer = 0 + + private fun Int.wrappedAdd(delta:Int): Int = (this + reservedSize + delta) % reservedSize + + fun size(): Int = (writePointer - readPointer + reservedSize) % reservedSize + + fun isEmpty(): Boolean = !full && size() == 0 + + fun isNotEmpty(): Boolean = !isEmpty() + + fun nextTimestamp(): Double? = if (isNotEmpty()) { + list[readPointer].timeToPlay + } else { + null + } + + fun lastTimestamp(): Double? = if (isNotEmpty()) { + val lastPointer = writePointer.wrappedAdd(-1) + list[lastPointer].timeToPlay + } else { + null + } + + fun add(message: TimedMidiMessage) { + check(!full) { + "SortedTimedMidiMessageList is full!" + } + val time = message.timeToPlay + + if (message.timeToPlay < (nextTimestamp() ?: 0.0)) { + readPointer = readPointer.wrappedAdd(-1) + list[readPointer] = message + } else if (message.timeToPlay > (lastTimestamp() ?: 0.0)) { + list[writePointer] = message + writePointer = writePointer.wrappedAdd(1) + } else { + var index = readPointer + + while(index != writePointer && list[index].timeToPlay < time) { + index = index.wrappedAdd(1) + } + if (index == writePointer) { + writePointer = writePointer.wrappedAdd(1) + list[writePointer] = message + } else { + val writePosition = index + while(index != writePointer) { + list[index.wrappedAdd(1)] = list[index] + index = index.wrappedAdd(1) + } + writePointer = writePointer.wrappedAdd(1) + + list[writePosition] = message + } + } + + full = readPointer == writePointer + } + + fun read(): TimedMidiMessage { + check(isNotEmpty()) { + "Can't read from an empty list!" + } + + val message = list[readPointer] + readPointer = readPointer.wrappedAdd(1) + full = false + return message + } +} diff --git a/src/commonTest/kotlin/nl/astraeus/midi/message/SortedTimedMidiMessageListTest.kt b/src/commonTest/kotlin/nl/astraeus/midi/message/SortedTimedMidiMessageListTest.kt new file mode 100644 index 0000000..f51d538 --- /dev/null +++ b/src/commonTest/kotlin/nl/astraeus/midi/message/SortedTimedMidiMessageListTest.kt @@ -0,0 +1,61 @@ +package nl.astraeus.midi.message + +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertFailsWith + +class SortedTimedMidiMessageListTest { + + @Test + fun testInsert() { + val list = SortedTimedMidiMessageList(5) + + list.add(TimedMidiMessage(1.0, 1, 2, 3)) + list.add(TimedMidiMessage(2.0, 2, 3, 4)) + list.add(TimedMidiMessage(1.5, 3, 4, 5)) + list.add(TimedMidiMessage(0.5, 4, 5, 6)) + + assertEquals(0.5, list.nextTimestamp()) + assertEquals(0.5, list.read().timeToPlay) + assertEquals(1.0, list.read().timeToPlay) + assertEquals(1.5, list.read().timeToPlay) + assertEquals(2.0, list.read().timeToPlay) + } + + @Test + fun testEmpty() { + assertFailsWith(IllegalStateException::class) { + val list = SortedTimedMidiMessageList(5) + + list.read() + } + } + + @Test + fun testFull() { + assertFailsWith(IllegalStateException::class) { + val list = SortedTimedMidiMessageList(2) + + list.add(TimedMidiMessage(1.0, 1, 2, 3)) + list.add(TimedMidiMessage(2.0, 2, 3, 4)) + list.add(TimedMidiMessage(1.5, 3, 4, 5)) + } + } + + @Test + fun testFull2() { + val list = SortedTimedMidiMessageList(2) + + list.add(TimedMidiMessage(1.0, 1, 2, 3)) + list.add(TimedMidiMessage(2.0, 2, 3, 4)) + + assertEquals(true, list.full) + + list.read() + + assertEquals(false, list.full) + + list.add(TimedMidiMessage(1.5, 3, 4, 5)) + } + +}