Commit be43aff1 by PLN (Algolia)

gig: 9 of 9 off-map orbits were ghosts, and no Master to fall back on

Corrections and additions to the Thu-24 reconstruction, all from sources
that should have been read first.

The fader claim was wrong on cause: I blamed the LCXL lap reset, but every
one of those journal lines says 'effect knobs -> 0' and '(no CC sent)' —
Tidal params, not Ardour gain. The 2026-08-14 forensics had already settled
it as a faithful save of faders in motion. Same verdict now reached from
the audio side, which is the new part.

Verified rather than assumed: dN == Ardour 'Tidal NN', from BootTidal.hs,
fold-orbits.py and check-mix.py independently. That is what makes the
missing stem d8.

New: all nine off-map orbits were declared by the immediately preceding
track, so #68's ghost mechanism is now measured in audio, with levels —
take_5_drops ran its whole 8m43s under piment_bresilien's orbit 04 at 99%
active. And the answer to 'why no Master to recover from': Master is a bus
Ardour cannot arm, while the out-of-Ardour net gig_record.sh has no unit
and no inventory entry, so nothing ever asserts it.

Dropped: a killed-recorder verdict that was an artifact of reporting on a
sliced log, a laptop-speaker inference the data does not support, and a
13-of-15 peak count that should have been 12 of the 13 captured.
parent b3546c65
......@@ -39,8 +39,17 @@ percussive material is not an optimisation, it is a wrong answer.
- **Orbit 08 was never armed** (`rec-enable value="0"`, alone among 12), and the
control map lists it in all 15 tracks. No file was created — an absent stem,
not a silent one.
- **No MIDI from either recorder.** gig-log bound seq port `133:0` at 00:59 and
never rebound; Ardour's `Keys` wrote 24 files of 26 bytes each.
- **No MIDI at all**: gig-log bound seq port `133:0` at 00:59 and never rebound.
Zero control moves for the whole set. (Ardour's `Keys` track is not a second
chance — nothing routed the board to it.)
- **No Master either.** `Master` is a bus: no playlist, no `rec-enable`. Ardour
cannot arm it. The out-of-Ardour safety net `tools/gig_record.sh` exists, is
item 9 of the RUNBOOK, and has never been started on this machine — no
`recordings/` dir, no systemd unit, no entry in `rig_units.py`.
- **#68 measured in audio for the first time.** Nine orbits sounded off-map;
**9 of 9** were declared by the immediately preceding track. Two at 99% active:
`take_5_drops` ran its whole 8m43s with `piment_bresilien`'s orbit 04 — the
loudest orbit of the night — still underneath it.
## Sel (the shareable learning)
**The lens that saved the night was not built for it.** gig-log has a MIDI lens,
......@@ -54,11 +63,13 @@ first record to the last: Ardour's own transport feedback never once said
Redundancy is not three copies of the good instrument. It is four instruments
that fail differently.
Corollary, learned the same morning: **the session file no longer holds the mix
you played.** Nine of twelve faders read −∞ in `Tidal Live.ardour`, saved at
19:44:41, twenty-six seconds after a surface `lap reset` zeroed the board. The
stems prove those faders were up — orbit 04 sits at a −17 dBFS median and is the
loudest orbit in 13 of 15 tracks. Audit the artifact, not the config.
Corollary, and it closes an old file: **the session save does not hold the mix you
played.** Nine of twelve faders read −∞ in `Tidal Live.ardour` (saved 19:44:41)
while the stems, written post-fader, are loud. `2026-08-14-ardour-inf-forensics.md`
had already ruled out automation and corruption and called it a faithful photograph
of wherever the physical faders were at save time. This is the same verdict reached
from the opposite side — for the first time with the audio to prove the routes were
live. Audit the artifact, not the config.
## Hameçon (hook)
"I forgot to hit record." Ninety-four minutes later the laptop could still name
......@@ -67,7 +78,8 @@ the LEDs.
## Sillage (what it unlocks)
- Mastering can start: 11 stems, 76m19s, t0 = 18:27:41.201, per-orbit levels done.
- Peaks over 0 dBFS on 13 of 15 tracks (worst +7.7) — the limiter was working.
His ear decides whether that is the sound.
- Peaks over 0 dBFS on 12 of the 13 captured tracks (worst +7.7) — the limiter was
working. His ear decides whether that is the sound.
- A REC reminder is now buildable **and** the lens it must not use is identified.
- Two open holes with names: orbit 08's arm, and gig-log's MIDI rebind.
- Three open holes with names: orbit 08's arm, gig-log's MIDI rebind, and
`gig_record.sh` having no unit in the inventory that asserts it.
......@@ -18,6 +18,12 @@ uses audio to guess a name.
track uses. Independent of gig-log; it survived the gig where
gig-log's MIDI lens did not (it had bound port 133:0 at 00:59 and
never rebound, so `cc` is empty for the whole set).
ORBIT NUMBERING, verified not assumed: `dN` is `xfade N . (|< orbit N-1)`
(BootTidal.hs:215-226), fold-orbits.py:166 states "orbit k is played by `dk`",
and check-mix.py's docstring diagnoses "`d9`-`d12` make no sound" as the
`Tidal 09`..`Tidal 12` faders being shut — so LCXL column N == dN == Ardour
stem `Tidal NN`, one-to-one across all three layers.
stems full-resolution 1 s RMS/peak per orbit from the Ardour take. Ground
truth for what actually reached the DAW.
......@@ -27,8 +33,11 @@ measured INSIDE those windows.
TWO READINGS THAT ARE NOT ERRORS
* an orbit MAPPED BUT QUIET — a knob existed, the orbit stayed under the
floor. Same reading as an unresolved sample name: normal, never an error.
* an orbit HEARD OFF-MAP — it played with no knob on the surface. Can also be
a previous pattern still running, so it is reported, not interpreted.
* an orbit HEARD OFF-MAP — it sounded with no knob painted for it. Usually
#68: `dN $ ...` replaces orbit N and says nothing about the others, so
every orbit the outgoing track declares and the incoming one does not keeps
running underneath (see tools/orphan-orbits.py). The `ghost` field says
whether the previous track declared it; that is a mechanism, not a fault.
DECIMATION IS A TRAP HERE. The first pass read 4096 of every 48000 frames and
the window kept landing between hits, so most orbits looked 0% active. Every
......@@ -124,8 +133,8 @@ def stem_levels(stem_dir: Path, take: str) -> tuple[dict[int, dict], float, floa
# ── lenses ───────────────────────────────────────────────────────────────────
def gig_log(log: Path, day: str, lo: str, hi: str):
"""(eval events, rec transitions, session stats) inside the window."""
evals, recs, samples = [], [], []
"""(eval events, rec transitions, 1 Hz samples, MIDI events) in the window."""
evals, recs, samples, midi = [], [], [], []
for line in log.open(errors="replace"):
if not line.strip():
continue
......@@ -146,7 +155,9 @@ def gig_log(log: Path, day: str, lo: str, hi: str):
recs.append(r)
elif k == "s":
samples.append(r)
return evals, recs, samples
elif k in ("cc", "note"):
midi.append(r)
return evals, recs, samples, midi
def surface_loads(day: str, lo: str, hi: str):
......@@ -179,7 +190,7 @@ def db(x: float) -> float:
def build(args) -> dict:
day = args.date
lo, hi = args.window
evals, recs, samples = gig_log(Path(args.log), day, lo, hi)
evals, recs, samples, midi = gig_log(Path(args.log), day, lo, hi)
loads = surface_loads(day, lo, hi)
if not loads:
raise SystemExit("surface lens empty — is lcxl3-driver's journal still there?")
......@@ -241,6 +252,8 @@ def build(args) -> dict:
row["mapped_but_quiet"] = [o for o in s["orbits_mapped"]
if o in orbits and o not in heard]
row["heard_off_map"] = [o for o in heard if o not in s["orbits_mapped"]]
prev = seq[i - 2]["orbits_mapped"] if i > 1 else []
row["ghost_of_previous"] = [o for o in row["heard_off_map"] if o in prev]
row["peak_db"] = max(v["peak_db"] for v in lv.values())
row["loudest_orbit"] = max(lv, key=lambda o: lv[o]["rms_p50_db"])
row["levels"] = lv
......@@ -259,7 +272,7 @@ def build(args) -> dict:
"captured_pct": round(100 * dur / (seq[-1]["end"] - seq[0]["start"])),
"orbits_missing_from_take": missing,
"rec_lens_conflicts": len(conflicts),
"midi_cc_in_window": 0 if not any(r.get("k") == "cc" for r in samples) else None,
"midi_events_in_window": len(midi),
"planned_not_played": [p for p in planned if p not in played],
"played_not_planned": [p for p in played if p not in planned],
"post_set_loads": post,
......@@ -303,6 +316,10 @@ def main() -> int:
print(f" head lost: {out['head_lost_s']//60}m{out['head_lost_s']%60:02d}s")
if out["orbits_missing_from_take"]:
print(f" orbits with NO stem: {out['orbits_missing_from_take']}")
print(f" MIDI events logged during the set: {out['midi_events_in_window']}")
off = sum(len(r.get("heard_off_map") or []) for r in out["tracks"])
gh = sum(len(r.get("ghost_of_previous") or []) for r in out["tracks"])
print(f" orbits heard off-map: {off}, of which #68 ghosts of the previous track: {gh}")
print()
print(table(out))
if out["played_not_planned"]:
......
......@@ -14,7 +14,7 @@
8
],
"rec_lens_conflicts": 4579,
"midi_cc_in_window": 0,
"midi_events_in_window": 0,
"planned_not_played": [],
"played_not_planned": [
"sunny_side_up"
......@@ -147,6 +147,9 @@
"heard_off_map": [
12
],
"ghost_of_previous": [
12
],
"peak_db": -4.1,
"loudest_orbit": 1,
"levels": {
......@@ -271,6 +274,10 @@
4,
9
],
"ghost_of_previous": [
4,
9
],
"peak_db": 7.7,
"loudest_orbit": 4,
"levels": {
......@@ -399,6 +406,10 @@
5,
12
],
"ghost_of_previous": [
5,
12
],
"peak_db": 5.3,
"loudest_orbit": 4,
"levels": {
......@@ -523,6 +534,9 @@
"heard_off_map": [
9
],
"ghost_of_previous": [
9
],
"peak_db": 1.4,
"loudest_orbit": 4,
"levels": {
......@@ -650,6 +664,9 @@
"heard_off_map": [
4
],
"ghost_of_previous": [
4
],
"peak_db": 5.1,
"loudest_orbit": 4,
"levels": {
......@@ -769,6 +786,9 @@
"heard_off_map": [
7
],
"ghost_of_previous": [
7
],
"peak_db": 4.2,
"loudest_orbit": 4,
"levels": {
......@@ -897,6 +917,7 @@
12
],
"heard_off_map": [],
"ghost_of_previous": [],
"peak_db": 5.3,
"loudest_orbit": 4,
"levels": {
......@@ -1021,6 +1042,7 @@
12
],
"heard_off_map": [],
"ghost_of_previous": [],
"peak_db": 6.7,
"loudest_orbit": 4,
"levels": {
......@@ -1139,6 +1161,7 @@
11
],
"heard_off_map": [],
"ghost_of_previous": [],
"peak_db": 7.6,
"loudest_orbit": 4,
"levels": {
......@@ -1260,6 +1283,7 @@
12
],
"heard_off_map": [],
"ghost_of_previous": [],
"peak_db": 2.6,
"loudest_orbit": 4,
"levels": {
......@@ -1388,6 +1412,9 @@
"heard_off_map": [
1
],
"ghost_of_previous": [
1
],
"peak_db": 4.7,
"loudest_orbit": 4,
"levels": {
......@@ -1503,6 +1530,7 @@
7
],
"heard_off_map": [],
"ghost_of_previous": [],
"peak_db": 3.5,
"loudest_orbit": 4,
"levels": {
......@@ -1627,6 +1655,7 @@
10
],
"heard_off_map": [],
"ghost_of_previous": [],
"peak_db": 5.8,
"loudest_orbit": 5,
"levels": {
......
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