Bake reset: assert the limiter and bake Hold land neutral, prove the loop returns parked, and baseline the render's identity path

resetAfterBake is unchanged — every value already resets by construction. The render prints master gain but not the limiter, so §3.4's rationale is wrong; the invariant is corrected.
This commit is contained in:
2026-08-02 07:21:19 -04:00
parent f60c05c042
commit e2981e83ee
5 changed files with 225 additions and 29 deletions
+3 -2
View File
@@ -21,8 +21,9 @@ decision about what the render made obsolete.
loop runs to `BakePlan::renderFrames()` and stops. That is why a Gate bake with a sustain
loop active terminates: the gate is released at `noteOffFrame` so the tail is real, but
even a pathological envelope cannot run past the window.
- **The whole signal chain is printed, master gain included** — the gain multiply in
`bake_render.cpp` carries the argument for why.
- **The voice chain and master gain are printed; the limiter is not.** The gain multiply in
`bake_render.cpp` carries the argument for the gain, and `bake_reset.h` records where the
printed master stage stops.
- **A degenerate or unholdable window is refused, not rendered.** `planBake` refuses a
collapsed window, a non-positive rate, a window that rounds to no frames, and one past
`kMaxBakeFrames` — an unbounded window is a `bad_alloc` inside a UI tick, and the
+3 -1
View File
@@ -17,4 +17,6 @@ reasampler_test(bake_window LINK bake_plan bake_render)
# sample_map carries InstrumentParams, which is the whole of what a reset rewrites.
reasampler_pure_library(bake_reset SOURCES bake_reset.cpp LINK PUBLIC sample_map)
reasampler_test(bake_reset LINK bake_reset)
# loop_marks is a TEST-only edge: it defines what a neutral loop looks like on the band, so
# the reset's loop assertions read it rather than restating it.
reasampler_test(bake_reset LINK bake_reset loop_marks)
+4
View File
@@ -13,6 +13,10 @@ namespace reasampler::instrument::bake {
// The two surfaces a bake resets. Master gain lives on the processor rather than in the
// parameter set; it is answered here because renderBake prints it into the file (see
// bake_render.cpp's gain multiply) rather than left to the shell.
//
// Gain is the ONLY master-stage control the render prints — the limiter runs in the
// processor's block, off the bake path — so "the bake prints the gain" does not generalize
// to the master stage as a whole, and cannot be used to classify anything else on it.
struct BakeReset {
map::InstrumentParams params;
double masterGainLinear = 1.0; // unity — renderBake printed the dialed gain