Give the machine a sound device

Four channels on ports 0x40 to 0x4F, each one a whole soundThing voice:
two oscillators, two envelopes, a filter and the routing between them. A
channel keeps its patch between notes, so a program sets an instrument up
once and then plays it.

Six ports rather than forty, because a voice has around forty settings and
four of them would spend more than half the port space on one device.
There is a selector and a value instead: say which channel, say which
setting, write it. That is three writes to change a setting and two to
play a note, which is the right way round - patches are loaded, notes are
played in an inner loop.

Samples come from the machine's clock and not the host's: 48,000 a second
of emulated time, worked out in whole numbers so it never drifts. A
million cycles is exactly 48,000 samples on any host at any speed, which
is what makes a sound something a test can compare. --sound writes them
out, the way --screen writes a picture, for the same reason: the suite has
no speaker.

Tests/sound.sh is 22 checks and found three real defects the first time it
ran, all the same shape - a synthesizer written for a patch editor, wired
up as hardware and inheriting the editor's assumptions:

  - Only one voice had an oscillator switched on, so three of the four
    channels could not make a sound whatever was written to them.
  - That voice's oscillator arrived at full gain and every other one
    arrived at nothing, an asymmetry with no reason behind it.
  - A note with no sustain is silent but not over, so the obvious way to
    wait for a sound to finish waits for ever.

The first two are fixed by the device defining its own power-on state
rather than inheriting synthInit's: every channel arrives able to make a
sound, so writing a note number is the whole of playing a note. The third
was already written into the manual as advice, an hour before the check
existed. The check disagreed with the documentation and the check was
right; the manual now says the one rule, which is that a note sounds until
the gate is dropped.

Programs/Examples/tune.asm plays eight notes, taking its tempo from the
screen's frame interrupt because that is the only regular beat this
machine has. It spends 99.8% of its cycles asleep in WAIT.

Voyager has no speaker yet - this is the device and its tests. Playing the
samples out of the window is the next commit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
This commit is contained in:
Anachronaut
2026-08-29 20:59:17 -04:00
co-authored by Claude Opus 5
parent b0d06aa6e5
commit d388cd3122
14 changed files with 1332 additions and 8 deletions
+23 -3
View File
@@ -9,7 +9,7 @@ believe them.
## What The Suite Claims:
The suite is not one thing. It is ten scripts making five different kinds of claim, and
The suite is not one thing. It is eleven scripts making five different kinds of claim, and
knowing which claim you are relying on is the whole point of this document. A recorded
transcript and a byte-for-byte comparison against a second implementation both print
`[ok ]`, and they are worth wildly different amounts.
@@ -58,6 +58,7 @@ Individual scripts can be run on their own, from anywhere:
./Tests/disk.sh The disk tool against the format.
./Tests/cycles.sh What the memory controller charges.
./Tests/video.sh What the video device draws.
./Tests/sound.sh What the sound device makes.
./Tests/terminal.sh The things a recorded file cannot see.
./Tests/native.sh The two assemblers against each other.
./Tests/agree.sh The two filesystems against each other.
@@ -78,7 +79,7 @@ from `make`, not from here.
### 1. Recorded output
`Tests/run.sh` assembles each program named in `Tests/manifest`, runs it, and compares
everything it printed against a file in `Tests/expected`. 169 tests, of which 107 run, 35
everything it printed against a file in `Tests/expected`. 170 tests, of which 108 run, 35
only assemble, 16 are expected to fail to assemble, and 11 boot from ROM with no image
given at all.
@@ -158,7 +159,26 @@ the palette is what colours it, that the attribute nibble adds sixteen, that scr
which row is on top, that the map wraps, and that an impossible mode is refused without
stopping the machine.
**Half of it is about the console rather than the device.** Those programs ask the video
`Tests/sound.sh` is the same argument again, one device along: the suite has no speaker, and
a sound nothing can hear is a sound nothing checks. Its samples come from the machine's clock
rather than the host's, so `--sound` writes a file that is a pure function of the program and
the cycle count - a million cycles is exactly forty-eight thousand samples, on any host, at
any speed. The checks read that file back and measure it: that a note is the note that was
asked for, that twelve of them is an octave, that gain is a level and volume is over the top
of it, and that two runs are identical byte for byte.
**It found three real defects the first time it ran**, all of them the same shape - a
synthesizer written for a patch editor, wired up as hardware and inheriting the editor's
assumptions. Only one voice had an oscillator switched on, so three of the four channels could
not make a sound whatever was written to them. That voice's oscillator arrived at full gain
while every other one arrived at nothing. And a note with no sustain is silent but not over,
so the obvious way to wait for a sound to end waits for ever.
The last of those had already caught the person writing the device, an hour before the check
existed, and had been written into the manual as advice. That is the argument for a suite in
one sentence: **the check disagreed with the documentation, and the check was right.**
**Half of `video.sh` is about the console rather than the device.** Those programs ask the video
device for nothing at all: they write bytes to port 0x00, the way every SplitBit program
always has, and the picture is what is checked. A character lands at the cursor and the
cursor moves along, a newline starts the next row, backspace rubs out, the line wraps at the