Skip to content

tests: record the boot chime of each sound card and check its structure - #736

Open
jamesbraid wants to merge 3 commits into
audio/hal2-fixturefrom
audio/chime-tests
Open

jamesbraid wants to merge 3 commits into
audio/hal2-fixturefrom
audio/chime-tests

Conversation

@jamesbraid

@jamesbraid jamesbraid commented Nov 14, 2026 •

Copy link
Copy Markdown
Collaborator

Boots each machine's embedded PROM with no disk and checks the boot chime through the card-rate recorder (IRIS_AUDIO_DUMP), so a HAL2, RAD1 or MACE change that alters what a booted machine plays fails a test.

The checks are structural: native rate (HAL2 44100 Hz, RAD1 32000 Hz, MACE 34000 Hz), two boots playing identical samples (compared before any length is pinned), left equal to right on HAL2 and RAD1, not silent, not held at full scale, and a regression pin of length and peak per card. The pins record what the model plays now; they are not a model of the tune and nothing compares samples against synthesized data.

The guest does not wait for the card, which is paced by the host clock, so the PROM prompt can appear while the chime still plays (sooner with the JIT). Each test waits on frames the card played: for HAL2 a quarter second of frames its meter counts as dry after the last one moved, for the O2 a second of recorded silence after the last sound, and the O2's pin counts its non-silent frames, because the dry-ring gaps inside its chime vary with host load (62136 non-silent frames, identical across six boots, five of them loaded), for RAD1 a quarter second of it and then for the dump to stop growing.

Also: a test of the O2 DAC gain against the AD1843 data sheet for all 64 register values.

Debug build: Indy 92150 frames (peak 32768, 6 samples at full scale), Indigo2 IP22 85000 (19730), IP28 85000 (19422), Octane 60927 (27717), O2 62136 non-silent frames (6632). The O2's left and right differ, so equality is not asserted there. The Octane test takes one to two minutes and is #[ignore]d; each of the other four adds 13 to 23 s to a debug test run.

The monitor test carries its own guard that kills a stray iris, a free
port finder and a CI socket client. The chime tests drive iris the same
way, and a second copy would have to be kept in step with the first.

Move the three into tests/common/iris_process.rs; the CI client takes
its arguments and read timeout so wait-serial, which holds its reply
until the pattern shows, can use it. The monitor test keeps a one-line
wrapper with its old signature.
…value

The existing gain test spot-checks a few register values. The gain
field is 64 steps across an analog and a digital half, and a slip in
the join between them (a step off at the 32 boundary) would pass the
spot checks while changing every quiet sound.

Check all 64 values against the data sheet's scale: each step is
-1.5 dB, 8 is 0 dB, 0 is +12 dB and 63 is -82.5 dB, with those three
anchors also written out as literal factors so the formula cannot be
wrong in the same way as the code. Left and right take different
values, and each mute bit is set alone, so swapped fields or swapped
mute bits fail.
Nothing exercised a sound card end to end from a real PROM, so a change
to HAL2, RAD1 or the O2's audio could leave every unit test green and
still change what a booted machine plays.

Boot each machine's embedded PROM with no disk, wait for the PROM's
prompt on the serial console, and read the card-rate dump. Assert the
native rate (HAL2 44100 Hz, RAD1 32000 Hz, MACE 34000 Hz), that two
boots play identical samples (compared before any length is pinned),
that left equals right where the card makes them equal (not the O2,
whose channels differ), that the sound is not silent and not held at
full scale, and the length and peak of what the model plays now. Those
last two are regression pins of observed behaviour, not a model of the
tune; the repository has no vendor tune data to derive them from.

The guest does not wait for the card, which is paced by the host clock,
so the prompt can come up while the chime is still playing, and does
sooner with the JIT. Quitting at the prompt cut the Indy's chime short
by a different amount each run. Each test waits on the card instead.
HAL2 records nothing while its ring is dry, so the wait is for a quarter
second of the frames its meter counts as dry after the last one moved.
The O2 records its silence indefinitely, so the wait is for a second of
it after the last sound. A late guest also leaves silent gaps inside the
O2's chime (56 to 2836 frames in six boots, five of them loaded, with
62136 non-silent frames identical in order and value around them), so
the O2's chime is its non-silent frames. RAD1 records only a quarter second of silence
and then stops, so the wait is for that and then for the dump to stop
growing: a guest stall that leaves the ring silent mid-chime keeps it
growing.

The Octane boots with its graphics board off to get a serial prompt, and
RAD1 only records with its output open, so the host output is the null
one. The Octane test boots twice for one to two minutes and is ignored
by default. Each of the other four adds 13 to 23 s to a debug test run.
TESTING.md says what the tests check and what they do not.
@jamesbraid
jamesbraid added this pull request to stack #737 November 14, 2026 14:16
@jamesbraid
jamesbraid removed this pull request from stack #737 November 14, 2026 20:52
@jamesbraid
jamesbraid added this pull request to stack #741 November 14, 2026 20:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant