docs: record the bake-prints-limiter track and close Phase Gamma
This commit is contained in:
@@ -1249,6 +1249,51 @@ limiter. Until that lands this is a recorded, known limitation, not an oversight
|
||||
|
||||
**Neither track has been verified in a running DAW; both are asserted in CTest only.**
|
||||
|
||||
### Γ-W3-T3 — bake-prints-limiter
|
||||
|
||||
The bake's master stage now prints the limiter as well as the gain multiply, closing the
|
||||
audible gap Γ-W3-T2 recorded and left open: a capture baked with the limiter engaged
|
||||
returns limited audio rather than unlimited audio. `renderBake`
|
||||
(`core/instrument/bake/bake_render.cpp`) instantiates its own `Limiter` — the same
|
||||
bake-only-engine precedent its `VoiceEngine` already set — never linked into
|
||||
`reaper_reasampler`; `src/app/CMakeLists.txt`'s exclusion comment names the limiter
|
||||
alongside `sampler_core`/`pitch_shift`/the filter, so the extension's link graph gains no
|
||||
new edge.
|
||||
|
||||
**The lookahead needed compensation, which was open at spec time.** The limiter delays its
|
||||
output by `kLimiterLookaheadSeconds` (0.002 s = 96 samples at 48 kHz), so the render's
|
||||
buffers carry `renderFrames() + flushFrames` frames, the extra span fed silence rather than
|
||||
more rendered audio, and the capture is read out starting at `leadInFrames + flushFrames`
|
||||
instead of `leadInFrames` alone — the file is the same frames it would be bypassed, not the
|
||||
same capture shifted 2 ms late.
|
||||
|
||||
**A sequencing trap, recorded inline at the call site.** `Limiter::prepare()` ends by
|
||||
calling `reset()`, which snaps to whatever the enable target already is, so the render calls
|
||||
`setEnabled(true)` before `prepare()`. Reversed, the limiter would take its live-engage path
|
||||
instead — `process()`'s prime-then-fade — muting and then fading in the first ~12 ms of
|
||||
every capture (the delay-line prime plus `kLimiterMuteSeconds`, per `limiter.h`).
|
||||
|
||||
**The bypassed path is unchanged.** `test_bake_render.cpp` asserts bypass ≡ engaged
|
||||
bit-for-bit under the ceiling (a ramp fixture at unity gain, verified against the source
|
||||
sample for sample too) and separately confirms the printed-limiter path holds the ceiling
|
||||
and stays stereo-linked under a DC fixture driven well past it; repeat bakes stay
|
||||
bit-identical with the limiter engaged as well, since `renderBake` builds a fresh `Limiter`
|
||||
per call and `prepare()` zeroes every one of its state fields.
|
||||
|
||||
**Double-limiting is a named boundary, not a defect** (`bake/CLAUDE.md`): a printed capture
|
||||
replayed through an engaged limiter is limited twice. The post-bake reset ordinarily
|
||||
prevents it, since `limiterEnabled` is not on the survive list.
|
||||
|
||||
**`bake/CLAUDE.md`'s invariant is corrected alongside the code.** The text Γ-W3-T2 left in
|
||||
place ("the limiter is not printed") is replaced with "the whole chain is printed — voice,
|
||||
master gain, then the limiter, in the processor's own order," and the track's three
|
||||
`[propose at review]` open questions are answered inline in the same section: the bake
|
||||
instantiates its own `Limiter`; the lookahead does need in-render compensation, exactly the
|
||||
above; and yes, this track also corrects the invariant text rather than leaving it to a
|
||||
later pass.
|
||||
|
||||
**Not verified in a running DAW — CTest-asserted only.**
|
||||
|
||||
### Γ-W4-T1 — vst3-parameter-set
|
||||
|
||||
The instrument now reports its automatable parameters to the host: 44 of 44 issue, under a
|
||||
|
||||
+19
-48
@@ -597,6 +597,9 @@ system's is in **`docs/product/parameter-automation.md` §§6–10**. Read §1.2
|
||||
table) and §7 (collisions) before dispatching any track here — every number in this phase is
|
||||
derived there, and `docs/TODO.md`'s old deck-rework geometry is superseded.
|
||||
|
||||
**All four waves have landed — Phase Γ is complete.** W1 through W4 each carry their own
|
||||
landed note below; see `docs/COMPLETED.md` for every track's full narrative.
|
||||
|
||||
**Fork state — SEVEN ruled, ONE OF THEM LATER REVERSED, NONE OPEN.** Indexed at spec §8,
|
||||
folded into the tracks below:
|
||||
- **Γ-F1** — `kEditorMinHeight` stays **680**.
|
||||
@@ -1013,9 +1016,9 @@ than re-derived. **T2 depended on Phase Ξ** — `Ξ-W2-T1 (resample-bake-chain)
|
||||
first, the phase's only external gate — see `docs/COMPLETED.md` for the full narrative of each
|
||||
landed track.
|
||||
|
||||
**Two tracks have landed** — Γ-W3-T1 (`deck-reflow`) and Γ-W3-T2 (`bake-reset-amendment`) — see
|
||||
`docs/COMPLETED.md` for the full narrative of each. **A third track is now open and has not
|
||||
run:** Γ-W3-T3 (`bake-prints-limiter`), added below on Daniel's ruling of 2026-08-02.
|
||||
**All three tracks have landed** — Γ-W3-T1 (`deck-reflow`), Γ-W3-T2
|
||||
(`bake-reset-amendment`), and Γ-W3-T3 (`bake-prints-limiter`) — see `docs/COMPLETED.md` for
|
||||
the full narrative of each.
|
||||
|
||||
**None of the three tracks takes a payload rung.** T1 was layout only; T2 changed a reset list,
|
||||
not a format; T3 changes what the render's audio contains, not what is stored.
|
||||
@@ -1066,56 +1069,24 @@ field-by-field assertions over two independently-dialled fixtures, never struct
|
||||
mutation-verified spot-check sweep confirming both fixtures actually moved every asserted field
|
||||
off its default.
|
||||
|
||||
**One invariant correction:** `bake/CLAUDE.md` had claimed the whole signal chain prints, master
|
||||
gain included. It doesn't — the render's gain multiply is the only master-stage value it
|
||||
prints; the limiter runs in the processor's block, off the bake path entirely.
|
||||
|
||||
**Outstanding, not closed by this track.** A capture baked with the limiter engaged comes back
|
||||
unlimited — a real audible gap, and Daniel has ruled that a future track will change the bake to
|
||||
print the limiter. **That track is now Γ-W3-T3, below.**
|
||||
**One invariant correction, at the time this track landed:** `bake/CLAUDE.md` had claimed the
|
||||
whole signal chain prints, master gain included. It didn't yet — the render's gain multiply was
|
||||
the only master-stage value it printed; the limiter ran in the processor's block, off the bake
|
||||
path entirely, so a capture baked with the limiter engaged came back unlimited. **Γ-W3-T3
|
||||
(below) has since closed that gap** — the limiter is printed too now, and `bake/CLAUDE.md`'s
|
||||
invariant text is corrected again to match.
|
||||
|
||||
**Neither track has been verified in a running DAW; both are asserted in CTest only.**
|
||||
|
||||
#### Γ-W3-T3 — `bake-prints-limiter`
|
||||
|
||||
**Not started. Opened by Daniel's ruling, 2026-08-02.**
|
||||
|
||||
**Goal.** Print the limiter through the bake's master stage, so a capture baked with the
|
||||
limiter engaged returns limited audio rather than unlimited audio.
|
||||
|
||||
**Why this exists.** Γ-W3-T2's own finding disproved the premise
|
||||
`docs/product/instrument-control-surface.md` §3.4's reset classification rested on:
|
||||
`renderBake` (`core/instrument/bake/bake_render.cpp`) prints only a flat master-gain multiply,
|
||||
and the limiter (`core/instrument/engine/limiter`) runs in the processor's `process()` block,
|
||||
off the bake path entirely. Until this track lands, this is a recorded, known limitation — see
|
||||
`docs/COMPLETED.md`'s Γ-W3-T2 entry — not an oversight.
|
||||
|
||||
**Consolidates:** nothing from the seventeen. A correction, on the same footing as Γ-W3-T2 (see
|
||||
"Work in this plan that is not one of the seventeen").
|
||||
|
||||
**Spec:** none yet written. This ruling postdates §3.4 and has no product-doc section of its
|
||||
own; §3.4 is superseded on this one point, which a future scoping pass of this track should
|
||||
correct there as well as here.
|
||||
|
||||
**Surface boundary — likely, not yet confirmed against a full scoping pass:** owns
|
||||
`core/instrument/bake/bake_render` (the gain-multiply step, extended to also run the signal
|
||||
through a limiter), consuming `core/instrument/engine/limiter` — not owned, not modified. Does
|
||||
not own the processor's live block, the limiter DSP itself, the parameter surface, or
|
||||
`bake_reset` (the limiter-enable reset classification is already Γ-W3-T2's, landed).
|
||||
|
||||
**Open questions — none of this is ruled yet, only the goal is:**
|
||||
- **[propose at review]** Whether the bake instantiates its own `Limiter` — mirroring
|
||||
`renderBake`'s existing bake-only `VoiceEngine`, off the audio thread, never linked into
|
||||
`reaper_reasampler` — or reaches the limiter's settled behavior some other way. The
|
||||
bake-only-engine precedent (`bake/CLAUDE.md`) argues for the former.
|
||||
- **[propose at review]** Whether the limiter's lookahead needs any accommodation in an
|
||||
offline, non-realtime render — the processor's `getLatencySamples()` PDC report exists for
|
||||
the live block, and a bake is not on that clock, so this may be a non-issue; it has not been
|
||||
checked.
|
||||
- **[propose at review]** Whether this track also corrects `bake/CLAUDE.md`'s invariant text
|
||||
("the limiter is not [printed]") alongside the code, once scoped in full.
|
||||
- **No [Daniel] question on the goal itself** — the ruling above is the goal; what is open is
|
||||
the mechanism, not whether to do it.
|
||||
**Landed** — see `docs/COMPLETED.md` for the full narrative. The bake's master stage now
|
||||
prints the limiter as well as the gain multiply: `renderBake` instantiates its own `Limiter`
|
||||
(the bake-only-engine precedent, never linked into `reaper_reasampler`), the lookahead is
|
||||
compensated inside the render (an extra `flushFrames` of silence past the window, the capture
|
||||
read out at `leadInFrames + flushFrames`), and `bake/CLAUDE.md`'s invariant text is corrected
|
||||
alongside the code. All three of the track's `[propose at review]` open questions are
|
||||
answered in that entry.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user