Restore the bank fold and usage publish to the resume path, guard setActive against repeats, and make the meter fold's bound literal
The resume also hands back to a full reload when the fold moves the loaded capture's decode source, so the refs table and the audio cannot skew.
This commit is contained in:
+24
-6
@@ -17,12 +17,30 @@ separate: `setActive(false)` parks the decoded sample and destroys the voice sta
|
||||
decode; sounding voices are still destroyed across it (a surviving `live_` would be displaced
|
||||
into the drain slot and resurrect stale sustained voices as ghosts); an instance with nothing
|
||||
decoded still routes through the full reload, which is where the pre-v10 legacy lift lives; and
|
||||
`getLatencySamples()` still answers from the persisted enable, untouched by the cycle. The
|
||||
build shared by the reload, the voice-param rebuild and the reactivation was factored to one
|
||||
site so the three cannot drift on the generation stamp or the ring size. Daniel reversed the
|
||||
deferral (*"I thought we agreed to decouple the unnecessary functions from the reactivation
|
||||
path"*); Γ-F2 and Γ-F6 are untouched — dynamic latency ships, the deactivate/reactivate is
|
||||
still the accepted cost of the toggle, just a much cheaper one.
|
||||
`getLatencySamples()` still answers from the persisted enable, untouched by the cycle. The build
|
||||
shared by the reload, the voice-param rebuild and the reactivation was factored to one site so the three cannot drift
|
||||
on the generation stamp or the ring size. Daniel reversed the deferral (*"I thought we agreed
|
||||
to decouple the unnecessary functions from the reactivation path"*); Γ-F2 and Γ-F6 are untouched
|
||||
— dynamic latency ships, the deactivate/reactivate is still the accepted cost of the toggle,
|
||||
just a much cheaper one.
|
||||
|
||||
**`reloadInstrument` did three things, not one, and the resume path had to keep all three.** The
|
||||
first review pass discussed only the pre-v10 legacy lift; the other two were dropped silently and
|
||||
restored in the follow-up. `refreshRefsFromBank` — the recapture sync — and `publishUsage` — the
|
||||
`rsusage_` prune-protection write — are each a `GetProjExtState` plus a parse, neither disk nor
|
||||
decode, so both run on the resume path and the spec's "no disk I/O and no WAV decode" still holds
|
||||
exactly. This matters only with **no editor open**: `pollBankSync`, the only other route to
|
||||
either, has exactly one caller and it is the editor's sync tick. Restoring the refresh alone
|
||||
would have been worse than dropping it — the refs would name a recapture's new file while the
|
||||
parked PCM still played the old one — so the resume compares the selected ref across the fold
|
||||
(`sameDecodeSource`, `core/instrument/map/sample_map`) and hands back to the full reload when it
|
||||
moved. The decode is eliminated in the case that matters and re-run in the case that needs it.
|
||||
Three smaller consequences fell out of the same pass: `setActive` now treats a repeat of the
|
||||
state it already holds as a no-op (the base is an empty stub, so a repeated deactivate would have
|
||||
parked an empty optional over a still-valid sample); the park is disengaged before the build
|
||||
rather than left moved-from, so a throwing build cannot publish permanent silence; and
|
||||
`flushLatencyRestart` checks `restartComponent`'s `tresult` and rolls its announcement back on a
|
||||
refusal, since a latch on a value the host never took would strand its delay compensation.
|
||||
|
||||
### Comment-reduction pass (tree-wide, twelve parallel tracks)
|
||||
|
||||
|
||||
+13
-14
@@ -63,9 +63,8 @@ change, then advancing at 1/newDuration). **Phase Γ opened six [Daniel]-class f
|
||||
tracks below and indexed in `docs/product/instrument-control-surface.md` §8. **Γ-F6 closed
|
||||
with a correction to the analysis, not merely a ruling**: dynamic reported latency is routine
|
||||
for VST3 instruments and REAPER handles it as a matter of course; what makes the mandated
|
||||
restart expensive *here* is self-inflicted (`setActive(true)` calls `reloadInstrument`), so
|
||||
the cost is ours to reduce and the reduction is filed in `docs/TODO.md` rather than designed
|
||||
around.
|
||||
restart expensive *here* was self-inflicted (`setActive(true)` called `reloadInstrument`), so
|
||||
the cost was ours to reduce. **That reduction landed in Γ-W3** — see `docs/COMPLETED.md`.
|
||||
|
||||
**Γ-F3 was subsequently REVERSED and a seventh fork opened AND CLOSED, all by Daniel's later
|
||||
rulings of 2026-08-01.** Γ-F3 (*"the stage-time ceiling stays 2.0 s"*) is replaced by *"extend
|
||||
@@ -651,14 +650,15 @@ every parameter's **plain unit, range and display precision** (§6.7). Today the
|
||||
**What the Γ-F6 ruling changed in the analysis, not just in the plan.** Dynamic latency
|
||||
reporting is **routine** for VST3 instruments and REAPER handles it as a matter of course;
|
||||
the SDK's deactivate/reactivate requirement (`pluginterfaces/vst/ivsteditcontroller.h:105-108`)
|
||||
is the normal contract, not an exotic one. What makes the cycle expensive **here** is entirely
|
||||
our own doing: `ReaSamplerProcessor::setActive(true)` calls `reloadInstrument()` — a bridge
|
||||
read plus a full WAV re-decode (`reasampler_processor.cpp:89-97`) — where a typical plugin's
|
||||
`setActive` only allocates and frees buffers, and the deactivate side's freeing of
|
||||
`live_`/`draining_`/graveyard (`:98-107`) is likewise our own design. **The cost is therefore
|
||||
ours to reduce if it ever matters, and the reduction is decoupling reload from activation —
|
||||
not abandoning dynamic latency.** That improvement is filed as a `docs/TODO.md` entry with its
|
||||
trigger condition; it is not scheduled in this phase.
|
||||
is the normal contract, not an exotic one. What made the cycle expensive **here** was entirely
|
||||
our own doing: `ReaSamplerProcessor::setActive(true)` called `reloadInstrument()` — a bridge
|
||||
read plus a full WAV re-decode — where a typical plugin's `setActive` only allocates and frees
|
||||
buffers. **The cost was therefore ours to reduce, and the reduction was decoupling reload from
|
||||
activation — not abandoning dynamic latency.** **Landed in Γ-W3**: the activate branch
|
||||
(`reasampler_processor.cpp:86-132`) now resumes the voice state around a parked `SampleData`
|
||||
and reloads only when there is nothing to resume from or a bank refresh moved what the park was
|
||||
decoded from; the deactivate branch parks the PCM and frees everything else. Narrative and
|
||||
consequences are in `docs/COMPLETED.md`.
|
||||
|
||||
**Sequencing against Phase Ξ — the ordering claim is RETIRED and replaced by an owned
|
||||
correction.** This plan previously asserted that Γ must run before Ξ-W2 and called it *"a
|
||||
@@ -1421,9 +1421,8 @@ value semantics, any deck geometry, or the bake's reset *membership* (W3-T2's).
|
||||
nothing new is persisted and therefore it should not; if the `setState` verification says
|
||||
otherwise, it takes the reserved rung and says so.
|
||||
- **Closed, do not reopen:** Rate lifted from latched to live (§3.5 records the cost); the
|
||||
limiter enable made automatable (§3.8 — its one reopening condition is the `docs/TODO.md`
|
||||
reload/activation decoupling, and the answer is to do that first, not to re-litigate the
|
||||
classification).
|
||||
limiter enable made automatable (§3.8 — its one reopening condition was the reload/activation
|
||||
decoupling, which landed in Γ-W3, so the condition is discharged rather than pending).
|
||||
|
||||
---
|
||||
|
||||
|
||||
+9
-7
@@ -242,17 +242,19 @@ alpha and this entry is re-filed against the new value.
|
||||
|
||||
## The editor's drag state machine has no seam, and `reasampler_editor.h` is near the ceiling
|
||||
|
||||
**Context (Γ-W3, meter re-review).** `reasampler_editor.h` stands at **563 lines** against the
|
||||
~600-line ceiling — 37 lines of margin — and it keeps growing because every new surface on the
|
||||
**Context (Γ-W3, meter re-review).** `reasampler_editor.h` stands at **564 lines** against the
|
||||
~600-line ceiling — 36 lines of margin — and it keeps growing because every new surface on the
|
||||
Sample face adds its transient state there. The obvious seam is the drag state machine: `drag_`
|
||||
plus the per-gesture anchors it is read against.
|
||||
|
||||
**Why it was declined rather than taken.** `drag_` has **42 references across 13 shell TUs**
|
||||
(measured over `src/shell/instrument/*.cpp`; the declaration in the header is additional), and
|
||||
every input TU both writes it and branches on it. Extracting it is a real refactor of the
|
||||
editor's input half, not a header move — and doing it inside a wave whose subject is the MASTER
|
||||
deck would have put an unrelated high-blast-radius change in the same diff. Declining was right;
|
||||
leaving it unrecorded was not.
|
||||
(measured over `src/shell/instrument/*.cpp`; the declaration in the header is additional). Of
|
||||
the six input TUs, three write it and branch on it (`editor_input`, `_waveform`, `_curve`) and
|
||||
three only write it (`_chrome`, `_browse`, `_deck`) — which is what makes the anchor invariant
|
||||
observed rather than enforced. Extracting it is a real refactor of the editor's input half, not
|
||||
a header move — and doing it inside a wave whose subject is the MASTER deck would have put an
|
||||
unrelated high-blast-radius change in the same diff. Declining was right; leaving it unrecorded
|
||||
was not.
|
||||
|
||||
**The shape a fix would take.** A `DragState` type owning the kind plus its anchor payload,
|
||||
with the input TUs mutating it through named transitions rather than assigning `drag_` and its
|
||||
|
||||
@@ -1409,6 +1409,15 @@ back through the full reload, which is what keeps the pre-v10 legacy lift reacha
|
||||
untouched: dynamic latency ships and the deactivate/reactivate is still the accepted cost —
|
||||
it is simply a much cheaper one.
|
||||
|
||||
**What "cheaper" does NOT mean: skipping the bank fold.** `reloadInstrument` also runs the
|
||||
recapture sync and the `rsusage_` prune-protection publish, and with no editor open the
|
||||
activation is the only place either happens (`pollBankSync` runs off the editor's sync tick and
|
||||
nothing else). Both are a `GetProjExtState` plus a parse — neither disk nor decode — so both run
|
||||
on the resume path too, and a fold that moves the loaded capture's decode source hands back to
|
||||
the full reload rather than resuming PCM the bank has superseded. A resume that refreshed the
|
||||
refs without re-decoding would be the worst of the three: the table would name a recapture's new
|
||||
file while the voices played the old one.
|
||||
|
||||
---
|
||||
|
||||
## 8. Forks — SEVEN ruled (one later reversed), NONE open
|
||||
@@ -1484,7 +1493,7 @@ than just counting:
|
||||
4. **The verification requirements survive unchanged**, because they were always about the
|
||||
`kIoChanged` scar (a dual-mono capture panned hard right by a prior mid-session
|
||||
`restartComponent`), not about this flag.
|
||||
5. **The reduction is filed**, with a trigger condition, in `docs/TODO.md`.
|
||||
5. **The reduction was filed with a trigger condition and has since LANDED** (Γ-W3 — §7.11).
|
||||
|
||||
### 8.3 Γ-F7 — RULED: signal flow. The parameter order
|
||||
|
||||
|
||||
Reference in New Issue
Block a user