docs: close Phase Ξ — the popup abandoned by ruling, the bake window derives itself, and Γ's rung ladder shifts to v15
This commit is contained in:
@@ -754,3 +754,62 @@ bank-format change under the current deserializer, which fails the whole bank bl
|
||||
an out-of-range value — it wants its own decision); and `instrument_bake` copies the
|
||||
interleaved render buffer into a `std::vector<double>` for the WAV build, roughly
|
||||
doubling peak memory for a large bake.
|
||||
|
||||
### Ξ-W3-T1 — capture-signal-popup (spec abandoned by ruling; shipped as derived bake window)
|
||||
|
||||
Phase Ξ's final track, and Phase Ξ is now complete. What `docs/PLAN.md` specified was a
|
||||
popup menu letting the user hand-program the capture signal: note length as a
|
||||
musical-division picker (1/64 to 64/1, dotted and triplet), start/end offsets editable in
|
||||
both ms and beats, velocity, and a preview trigger auditioning the programmed note, under
|
||||
the acceptance criterion "preview and bake cannot diverge."
|
||||
|
||||
**What shipped instead, and why — the spec and the landed code diverge substantially and
|
||||
deliberately, by Daniel's ruling, not by shortfall.** The popup was built (~1500 lines)
|
||||
and then abandoned unmerged. Daniel, verbatim: *"I didn't realize you had already derived
|
||||
a usable window. The manual stuff for baking a specific midi length was just an idea, if
|
||||
we have a smarter, fewer-clicks way of doing it, that is ideal. I just don't want to lose
|
||||
anything when we bake. We can abandon the whole parameterized bake window if we can safely
|
||||
derive the window in gate and trigger modes."* An audit then established, with executable
|
||||
tests (`tests/test_bake_window.cpp`), that the window derives losslessly everywhere except
|
||||
one irreducible case. What actually shipped, in `src/core/instrument/bake/`:
|
||||
|
||||
- **The bake window derives itself.** Trigger derives from the play span; Gate *without*
|
||||
an active sustain loop derives from source exhaustion + release; Gate *with* an active
|
||||
loop takes one user value, because a loop sounds for as long as it is held and no
|
||||
derivation can supply a duration.
|
||||
- **One control: "Hold,"** a musical-division picker in the chrome row, visible and
|
||||
settable only when Gate + an active sustain loop. `bakeWindowNeedsHold` is the predicate
|
||||
and it reads the ENGINE's loop fold (`resolveLoop`) rather than the loop fields.
|
||||
- **Velocity comes from the instance's persisted preview velocity**, not a hard-coded 100
|
||||
— three velocity curves are live, so the velocity is a property of the sound being
|
||||
printed.
|
||||
- **No preview trigger, and no popup at all.** The chrome-row play button stays a pure
|
||||
MIDI trigger; bake parameters are their own thing. Daniel's ruling: *"play button is
|
||||
pure MIDI trigger, Bake parameters are their own thing."* So the plan's acceptance
|
||||
criterion 2 ("preview and bake cannot diverge") and its preview-trigger behavior bullet
|
||||
are **retired by ruling.**
|
||||
- **Three truncation bugs that pre-existed on `dev` were found and fixed:** a drawn EG
|
||||
plus a stale stored `%`-length lost up to the whole take; the Preserve pitch engine's
|
||||
window closed on the exact frame the terminal declick ramp began, ending files on a
|
||||
full-scale hard cut; and the Gate hold length quantized onto a musical ladder that
|
||||
**saturated at 384 beats**, cutting any source past it mid-sound (at 120 BPM, anything
|
||||
from 192 s up — a full-mix bounce).
|
||||
- **An invariant was deliberately amended:** `note/CLAUDE.md`'s "note length stays
|
||||
musical-division-only" is superseded — a note length now carries EITHER an exact
|
||||
duration (every derived path) or a musical division (the Hold picker only).
|
||||
Quantizing a derived length is what caused the saturation truncation.
|
||||
- Two undefined-behaviour paths closed as fallout: a NaN `keyTrack` from a corrupt payload
|
||||
reached a narrowing cast on the per-sample audio path, and a misaligned payload tail
|
||||
could fabricate a value rather than degrade to absent.
|
||||
- Payload rung **v14** consumed (the Hold division).
|
||||
|
||||
**Not verified in a live REAPER session** — worth carrying forward as owed: the "Bake
|
||||
Hold" label fitting its 56 px cell, the Hold knob's duration-ordered travel, and the
|
||||
control's appearance/disappearance on the 500 ms sync tick.
|
||||
|
||||
**Deferred, not done — logged to `docs/TODO.md`:** the loop intrinsic is folded twice
|
||||
(the editor's `pickedMarkers` resolves it from the live bank blob first, the processor's
|
||||
`reloadInstrument` resolves it from the instance ref via `resolveCapture`), so the two can
|
||||
disagree whenever a bank blob's loop for a capture differs from the copy in the instance's
|
||||
own refs table. Pre-existing — `bakeWindowNeedsHold` is only a new *consumer* of
|
||||
`pickedMarkers`, not the origin of the divergence.
|
||||
|
||||
Reference in New Issue
Block a user