docs: record Phase Gamma Wave 2's two landed tracks in COMPLETED

This commit is contained in:
2026-08-02 06:41:24 -04:00
parent 782f50c859
commit bf7840020e
+84
View File
@@ -1049,3 +1049,87 @@ excess 18.52 %, pitch-synchronous excess 0.00 %** — PSOLA eliminates that corn
than regressing it, with every splice at n = 1 landing exactly one source period away.
**These figures are a one-machine, Debug-build measurement against the named control arm,
not a general performance claim.**
### Γ-W2-T1 — pitch-rate-deck
PITCH became PITCH/RATE: three knobs (`Key Trk | Rate | Pitch`) under the existing
Varisp|Presrv toggle, both new controls wired through the engine. Rate is 50200 % on a
taper linear in semitones over ±12 (the stated exception to the centre-expansion law),
note-on latched; Pitch is a ±24 st baseline offset, live. Keytrack × rate × pitch-offset
compound into a single read-increment multiply — the per-sample path gained nothing.
Merged as `9dbb8b8`. Spent the phase's second payload rung, v16, as a strict suffix; a
v15 blob lifts to rate 100 % / pitch 0 st.
**`isLiveDeckParam` was renamed `deckParamCommit`** and now returns a three-state
`LiveCommit` (`Live` / `NoteOnLatched` / `Reload`) rather than a bool — one predicate
widened, not a second mechanism. **Γ-W4-T1 derives the VST3 exposed parameter set from
this predicate**, so the classification is load-bearing two waves out.
**The clamp question the plan left open at `[propose at review]` was resolved as one
clamp:** `clampStretchRate` at the stretcher, with the taper taking its bounds as
parameters and `deck_values` aliasing them from `engine::kStretchRateMin`/`Max`.
**Code review found one Critical, fixed before merge:** the resample bake derived its
frame window without the two new fields while rendering *with* them, so a bake at any
non-unity Rate — or, under Varispeed, a downward Pitch — wrote a truncated file into the
bank. Fixed by deriving the window from the rate the voice actually reads at; the
regression test judges against a measured reference render rather than a recomputed
formula, and was proved non-vacuous by reverting the fix (every non-unity case fails).
**A ruling folded in during remediation:** Pitch was an uncompensated stage-time coupling
under Varispeed — a Trigger AHD's wall-clock attack was invariant under Rate but scaled
with Pitch. Pitch is now compensated; key-track and velocity remain deliberately
uncompensated, because those are shipped sounds whose compensation would break
bit-identity at non-root notes.
**A Varispeed golden hash was added**, honestly labelled: unlike the Preserve constants
(witnessed against pre-track commit `0a7778b`), it was captured from the remediation
commit itself, so it stands as a witness for the *next* track rather than proof of this
one.
### Γ-W2-T2 — loop-crossfade-ux
An explicit loop enable, a legible mark grammar, and the crossfade painted where it is
heard. **No format change** — no `ComponentState` version moved, no new persisted field,
`resolveLoop` untouched, audio unchanged. The enable **is** `SampleLoop::hasLoop`, whose
provenance changes from marker-gesture-derived to user-owned, with the gestures as
shortcuts onto it. Merged as `a8e30a9`. A new pure module,
`core/instrument/ui/loop_marks`, holds the state machine (`resolveLoopMarks`/
`applyLoopMarks`); the four marks (START/LOOP/END/XFADE) get one grammar — line + shaped
cap + label, the cap being the grip — with cap/label/suppression geometry pure and
unit-tested.
**The crossfade moved to `[loopEnd crossfade, loopEnd)`** and draws as a
top-and-bottom edge wedge, never a second fill; the loop fill's peak alpha stays exactly
0.20.
**START draws in `overlay/trace`, NOT `accent/primary` as the spec table states**
because `accent/primary` *is* the waveform fill, so a primary START would measure 1:1
against the material it marks. `overlay/trace` measures 3.071:1 against the fill and
3.065:1 against `bg/base`, clearing the 3:1 non-text floor on both. **This is a
deliberate deviation from `docs/product/instrument-control-surface.md` §6.3's table**,
and the spec is what is wrong.
**Code review found three Majors, all fixed before merge:** a parked-vs-off state leak
where dragging START on a fresh capture silently converted "never set" into "LOOP OFF";
three text draws landing on the lime waveform fill at 1.58:1 and 1.10:1 (fixed with a
`bg/base` scrim at alpha 0.90, solved for the binding case rather than chosen by eye — it
lands at 4.666:1 / 8.091:1 and is pinned in `test_theme.cpp`); and a per-mouse-move
bridge read plus bank parse in the hover path, now memoized against the existing key
struct.
**`docs/TODO.md`'s "Pre-existing staged-envelope-node shadow at zero-attack" entry was
resolved incidentally** — giving START a cap is what closed it — and rewritten in place
with the recorded outcome by the track itself.
**One thing is deliberately NOT settled and is recorded here as open, not as accepted:**
the audible wedge draws `accent/secondary` against the `overlay/trace` envelope trace at
**1.60:1** against a 3:1 floor. The 0.20 fill-alpha constraint is met and the
pre-existing accepted 2.25:1 pair is unmoved, but the under-floor *extent* inside the
loop span grows from two 2 px marker columns to two `crossfadeWidth × 10 px` bands. No
alpha fixes it — the pair is intrinsic to teal-on-violet. **Daniel has this: he is
judging it visually in the DAW and has not yet ruled.**
**Neither track has been verified in a running DAW; both are asserted in CTest only.**
The full test suite passes on the merged result — **99/99, Debug config, on one
machine** — not a general cross-platform or Release-config claim.