fix(rig): the yellow-LED loop was our own systemd service — and the "broken"…
fix(rig): the yellow-LED loop was our own systemd service — and the "broken" orbits were closed Ardour faders
Two independent silent failures, both found tonight, both invisible from the
editor. Neither was in Tidal, which is where every hypothesis pointed.
## 1. The yellow-button loop: we were fighting ourselves
Symptom, standing for weeks: paint an LCXL button a colour, press it, it snaps
to yellow and wipes the colour. `aconnect -d 14:0 24:0` fixed it — and then it
came back, every time, "after a Tidal reboot". We blamed SuperCollider's
`MIDIIn.connectAll`, Ardour's control surface, WirePlumber.
It was `~/.local/bin/midi-autoconnect.sh`, a service we wrote ourselves. Its
rule 2 connected `Midi Through:0 -> Launch Control XL:0`, commented
"LED/visual feedback", and re-asserted it every 2 seconds. That IS the loop:
press -> LCXL emits Note On velocity 127
-> LCXL:0 -> Midi Through:0 -> (rule 2) -> LCXL:0
-> LCXL reads an inbound note velocity as an LED COLOUR
-> 127 = 0x7F = full red + full green = YELLOW
Not "reboot recreates it" — a 2-second reconcile loop was silently undoing the
operator's fix within two seconds of every manual cut. The rule bought nothing:
the HUD drives the LEDs directly by SysEx to the LCXL's own port.
Rule 2 is now INVERTED — it disconnects instead of connecting, so the return
leg is actively severed rather than merely not created (Ardour and SC can both
recreate it independently; same shape as every other binding on this rig — one
that must be re-asserted, never assumed). LCXL -> Midi Through -> Ardour still
works, so click-to-map fader learn is unaffected.
Rule 3 (Midi Through -> every aseqdump) is deleted too: aseqdump clients
already subscribe to the LCXL directly, so the extra hop delivered every CC
TWICE to the HUD — duplicated work on the renderer we are trying to keep off
the audio thread's back (see the typing-crackle investigation).
Verified: after `systemctl --user restart`, `Connecting To` on client 14 no
longer lists 24:0, and stays that way across reconciles.
## 2. tools/check-mix.py — the mixer is part of the signal path
An evening went into "d7 plays one bar then fades to nothing" and "d9-d12 make
no sound, I see the meter move but nothing on master". We chased the
untouched-control mute-bomb, the DJF helpers, orbit routing, a missing sample
bank. Measured and eliminated, in order: PipeWire links (all 24 present,
out_17->Tidal 09 ... out_23->Tidal 12), Ardour route outputs (all 12 active and
connected to Master), the sample bank (like_sugar present, 22 files, `:21`
valid, inside a loaded glob since April), and the helpers themselves
(check-boot.sh pass 3: all 13 audible against an empty control map).
Then: **Tidal 02, 06, 07, 08 and 12 have their faders at -inf dB.** d7 in
bombe_dj is Tidal 07. d12 in the_revolution is Tidal 12. Exact match.
Why it cost a whole evening rather than a glance:
* Ardour meters are POST-fader by default, so a shut fader shows NO meter —
the display agrees with the "Tidal is broken" theory instead of refuting it.
* `dN` is `xfade N`, so a re-eval fades the OUTGOING pattern out over ~4
cycles. With the fader shut you hear the previous pattern dying: "plays a
bar then slowly goes to zero", which reads exactly like a filter closing.
* The faders are MIDI-learnable from the LCXL, so a physical fader left down
persists into the saved session and outlives every reboot of everything.
The tie-breaker: `d12` in the_revolution uses no `g*` helper and no `^NN` at
all. Such a pattern cannot be silenced by anything inside Tidal — so its
silence proved the fault was downstream, and the fader was the only downstream
thing left unverified. A control case with no confounders beat four sessions of
hypothesising.
check-mix.py reads the session XML and flags, per Tidal route: fader at/near
-inf, muted, or not routed to Master. Exit 1 so `gig-up.sh` can gate on it.
It states its own limitation rather than implying more than it checks: the
session is read from DISK, so a clean report means "boots healthy", not "the
running mixer is healthy". Live verification needs Ardour's OSC surface, not
yet wired.
Showing
tools/check-mix.py
0 → 100644
Please
register
or
sign in
to comment