Commit cc9cbf48 by PLN (Algolia)

feat(take-lens): pack a take so it travels with its performance — and fix the trim PLN caught

Two things in one file, both from the same evening's practice recording.

=== PART 1: `pack` — the performance must travel with the audio (#106, #107)

"ensure recordings have the midi too, keep this from blowing up tracking either
ardour rec or compressing to avoid storing hours of no-move?"

Today the audio is permanent and the performance is not. Ardour's sources live
forever under the session; the MIDI and the track timeline sit in a gig-log
directory that prune() deletes on a timer. So the 29862 CC events that explain
take 94 were on a countdown while the audio they explain was not. `pack` writes a
sidecar next to the audio: meta.json (window, sr, subtype, per-orbit peak dBFS,
silent orbits, xrun delta, gear + boot state), midi.jsonl (every cc/note/track/mark
record in the window, copied verbatim out of the log so pruning cannot reach it),
and edl.json.

The sidecar states its own honest limit in a field: gig-log COALESCES CC per
(port, channel, controller) per second, keeping count + first/last/min/max. That is
a faithful summary of a knob sweep and is what makes the log cheap, but a .mid
rendered from it would be a reconstruction, not a recording. The JSONL is the truth.

`--compress` then wavpacks every source and verifies each one with `wvunpack -vm`
before reporting a single byte saved — an archiver that reports a ratio without
checking is reporting a hope. The .wav is NEVER deleted; removal stays a separate
human step after the take has been heard. FLAC was rejected outright: it cannot
store 32-bit float, and routing through s32 would hard-clip the 8 orbits sitting
over 0 dBFS while looking like a win on the silent one.

Two measurement bugs found by running it on real data rather than trusting it:
 - xrun is a RUNNING TOTAL in gig-log's `s` records, not a per-tick delta (its own
   CUMULATIVE tuple exists for exactly this mistake). Summing it reported 58,668,469
   xruns for a 21-minute take. Rebased to last-minus-first: 230, a real number.
 - Records are not events. A `cc` record is a one-second bucket carrying `n`, so
   printing the record count understated the performance 25x (1167 vs 29862).

=== PART 2: the trim threshold was protecting every bad transition

PLN heard the first machine-trimmed mix and found the hole: "silence around 18 is
not normal its a bad transition ahah in a real mixing work wed cut it proper and
fade or at least trim most". The gap he heard WAS detected and reported, and
survived anyway. SILENT_RUN_S was 20 s; the three gaps that made it into the mix
measured 17 s, 18 s and 11 s. Every one sat just under the bar. A threshold chosen
so the trimmer could never eat a musical break had silently become a threshold that
preserves every failed transition instead.

Three changes, all of them his rule rather than a tuning:

1. CLAMP, don't binary-cut. The bar drops to 10 s, but a detected silence is no
   longer removed whole — the last 2 s before the music resumes is kept as a
   breath. That is "or at least trim most" implemented literally, and it makes the
   lower threshold safe: the worst case if the rule fires on something musical is
   now a shortened rest, not a missing one. classify() computes both the detected
   region and the removed region so the report and the mixer cannot disagree.

2. FADE every seam. Every cut this tool had ever made was a butt-join, which in a
   live room is a click. Each removal now fades out into the cut and back in out of
   it over 250 ms, applied sample-accurately — the old mixer decided keep/drop per
   one-second block by its midpoint, quantising every boundary to +-0.5 s.
   Verified on the re-rendered take: max sample-to-sample step at the five seams is
   0.0001-0.0029 against a p99.99 of 0.0562 for the take as a whole, i.e. the joins
   are 20-100x below ordinary musical transients.

3. BRIDGE blips. A dead patch is rarely clean end to end, and one orbit's tail
   crossing -60 dBFS for a second splits it into pieces that each fall under the
   bar. Only single-orbit blips are bridged: a real hit lights several orbits, and
   that is what keeps this from swallowing a one-shot.

Result on take 94: 143 s trimmed instead of 119 s, all five gaps closed including
the one at +18.0 min he named, output 18.75 min, peak -3.36 dBFS.

=== `selftest`

Added because two of these rules could not be validated on real material — the
bridge fires zero times on take 94 and a correct fade is inaudible by construction.
A rule you have never seen fire is a hope, not a rule. It found a bug on the first
run, in the test's own arithmetic: asserting "no span survives a multi-orbit hit"
was wrong because the left half is exactly SILENT_RUN_S long and qualifies by
itself. The property that actually matters is that no trimmed span ever CONTAINS a
moment when the music was playing, and that is what it now asserts.

Correction to a verification, worth recording: the first check of the re-rendered
mix reported an 11 s silence still present. It did not exist. I measured the output
against -60 dBFS while the mix carries a uniform -16 dB, so I was testing at an
effective -44 dBFS at source. At the matched threshold exactly one rest over 4 s
remains, 9.25 s, correctly left alone as musical. The right lens per control, again.
parent b5061e23
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