SPL Meter 0.4.1: name a dead input, and stop the spectrogram smearing its labels #16

Merged
michael merged 2 commits from claude/spl-silent-input into main 2026-09-23 10:03:28 -04:00
Owner

Two fixes, both found by the meter looking broken on AB when it was not.

A dead input must not look like a quiet room

AB's meter appeared to halt for a day and a half. Nothing had halted. The capture child had run continuously since the machine was unlocked, never stalled, never exited, and was delivering twenty frames a second — every one of them digital silence, because Dante Via was passing nothing. The Timers module's LTC listener, on channel 16 of the same device, had been reporting no signal for exactly as long.

The module's part in that was reporting ok throughout and drawing a steady -83, which is the -200 floor plus the +117 calibration offset. A plausible number on a wall gets believed, and a green dot beside it says the number is worth believing. That is worse than showing nothing.

Silence is now a state the module names. Below -150 dBFS unweighted the input is not quiet, it is absent: a microphone in a silent room still reads about -83, and even a muted converter dithers. Five seconds of that on every channel and health() goes to error naming the device and the duration, every tile stops drawing a level and says "No audio" with how long, and the dot goes red.

Verified both directions, which is the half that matters — a device with nothing routed into it is caught in five seconds, and a real microphone at -49 dBFS is never flagged.

The spectrogram was dragging its own labels

It scrolled by copying the visible canvas onto itself one step along. That canvas already held the frequency labels and gridlines, so every frame smeared them sideways. Arrived with the labels in 0.3.0.

Only measured pixels belong on a surface that scrolls. The history now lives on its own offscreen canvas holding nothing but spectrum, and the visible canvas is repainted from scratch each frame, history first and annotations over the top. Nothing drawn as an annotation can reach the scroll buffer by construction, rather than by remembering to clear the right strip.

The layout was muddled in the same place and is fixed with it: the gutter was reserved along the bottom while the labels were drawn down the left, over the plot. Labels now sit beside the axis they describe, with room for "12.5k".

Verified in both orientations by fingerprinting the gutter and the plot two and a half seconds apart — gutter identical, plot changed.

Also worth knowing

The underlying Dante fault was not the module's. Separately diagnosed: AB has FileVault on with no auto-login, so after a reboot the machine sits at the pre-boot password screen and nothing runs — no Dante, no ProdDash — until someone types the disk password.

Deployed to AB and reading live: 62-64 dBA on Dante channel 15.

🤖 Generated with Claude Code

Two fixes, both found by the meter looking broken on AB when it was not. ## A dead input must not look like a quiet room AB's meter appeared to halt for a day and a half. Nothing had halted. The capture child had run continuously since the machine was unlocked, never stalled, never exited, and was delivering twenty frames a second — every one of them digital silence, because Dante Via was passing nothing. The Timers module's LTC listener, on channel 16 of the same device, had been reporting no signal for exactly as long. The module's part in that was reporting `ok` throughout and drawing a steady `-83`, which is the `-200` floor plus the `+117` calibration offset. A plausible number on a wall gets believed, and a green dot beside it says the number is worth believing. That is worse than showing nothing. Silence is now a state the module names. Below **-150 dBFS unweighted** the input is not quiet, it is absent: a microphone in a silent room still reads about -83, and even a muted converter dithers. Five seconds of that on every channel and `health()` goes to error naming the device and the duration, every tile stops drawing a level and says "No audio" with how long, and the dot goes red. Verified both directions, which is the half that matters — a device with nothing routed into it is caught in five seconds, and a real microphone at -49 dBFS is never flagged. ## The spectrogram was dragging its own labels It scrolled by copying the visible canvas onto itself one step along. That canvas already held the frequency labels and gridlines, so every frame smeared them sideways. Arrived with the labels in 0.3.0. Only measured pixels belong on a surface that scrolls. The history now lives on its own offscreen canvas holding nothing but spectrum, and the visible canvas is repainted from scratch each frame, history first and annotations over the top. Nothing drawn as an annotation can reach the scroll buffer by construction, rather than by remembering to clear the right strip. The layout was muddled in the same place and is fixed with it: the gutter was reserved along the bottom while the labels were drawn down the left, over the plot. Labels now sit beside the axis they describe, with room for "12.5k". Verified in both orientations by fingerprinting the gutter and the plot two and a half seconds apart — gutter identical, plot changed. ## Also worth knowing The underlying Dante fault was not the module's. Separately diagnosed: AB has FileVault on with no auto-login, so after a reboot the machine sits at the pre-boot password screen and **nothing** runs — no Dante, no ProdDash — until someone types the disk password. Deployed to AB and reading live: 62-64 dBA on Dante channel 15. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
michael added 2 commits 2026-09-23 09:59:43 -04:00
AB's meter appeared to halt for a day and a half. Nothing had halted: the
capture child had run continuously since the machine was restarted, never
stalled, never exited, and was delivering twenty frames a second. Every one
of them was digital silence, because Dante Via stopped passing audio after
the reboot — the Timers module's LTC listener, on channel 16 of the same
device, had been reporting no signal for exactly as long.

The module's part in that was reporting "ok" through all of it and drawing
a steady -83, which is the -200 floor plus the +117 calibration offset. A
plausible number on a wall is believed, and a green dot beside it says the
number is worth believing. That is worse than showing nothing.

So silence is now a state the module names. Below -150 dBFS unweighted the
input is not quiet, it is absent: a microphone in a silent room still reads
about -83, and even a muted converter dithers. Five seconds of that on every
channel and health() goes to error naming the device and how long it has
been dead, the tiles stop drawing a level and say "No audio" with how long,
and the status dot goes red.

Verified both directions, which is the half that matters: BlackHole with
nothing routed into it is caught in five seconds, and a real microphone in a
quiet room at -49 dBFS is never flagged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The spectrogram scrolled by copying the visible canvas onto itself one step
along. That canvas already held the frequency labels and gridlines, because
they were drawn straight onto it, so every frame smeared them sideways and
left a trail. Arrived with the labels in 0.3.0; the gridlines did it too.

Only measured pixels belong on a surface that scrolls. The history now lives
on its own offscreen canvas that holds nothing but spectrum, and the visible
canvas is repainted from scratch each frame — history first, annotations
over the top. Nothing drawn as an annotation can reach the scroll buffer by
construction, rather than by remembering to clear the right strip.

The layout was muddled in the same place and is fixed with it: the gutter
used to be reserved along the bottom while the labels were drawn down the
left, overlapping the plot. Labels now sit beside the axis they describe —
down the left when frequency runs vertically, with room for "12.5k", and
along the bottom when it runs horizontally.

Verified both orientations by fingerprinting the gutter and the plot two and
a half seconds apart: gutter identical, plot changed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
michael merged commit 0e618ea5d3 into main 2026-09-23 10:03:28 -04:00
michael deleted branch claude/spl-silent-input 2026-09-23 10:03:33 -04:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: michael/ProdDash#16