docs: record the bake-prints-limiter track and close Phase Gamma

This commit is contained in:
2026-08-02 21:32:04 -04:00
parent 3313ac6b96
commit 53e7d35178
2 changed files with 64 additions and 48 deletions
+45
View File
@@ -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