Public-ready: JSON tune specs, first-class loop API, licence, AGENTS.md
- MidiFile.set_loop(): one call writes LOOP_START/END, RPR LOOP START/END (Reaper) and LoopBegin/End markers - every engine finds its dialect; reader now parses markers and the smoke test asserts the round-trip - tools/make_tune.py: declarative JSON spec -> fully arranged MIDI with style presets (dos_adventure, n64_ambient, chiptune_racing); the agent-friendly front door, no Python required - tunes/specs/: demo tune 04 'Tea Break at the Terminal' (Am/112, loop bars 4-20) generated entirely from JSON - AGENTS.md: spec schema, score grammar, verification loop, looping conventions for game BGM - MIT LICENSE; history audited clean of credentials
This commit is contained in:
1 parent
c3cd91d04f
commit
633eb92352
15 files changed
+387
-9
No files matched your search
@@ -26,6 +26,7 @@ d = Track("Drums", channel=9)
|
||||
drums(d, 0, 2, "rock")
|
||||
mf.add_track(lead); mf.add_track(bass); mf.add_track(acomp); mf.add_track(d)
|
||||
mf.tempos = [MPQN.from_bpm(0, 120)]
|
||||
mf.set_loop(bar(0), bar(2)) # loop the whole 2-bar demo
|
||||
path = "/tmp/midikit_smoke.mid"
|
||||
mf.write(path)
|
||||
|
||||
@@ -34,6 +35,13 @@ print("OK:", path, d["duration_sec"], "sec,",
|
||||
sum(len(t["notes"]) for t in d["tracks"]), "notes,",
|
||||
len(d["tracks"]), "tracks")
|
||||
|
||||
# loop markers must survive the round-trip in all three conventions
|
||||
markers = sorted(set(m[1] for t in d["tracks"] for m in t["markers"]))
|
||||
expected = sorted(["LOOP_START", "LOOP_END", "RPR LOOP START", "RPR LOOP END",
|
||||
"LoopBegin", "LoopEnd"])
|
||||
assert markers == expected, "loop markers wrong: %s" % markers
|
||||
print("loop markers OK:", ", ".join(markers))
|
||||
|
||||
# cross-check with mido if present (third-party parser as second opinion)
|
||||
try:
|
||||
import mido
|
||||
|
||||
Reference in new issue
Block a user