-
fix(audio): prune the graph — 2.1M xruns came from nodes nobody used · db42ffce
THE J-5 DROPOUT. Sound went glitchy-then-silent mid-rehearsal, five days before OPAL, and every obvious suspect was healthy: sclang up, scsynth up and using 6.7% CPU, the UMC sink present and RUNNING, every link in place. Diagnosing the audio engine would have found nothing wrong with it, because nothing was. THE BEHRINGER IS THE CANARY, NOT THE FAULT. The internal speaker played fine the whole time and only the UMC202HD died, which looks exactly like a broken interface. It is not: period_size 128 on the UMC against 1024 on the SOF speaker is an 8x tighter deadline, so the UMC is the only device in the box with a real-time deadline tight enough to miss. USB devnum stayed at 14 across samples (not the 2026-07-26 re-enumeration bug), mixer 127/127, links intact. Rule for next time: when only the UMC is silent, suspect the SCHEDULER. WHAT pw-top FOUND. Xruns per node: sof_sdw.HiFi__Headset__source 1,421,369 nothing used it sof_sdw.HiFi__HDMI1__sink 704,081 2.8ms BUSY/cycle, no client UMC202HD Line sink 32,338 the victim alsa_input.hw_U192k_0 14,338 W/Q 1.24 = waits > a full quantum SuperCollider 1,119 ardour 422 Two nodes NOBODY USES produced 2.1 million of them. HDMI1 appeared when the screen was mirrored for the WYSIWYG show. THE ROOT CAUSE WAS A FIX. 52-no-suspend.conf matched ~alsa_output.* and ~alsa_input.* — every node in the graph. It was written for a real reason (a woken device eats the first note's attack) but applied graph-wide it held six SOF sinks and a broken mic source permanently open INSIDE the real-time graph. Never-suspend is precisely what it asked for. The generalisable lesson, and it is the one worth keeping: a rule scoped to one device but applied to the whole graph stops being a fix and becomes a load. Suspension is not the enemy — suspension of the device you are playing through is. Now narrowed to the UMC plus the internal Speaker, the latter kept deliberately because it is the fallback that proved the machine could still make sound during the incident. AND THE LAPTOP MICROPHONE WAS IN THE d1 RECORDING. pw-link showed Headset__source:capture_FL -> ardour:Tidal 01/audio_in 1. Ardour auto-connects physical inputs, so the internal mic was summed into the input of the track that records d1, alongside SuperCollider:out_1 — invisible in Ardour's GUI and in the saved session file. 53-rig-graph.conf disables the source outright rather than trusting nobody to re-arm that track. Take95 was recorded with it connected; auditing that is #132. RESULT, measured. Load 7.17 -> 4.80. UMC hw_ptr went from restarting once a second — never past ~3000 frames, deltas going NEGATIVE — to a steady 48,145 frames/sec across six consecutive samples with zero restarts. VERSIONED, NOT COPIED. The three wireplumber files now live in config/wireplumber/ and are SYMLINKED from ~/.config. One source of truth: a copy would have become the fourth thing in this project to drift from its generated twin. check-audio-graph.sh also fails on a dangling symlink, because a broken one is silent until the next wireplumber restart — the worst possible moment to find out. NEW GATE: tools/check-audio-graph.sh, wired into gig-up as a HARD check. It asserts what was actually wrong, in the order it bites: no non-SuperCollider source on any Tidal input (recording integrity first — a dropout you hear and redo, a stem with room noise in it you ship), Master really reaching the UMC, the interface actually clocking, and the prune still in effect. check-mix reads the SAVED session; this reads the LIVE graph, and the saved file has been wrong before (#62). TWO METHODOLOGY RULES BAKED INTO IT, both learned that day: - NEVER SCAN THE JOURNAL. `journalctl --since` on a long-uptime box reads the whole journal and burned a full core twice WHILE PLN WAS LOSING AUDIO — the diagnostic making the fault worse. Everything is /proc, pw-link, bounded pw-top. - `state: RUNNING` PROVES NOTHING. It read RUNNING while the device was dying. Only the hardware pointer, sampled repeatedly, is honest — and take four samples, not two: my first two-sample read gave a confidently wrong "still stalling" verdict because a ring-buffer wrap looks identical to a stall. Mutation-checked: the recording-integrity awk was run against the real 2026-08-03 pw-link dump WITH the mic present (it fires) and against a clean one (silent, no false positive). A check that has never seen the bug it was written for is a guess.PLN (Algolia) authoreddb42ffce
| Name |
Last commit
|
Last update |
|---|---|---|
| .. | ||
| 51-disable-sof-dmic.conf | Loading commit data... | |
| 52-no-suspend.conf | Loading commit data... | |
| 53-rig-graph.conf | Loading commit data... |