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))
+ }
+
+}