Commit 91b8b958 by PLN (Algolia)

fix(gimme_acid): the EXPLOSIF knob boots at an extreme — diagnosed, not silently retuned (#111)

`# width (range 0.2 0.8 "^33") -- /!\ FIXME EXPLOSIF /!\` in gimme_acid's acid synth.
PLN has had a hazard marker on that line for a while. The cause is mechanical and
checkable without any audio:

^33 is an A/B knob, so BootTidal's #55 seed gives it 0. The seed policy states its own
convention — "range <neutral> <extreme>, so 0 == neutral for effect knobs" — but 0.2 is
NOT neutral for `width`: the preset reference PLN pasted two lines above the call says
nominal is width = 0.51. So the line boots the synth at an extreme and the knob sweeps
it THROUGH nominal rather than away from it, which is a good candidate for whatever
"explosif" means to his ears.

This is the exact shape BootTidal.hs already documents as an authoring bug, using
piment_bresilien's `legato (range 0.05 2 "^52")` as its worked example, and its stated
remedy is to fix the range in the TRACK rather than special-case the seed.

Deliberately NOT applied. The candidate is `range 0.51 0.8 "^33"` — boots at nominal,
knob only adds — but it costs the 0.2-0.51 downward half of his sweep, and that is a
decision about how the track sounds. The analysis goes in the file next to his marker
so the next reader inherits the diagnosis instead of re-deriving it; the sound stays
his.

Did remove one unambiguous thing: `# filterRange (range 0 8 "^53")` appeared TWICE in
consecutive lines, same value, so the second was a no-op paste.

MORNING.md rewritten for today. Leads with the finding that actually matters at J-7:
check-mix.py reports Tidal 06/10/12 at -inf dB in the SAVED Ardour session, and
cross-referencing those against the orbits each setlist track declares shows **9 of 13
tracks would lose at least one orbit on a relaunch** (#62). The live faders are
probably fine — PLN has been playing — which is precisely the bug: the fix is not
persisted, so it dies with the process. Ctrl+S is the whole remedy, and it is his
hands, not mine: the D row is MIDI-learned to CC 77-84 and writing from outside
desyncs it from the physical desk.

Also flagged in MORNING.md rather than guessed: yesterday's file said "OPAL Day-5" and
today's framing was "J-7". There is no OPAL 2026 entry in Web/www/content/lives/2026/,
which CLAUDE.md names as the canonical source for gig metadata, so the countdown is
unresolvable from here and is asked rather than invented.
parent 27c1581e
# ☕ Morning, 2026-07-30 — OPAL Day-5 # ☕ Morning, 2026-07-30
**Everything from last night is superseded — that warning about ctrl+enter fading to Supersedes yesterday's file. Branch `claude/preload-eager-banks`, nothing pushed.
silence is FIXED and you confirmed it by ear ("no sample goes oblivion!! 👏"). This file Ordered by urgency, not effort.
replaces it.**
Branch `claude/preload-eager-banks`, nothing pushed. Built while you were on the practice > **Small thing that affects your planning:** yesterday's file said "OPAL Day-5",
recording and listening to the mix. Five things to check with your ears/eyes; everything > today you framed it "J-7". There is no OPAL 2026 entry in
else is done and verified mechanically. > `Web/www/content/lives/2026/` yet, so I can't resolve it and I'm not going to
> guess a countdown. Worth pinning down — and worth adding to the site content,
> since that's the canonical place for gig metadata.
--- ---
## 1. GIG BLOCKER — desire does not compile (5-second fix, but do it in Pulsar) ## ⚠️ 0. THIRTY SECONDS, DO THIS FIRST
`live/collab/raph/desire.tidal:46` has `# pan 0.42plz /se` — committed, not a stray edit. **Ardour's SAVED session has 3 orbits at -inf dB:** `Tidal 06`, `Tidal 10`, `Tidal 12`.
`plz` isn't a Tidal function. desire has **no blank lines**, so it's one do-block: this one
typo silences **every orbit**, d1 through d9. It's on the OPAL setlist.
**Fix in the editor, not on disk** — desire is in your dirty working tree and Pulsar saves Your LIVE faders are probably fine — you've been playing. That *is* the bug: the fix
the buffer, so if your open tab already has the correction, a disk edit gets silently isn't persisted, so it dies with the process and a relaunch at the venue restores the
reverted on your next save; if it doesn't, save after fixing. Change is one character: broken mix.
I cross-referenced those three against the orbits each setlist track declares:
``` ```
- # pan 0.42plz /se do_it_right d6 d10 d12 perfect d6 d10 d12
+ # pan 0.42 take_5_drops d10 d12 gimme_acid d10 d12
the_revolution d10 d12 vague_de_crime d6 d10
piment_bresilien d10 you_my_sunshine d6
desire d6
``` ```
Verify: `python3 tools/silent-eval.py --seeded live/collab/raph/desire.tidal` → should **9 of your 13 tracks would lose at least one orbit on a relaunch.**
print `desire: ok`.
--- 1. Ardour → check Tidal 06 / 10 / 12 faders, raise any that are down
2. **Ctrl+S** ← this is the entire fix
3. `python3 tools/check-mix.py` → expect no `-inf`
## 2. Your practice take is packed, archived, and the mix is validated Not touched by me: the D-row faders are MIDI-learned to CC 77-84, so writing from
outside desyncs them from the physical desk; CC77 down is total silence; and mix levels
are your musical intent. Writing to a live session while you're out isn't my call. (#62)
---
You heard `mix/take94/take94_trimmed.wav` and called it clean but flagged the ~18min gap as ## 🔴 1. BEFORE YOU OPEN ANY TRACK IN PULSAR — reload from disk
"not normal, a bad transition — cut it proper and fade". You were right and the tool was
wrong: three gaps (17s/18s/11s) all sat *just under* the trim threshold. Fixed — threshold
dropped to 10s, silences are now clamped to a 2s breath instead of removed whole, and every
cut fades (250ms) instead of butt-joining. Re-rendered: `mix/take94/take94_trimmed_v2.wav`
(18.75 min, all 5 gaps addressed including the one you named). **Give this one a listen —
it's the one that matters, not the v1 you already heard.**
Also done, no listening needed: **I changed 213 `.tidal` files on disk.** Pulsar saves the **BUFFER**, not the file.
- `tools/take-lens.py pack 94 --compress` — the take's MIDI (29862 events), track state, Anything you had open now has a stale buffer, and your next Ctrl-S in that tab
and gear info now live next to the audio at **silently reverts the migration in that file**.
`~/Work/Sound/Ardour/Tidal Live/takes/take94/`, safe from the gig-log prune timer.
Archived with wavpack: **5.84 GB → 1.25 GB, every file verified lossless**, .wav sources
untouched (deleting them is a separate step, your call, after you've heard v2).
- Found and fixed: xrun count in the sidecar was reading a *running total* as if it were a
per-tick delta, reporting 58 million xruns for a 21-minute take. Real number: **230**.
Same command works on your next take: `tools/take-lens.py pack <N> --compress`. `Window: Reload` before evaluating anything. (This is exactly why #95 exists.)
--- ---
## 3. silent-eval now covers all 13 setlist tracks (was 9) ## 2. The gM refactor is DONE — corpus-wide, not just the set
Two of the tool's own bugs were making it diverge from how ghci actually runs your code — Your map, now authored in `tools/lcxl_grid.py` with your words above it:
fixed by matching ghci's defaults exactly (ExtendedDefaultRules, and hiding boot names from
the Context import so `let cutoff = ...` shadows the same way live). `perfect` and
`mafia_sans_serif` now build clean. That's how desire's real bug (#1 above) got found — the
tool used to lump it in with "harness limit, ignore this," which was actively hiding a gig
blocker. It now says `THE TRACK DOES NOT COMPILE` when it means that.
```bash | mutes | F1 / gM1 | F2 / gM2 | F3 / gM3 |
python3 tools/silent-eval.py --seeded # whole setlist, should be 13/13 ok after #1 |---|---|---|---|
``` | | **d1 alone** (the kick) | other percs (d2 d3 d8) | bass + melodics (d4–d12) |
| DJF | C1 / gF1 | C2 / gF2 | C3 / gF3 |
|---|---|---|---|
| | all percs | bass only | melodies |
**917 lines across 213 files.** The bulk was *not* the kick — it was **505 perc lines
vacating gM1** so the kick could have it. Plus **7 orbits in the set that had no mute at
all** got one (your "no mute is oversight").
### One thing I had wrong, and you should know
#105 was written as "align gM to gF" — mirror the mute index onto the filter index. I
measured 35 mismatches under that rule and was ready to ship it. **The rule was wrong.**
Your answer showed filters and mutes group *differently on purpose*. Under your real map
it's 55 edits in the set, and `d4: gF2+gM3` — which the mirror rule called broken in 11
tracks — is **correct**. Shipping the "alignment" would have moved 11 good lines and left
the kick sharing a button with the hats.
### How it was verified (you asked me to be careful)
- **Convergence** — migrator run twice; second pass proposes 0 changes
- **Structural proof** — all 917 changed lines diffed against HEAD: 908 provably
mute-token-only, the other 9 individually listed and accounted for. Nothing else moved.
- **`silent-eval --seeded`: 13/13 ok** — whole setlist builds cold, before and after
- **222 tests pass** (was 213 passed / 1 failed when I started)
- **Full before/after `silent-eval` over all 213 files** — see the commit for the result
**THE HONEST LIMIT, and it's the important part:** every button CC seeds to 0 at boot and
`gMute<N>` is `midiOn "^7N" (mask "f*16")`, so all three mutes are equally inert until
pressed. **None of the above proves anything about behaviour under a press** — the only
thing this change actually alters. That needs your fingers, two minutes on any track:
> **F1 → only the kick drops. F2 → percs drop, kick keeps playing. F3 → bass + melody drop.**
If you hate it: `git revert 27c1581`, one commit, all 917 lines.
--- ---
## 4. The slop renderer exists — first clip rendered, not yet good enough to send ## 3. 🎧 you_my_sunshine — your "FIXME VOICE OFF" is fixed, confirm by ear
d5 (the voice) and d11 (`no_sunshine:4/4` chopped) were **both on `# cut 5`**. Cut groups
are monophonic, so every d11 event killed the vocal mid-word. That was also the root cause
of your `-- FIXME VOICE OFF` on d5 — **one bug wearing two labels.**
`visuals/slop/render_slop_clip.mjs` takes a planned cut or any audio window and renders a d11 → `# cut 11` (group N = orbit N, as d3/d6/d8/d9 already do). Found by pvlint PV004. If
vertical reel with Slopmotion reacting to the real audio (not a synthetic pump). It ran the vocal was *meant* to be monophonic across both layers, put it back to 5 — the comment
start to finish on 8s of take 94. **Frame rate is the open problem** — 7fps at 1080x1920, says so, and it's the only line that changed. (#70)
which is the GL backend + the machine, not the pipeline (measured, details in
`visuals/slop/FEEDBACK.md`; needs re-measuring on a quiet machine, not tonight while the ---
rig was up). Not something to review yet — flagging so you know it's real now, not vapor.
```bash ## 4. 🤔 gimme_acid `/!\ FIXME EXPLOSIF /!\` — diagnosed, NOT fixed, your call
node visuals/slop/render_slop_clip.mjs --idea wap # from the OPAL plan
node visuals/slop/render_slop_clip.mjs --audio mix/take94/take94_trimmed_v2.wav \ ```haskell
--start 300 --dur 30 --playset liquid-metal --name probe # width (range 0.2 0.8 "^33")
``` ```
(needs `cd ~/Work/Sound/hydra-live-hexa && . ~/.nvm/nvm.sh && nvm use 22 && npm run dev` running first)
`^33` is an A/B knob → BootTidal's #55 seed gives it **0** → this sits at **width 0.2 at
boot**. Your own preset comment two lines above says nominal is **width = 0.51**. So the
synth starts at an extreme and the knob swings it *through* nominal rather than away.
Same shape BootTidal already documents for piment_bresilien's `legato (range 0.05 2 "^52")`,
whose stated remedy is *fix the range in the track*.
Candidate: `range 0.51 0.8 "^33"` → boots at nominal, knob only adds. Costs the 0.2–0.51
downward half. **That's a sound decision, so I wrote the analysis into the file and left
the sound alone.**
Also removed a duplicated `# filterRange (range 0 8 "^53")` right below it — same value
twice, harmless, clearly a paste.
--- ---
## 5. desire bass rhythm — four things to A/B, not a decision made for you ## 5. 📋 The non-set missing-mute report
`docs/2026-07-30-orbits-without-a-mute.md` — you said flag, don't fix, outside the set.
2397 blocks, split into the cut that makes it actionable:
You said: *"i gotta solve desire bassline is not great rythmics, could be cooler, more | | files | blocks | |
ete_a_mauerpark or insouciance or haunted_house."* Read all three. The diagnosis is |---|---|---|---|
mechanical: desire's d4 is four equal groups of the same repeated note, on the beat, never | **A · partial** | 110 | 321 | uses family mutes but missed some — **the oversight you meant** |
resting — a metronome with a stutter, not a riff. The three references share six things it | **B · never** | 354 | 2076 | no orbit has one; predates the convention — a style era, not a mistake |
has none of (uneven note durations, pitch=rhythm, eighth-note displacement against the
kick, accent following the rhythm, rests, a phrase longer than one bar).
`study/desire_bass_rhythm.tidal` has four alternatives, each isolating different mechanisms Group A is the real list. Fix any one file with
so you can tell what you're reacting to — A (weight), B (gesture, biggest change), C `python3 tools/fix-mute-roles.py --fill --apply <path>`.
(space, safest/smallest change), D (all six combined — and deliberately *busier* than
today's line, to prove the fix isn't "fewer notes"). All four verified to compile and play.
Paste one `d4` over desire's real one and listen; pitch/key is unchanged in all four.
--- ---
## Everything else from tonight — mechanical, no listening needed ## 6. New guardrails, so none of this re-drifts
- LED daemon (`lcxl-leds-watch.service`) was silently mute in the journal — Python's stdout - **PV012** — flags an orbit whose mute doesn't match its **role**. Deliberately *not*
buffering under systemd, plus its own `-q` flag suppressing the one line that mattered "gM index ≠ gF index", with a regression test asserting `d2 $ gF1 $ gM2` is clean.
(track changes). Fixed both; verified live, restart not needed (already applied). - **PV013** — flags an orbit with **no** family mute.
- `take-lens.py selftest` added — exercises the trim/fade rules on synthetic input, since - `fix-mute-roles.py --check` exits 1 on drift — worth wiring into the pre-gig gate (#44).
two of them (the silence-bridge, the fade shape) never fire on real material and were
otherwise unverifiable. All pass. **PV013 caught a bug in the migrator that wrote it**, minutes after existing: the migrator
had its own orbit regex requiring `^dN $` and walked straight past
`d5 -- The Voice of Love` (no `$`, gates on a commented line). It now uses pvlint's parser
and owns none of its own. That miss had hidden 14 rewrites and 7 missing mutes.
---
Nothing here needs a reload or restart. Go play. 🤘 ## 7. Waiting on you — carried over, not urgent today
- **#12 the BPM arc**`124, 133, 89, 124, 124, 128, 160, 120, 160, 166, 129` has two big
drops (160→120→160). Your taste call, and it blocks #13 and #14.
- **#31 desire's bass** — four alternatives in `study/desire_bass_rhythm.tidal`, measured
to genuinely differ (3.0 / 4.0 / 4.5 / 5.75 onsets per bar). A/B them.
- **#86** — the 2-minute remap rollback drill, next time Ardour is closed.
- **take-94 mix v2**`mix/take94/take94_trimmed_v2.wav`, with the clamp+fade you asked
for. 18.75 min, peak -3.36 dBFS, all 5 silence gaps handled including your +18:00 one.
- **#110 USB safety take** — you said the fallback is the point but the reference take is
valuable too, so: both from one run. The mastered one is blocked on **#91** (record bus
~16 dB hot, 8 of 12 orbits over 0 dBFS — a fallback that clips isn't a fallback).
## 8. Found but couldn't act on
- **#112 — 14 corpus tracks don't compile at all.** Pre-existing, **none in the setlist**,
found while baselining the migration. Same class as desire's `plz` typo.
- **#56 xruns** — needs a gig-log session to analyse and I found none on disk. Your next
full run-through produces one.
...@@ -68,7 +68,16 @@ d5 $ gF3 $ gM3 -- Synth lapin speed ...@@ -68,7 +68,16 @@ d5 $ gF3 $ gM3 -- Synth lapin speed
-- lagTime = 0.12, filterRange = 6, width = 0.51, rq = 0.3; -- lagTime = 0.12, filterRange = 6, width = 0.51, rq = 0.3;
-- 18 │ -- 18 │
# width (range 0.2 0.8 "^33") -- /!\ FIXME EXPLOSIF /!\ # width (range 0.2 0.8 "^33") -- /!\ FIXME EXPLOSIF /!\
# filterRange (range 0 8 "^53") -- DIAGNOSED 2026-07-30, not yet fixed — needs PLN's ear, it changes the sound.
-- ^33 is an A/B knob, so BootTidal's #55 seed gives it 0 (see the seed policy:
-- "range <neutral> <extreme>, so 0 == neutral for effect knobs"). That makes this
-- line sit at width 0.2 AT BOOT — while the preset reference two lines up says
-- nominal is width = 0.51. So the synth starts at an extreme and the knob swings
-- it wildly THROUGH nominal rather than away from it. Same authoring shape
-- BootTidal calls out for piment_bresilien's `legato (range 0.05 2 "^52")`, whose
-- documented remedy is to fix the RANGE in the track, not special-case the seed.
-- Candidate: `range 0.51 0.8 "^33"` -> boots at nominal, knob only adds. Costs the
-- 0.2-0.51 downward half, which is why it is your call and not mine.
# filterRange (range 0 8 "^53") # filterRange (range 0 8 "^53")
# room 0.4 # dry 0.8 # room 0.4 # dry 0.8
# gain 1.5 # gain 1.5
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment