Rename application identifier to space.rcmd.android.sizzle
Global rename of the app/package identifier from com.reactorcoremeltdown.sizzletracker to space.rcmd.android.sizzle: - build.gradle.kts: applicationId + namespace. - Move the Kotlin source tree (main + test) and rewrite every package/import. - native_audio.cpp: JNI symbol names (Java_space_rcmd_android_sizzle_...) so the Oboe callback still links against the relocated NativeAudioBridge. - docs: package/file-map header. The desktop-project GitHub URLs (github.com/reactorcoremeltdown/sizzletracker) and the Reactorcoremeltdown copyright/SPDX author identity are intentionally left unchanged. Note: the new applicationId installs as a separate package (existing installs won't upgrade in place). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
// SPDX-FileCopyrightText: 2026 Reactorcoremeltdown
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package space.rcmd.android.sizzle.io
|
||||
|
||||
import space.rcmd.android.sizzle.model.Arrangement
|
||||
import space.rcmd.android.sizzle.model.Pitch
|
||||
import space.rcmd.android.sizzle.model.Project
|
||||
import space.rcmd.android.sizzle.model.TimeSignature
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertNotEquals
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
|
||||
/** Verifies the `.sng` reader/writer against the reference desktop format. */
|
||||
class SngFormatTest {
|
||||
|
||||
private val reference = """
|
||||
version 1
|
||||
bpm 120
|
||||
sig 4 4
|
||||
|
||||
block A 16 4
|
||||
roll ####
|
||||
track T1 0
|
||||
0 C-4 64 01
|
||||
4 E-4 .. ..
|
||||
8 OFF .. ..
|
||||
endblock
|
||||
""".trimIndent()
|
||||
|
||||
@Test
|
||||
fun parsesReferenceExample() {
|
||||
val p = SngFormat.importInto(Project(), reference)
|
||||
|
||||
assertEquals(120f, p.tempoBpm, 0.001f)
|
||||
assertEquals(TimeSignature.FOUR_FOUR, p.timeSignature)
|
||||
|
||||
val block = p.patterns[0]
|
||||
assertEquals("A", block.name)
|
||||
assertEquals(16, block.length)
|
||||
|
||||
val c0 = block.cell(0, 0)
|
||||
assertEquals(Pitch.parse("C-4"), c0.note)
|
||||
assertEquals(0x64, c0.velocity) // velocity is hexadecimal
|
||||
assertEquals(1, c0.channel)
|
||||
|
||||
val c4 = block.cell(0, 4)
|
||||
assertEquals(Pitch.parse("E-4"), c4.note)
|
||||
assertEquals(0x7F, c4.velocity) // ".." -> default (full MIDI velocity)
|
||||
assertEquals(1, c4.channel) // ".." -> inherit track channel (0 -> 1)
|
||||
|
||||
assertTrue(block.cell(0, 8).isNoteOff)
|
||||
|
||||
// roll "####" enables block 0 on beats 0..3 of its own lane.
|
||||
for (beat in 0..3) assertNotEquals(Arrangement.EMPTY, p.arrangement.patternAt(0, beat))
|
||||
assertEquals(Arrangement.EMPTY, p.arrangement.patternAt(0, 4))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun roundTripsNotesAndRoll() {
|
||||
val p = Project()
|
||||
p.tempoBpm = 140f
|
||||
p.timeSignature = TimeSignature.FIVE_FOUR
|
||||
p.patterns[0].cell(0, 0).apply { note = 60; velocity = 0x40; channel = 3 }
|
||||
p.patterns[0].cell(1, 5).apply { note = 67; velocity = 0x7F; channel = 2 }
|
||||
p.arrangement.set(0, 0, 0)
|
||||
p.arrangement.set(0, 1, 0)
|
||||
|
||||
val restored = SngFormat.importInto(Project(), SngFormat.export(p))
|
||||
|
||||
assertEquals(140f, restored.tempoBpm, 0.001f)
|
||||
assertEquals(TimeSignature.FIVE_FOUR, restored.timeSignature)
|
||||
restored.patterns[0].cell(0, 0).let {
|
||||
assertEquals(60, it.note); assertEquals(0x40, it.velocity); assertEquals(3, it.channel)
|
||||
}
|
||||
restored.patterns[0].cell(1, 5).let {
|
||||
assertEquals(67, it.note); assertEquals(0x7F, it.velocity); assertEquals(2, it.channel)
|
||||
}
|
||||
assertNotEquals(Arrangement.EMPTY, restored.arrangement.patternAt(0, 0))
|
||||
assertNotEquals(Arrangement.EMPTY, restored.arrangement.patternAt(0, 1))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user