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
+18
View File
@@ -10,6 +10,7 @@
#include <vector>
#include "core/audio/peaks.h"
#include "core/instrument/engine/live_params.h"
#include "core/instrument/engine/play_params.h"
#include "core/instrument/engine/voice.h"
@@ -106,6 +107,23 @@ private:
// one per the documented policy. Always returns a valid index (maxVoices >= 1).
std::size_t allocateVoice();
// --- Live-parameter observation (live_params.h) ---
// The ONE place the seqlock is read: at block start and at each note-on, on the audio
// thread, never per frame. A torn or never-published read leaves the last good snapshot
// in place rather than spinning. Returns whether a NEW generation landed.
bool refreshLive();
// Block-boundary refresh: pushes a newly-observed generation into every sounding voice,
// which glides toward it. No-op when nothing changed (and when no block is attached).
void applyLiveToActive();
// The one restart path: start the voice, hand it the live values outright (it has nothing
// to glide from), and stamp its age. Shared by the poly steal and both mono restarts so
// no restart site can miss the live handoff.
void startVoice(Voice& voice, int note, int velocity);
instrument::engine::LiveValues live_{};
std::uint32_t liveGeneration_ = 0; // last generation observed; 0 = none yet
bool haveLive_ = false;
// Count of active Preserve-engine voices (for the Preserve cap). Rescanned per note-on
// (cheap: bounded by maxVoices) rather than maintained as a running tally.
std::size_t activePreserveVoices() const;