speaker: interactive PCM probe piece + system.audio API + onboard probing docs
When ac-native's main audio path is silent the fastest way to figure
out which ALSA device actually drives the speakers is to play a tone
on every playback PCM in turn and listen for which one comes out.
speaker.mjs makes that a two-key workflow:
↑↓ — navigate /proc/asound-enumerated PCMs (HDMI hidden)
space — play a 440Hz sine for 500ms on the highlighted device
f / v / d — cycle frequency / volume / duration
r — re-enumerate PCMs (e.g. after hot-plugging a USB DAC)
esc — back to prompt
Two new native APIs in js-bindings.c:
system.audio.listPcms()
Scans card0..card3, pcm0p..pcm7p, returns [{device,card,num,id,name}]
with `active: true` marking whichever PCM the main audio thread
currently owns (so the UI can show where the rest of the system is
pointed).
system.audio.testPcm(device, freq_hz, duration_ms, volume)
Opens the given hw:N,M, set_params to stereo S16LE @ 48kHz /
~100ms latency, writes a sine wave, drains + closes. Runs in a
detached pthread so the calling JS frame stays responsive. Default
args: 440Hz / 500ms / 0.3.
Both are read-only — they never touch the main audio thread's PCM
handle, so a user can probe while notepat is playing without
glitching.
SCORE.md: new "Hardware Probing on ac-native" section telling the
onboard Claude instance (the CLI binary bundled in the initramfs at
/bin/claude) where to look when debugging hardware issues — boot-time
logs, runtime piece APIs, sysfs hotspots, build-time canaries. The
same Claude that's been helping offline through this whole audio saga
now has the playbook baked in.
docker-build.sh: bundle speaker.mjs alongside clock and arena.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>