instrument: deliver continuous playback params live to sounding voices via a seqlock block, holding normalized stage position across time edits

This commit is contained in:
2026-07-30 21:03:05 -04:00
parent 7bd911d58b
commit 1dade0bfcf
25 changed files with 1352 additions and 66 deletions
+14
View File
@@ -67,6 +67,20 @@ scattered `#ifdef`s in the VST shell, except the one described below).
- **Verify** all identity/factory wiring against the vendored Steinberg SDK
(`DEF_CLASS2` / `INLINE_UID` / `FUID` from `pluginfactory.h` + `funknown.h`).
**The three commit tiers (Θ-W3).** An edit reaches the audio by exactly one of three routes, and
which route a control takes is decided once, by the pure `isLiveDeckParam` predicate — see
`core/instrument/CLAUDE.md`'s "Live parameter delivery" for the rule and its rationale.
1. **Full reload**`reloadInstrument`: bridge read, WAV re-decode, fresh engine, snapshot swap.
2. **Engine rebuild**`rebuildVoiceEngine`: same drain-slot swap around the already-decoded
`SampleData`. Voice count / mode / mono trigger.
3. **Live**`publishLiveParams` (and `masterGain_`, the original of the shape): a lock-free
publish the audio thread observes at block boundaries. No rebuild, no snapshot, no disk.
`liveParams_` is declared ahead of the instrument slots so it outlives every snapshot pointing at
it. The editor's `commitLive` is the tier-3 peer of `commitAndReload` and still writes the
parameter set, so persistence is unchanged — `getState` serializes `params_`, never a reload
artifact, and the reload was never the persistence trigger.
**Non-goals / guardrails.**
- The instrument never captures and never inserts into the arrange. Playback is a
read-only act over the bank. Any instrument path that captures, places a timeline