diff --git a/Programs/CosmOS/Apps/Play.asm b/Programs/CosmOS/Apps/Play.asm index 4dcc871..709d08d 100644 --- a/Programs/CosmOS/Apps/Play.asm +++ b/Programs/CosmOS/Apps/Play.asm @@ -133,15 +133,15 @@ playReady: ; ---- The beat ---- ; - ; 125,000 cycles is a sixteenth note at 120 beats a minute, which is the smallest thing - ; this piece divides a beat into. The period goes in before the control byte, because - ; writing control with the run bit set is what loads it. - INIA 0x01 - OUTA 0x52 - INIA 0xE8 - OUTA 0x53 - INIA 0x48 - OUTA 0x54 + ; ONLY THE CONTROL BYTE. The period was set by whoever supplied the tune, because a tick + ; belongs to the tune and not to this program: a file says what it wants in its header. + ; + ; It used to be written here as well, AFTER useTune had taken it out of the file - so every + ; tune played at a sixteenth note at 120 beats a minute whatever its header said. The only + ; reason nothing noticed is that the one fixture in the suite asks for exactly that. + ; + ; Writing control with the run bit set is what loads the period, which is why this comes + ; after whoever set it and not before. INIA 0x07 OUTA 0x51 ; Run, repeat, interrupt. SIF @@ -220,6 +220,15 @@ playNotATune: ; three tables the player asks for, and an order list for each voice. Nothing is relocated, ; because the assembler already wrote the addresses. useBuiltIn: + ; The tick this tune wants. For a file it comes out of the header; for this one it is here, + ; so that both hand the player the same things. + INIA 0x01 + OUTA 0x52 + INIA 0xE8 + OUTA 0x53 + INIA 0x48 + OUTA 0x54 ; 0x01E848 is 125,000: a sixteenth note at 120. + SETD.0 BuiltInPatches SETD.1 PatchTable STD.0.1 diff --git a/Tests/makedisks.sh b/Tests/makedisks.sh index a1eb997..5fed4cf 100755 --- a/Tests/makedisks.sh +++ b/Tests/makedisks.sh @@ -736,6 +736,13 @@ open(sys.argv[1], "wb").write(blob(128)) open(sys.argv[2], "wb").write(blob(129)) FIXTURE "$ROOT/TuneC" -I "$WORK" "$ROOT/Programs/Tunes/two.tune.txt" "$WORK/compiled.tune" >/dev/null + +# The same tune at half the speed. A TICK BELONGS TO THE TUNE, and the only reason nothing +# noticed that Play was ignoring it was that every fixture asked for the tick Play happened to +# have written into itself. One that asks for something else is the whole check. +sed 's/#Tick 0d125000/#Tick 0d250000/' "$ROOT/Programs/Tunes/two.tune.txt" > "$WORK/slow.tune.txt" +"$ROOT/TuneC" -I "$WORK" "$WORK/slow.tune.txt" "$WORK/slow.tune" >/dev/null +"$TOOL" put "$DISKS/quiet.img" "$WORK/slow.tune" slow.tune >/dev/null "$ROOT/Assembler" -I "$ROOT/Programs/Sounds" -I "$ROOT/Programs/Libraries" \ -I "$ROOT/Programs/CosmOS/Source" \ "$ROOT/Programs/CosmOS/Apps/Play.asm" -o "$WORK/Play.sbx" >/dev/null diff --git a/Tests/sound.sh b/Tests/sound.sh index 8aac3a7..cb2f7c6 100755 --- a/Tests/sound.sh +++ b/Tests/sound.sh @@ -817,6 +817,28 @@ PY2 || result no "and a command in it loads a patch from it" "$SECOND hertz, wanted the octave" fi + # ---- A tune's tick is the tune's ---- + # + # slow.tune is two.tune with twice the period and nothing else changed, so it has to last + # twice as long. Play used to write its own tick over the one useTune had just taken out + # of the header, and every tune played at a sixteenth note at 120 whatever it asked for - + # invisible for as long as every fixture asked for exactly that. + printf 'Play slow.tune\n\n\nexit\n' > "$BUILD/slow.in" + timeout 60 "$EMU" --fast --cycles 8000000 --sound "$BUILD/slow.raw" \ + --disk "$ROOT/Tests/build/disks/quiet.img" "$BUILD/cosmos.bin" \ + < "$BUILD/slow.in" > "$BUILD/slow.out" 2>&1 + SPAN="$(python3 - "$BUILD/slow.raw" <<'PY2' +import struct, sys +d = open(sys.argv[1], "rb").read(); n = len(d) // 2 +v = struct.unpack("<%dh" % n, d) +loud = [i for i, x in enumerate(v) if abs(x) > 500] +print(loud[-1] - loud[0] if loud else 0) +PY2 +)" + near "$SPAN" 96000 2 \ + && result ok "a tune's tick is the tune's own" "$SPAN samples, and 8 ticks of 250,000 cycles is 96,000" \ + || result no "a tune's tick is the tune's own" "$SPAN samples, wanted about 96,000" + # ---- The compiler and the hex editor agree ---- # # TWO IMPLEMENTATIONS OF ONE FORMAT, which is the discipline SplitDisk and sbfs.asm are