Make spline EG drags audible live: held and new notes follow a dragged knot
Contours ride their own seqlock block into a double-buffered engine copy, and the swap step is smoothed. Each drag move publishes contours without a model write; release still commits and reloads.
This commit is contained in:
@@ -23,6 +23,7 @@
|
||||
#include "core/instrument/map/sample_map.h" // InstrumentParams (the one parameter set)
|
||||
#include "core/instrument/map/component_state_io.h" // ComponentState codec
|
||||
#include "core/instrument/engine/limiter.h" // the master bus's post-gain limiter
|
||||
#include "core/instrument/engine/live_contours.h" // LiveContourBlock (the drawn-contour block)
|
||||
#include "core/instrument/engine/live_params.h" // LiveParams (the live-parameter block)
|
||||
#include "core/instrument/engine/meter_accumulate.h" // the meter's block-rate folds + consume
|
||||
#include "core/instrument/param/param_id.h" // the frozen ParamId space + DeckParam binding
|
||||
@@ -31,6 +32,7 @@ namespace reasampler::vst {
|
||||
|
||||
using instrument::map::ComponentState;
|
||||
using instrument::map::InstrumentParams;
|
||||
using instrument::map::PlaySeconds;
|
||||
using instrument::map::SampleRefEntry;
|
||||
using instrument::map::SampleRefs;
|
||||
using instrument::map::kPreviewVelocityDefault;
|
||||
@@ -206,6 +208,11 @@ public:
|
||||
// bakes and publishes). UI thread; serialized against reloadInstrument's own publish. Returns drainAutomationToModel's release proof (automation_channel.h); other callers ignore it.
|
||||
AutomationChannel::ReleaseProof publishLiveParams();
|
||||
|
||||
// Publishes `play`'s three drawn contours to every sounding voice WITHOUT writing the
|
||||
// model — the contour drag's courier (this directory's CLAUDE.md, the authority table).
|
||||
// UI thread; serialized against reloadInstrument's own contour publish.
|
||||
void publishLiveContours(const PlaySeconds& play);
|
||||
|
||||
// Per-instance channel mode (mono | stereo), guarded by channelModeMutex_, never read
|
||||
// on the audio thread. Decode policy only (downmix vs L/R split) — the output bus is
|
||||
// fixed stereo, so a mode change never renegotiates host I/O.
|
||||
@@ -387,6 +394,10 @@ private:
|
||||
// Both live_ and draining_ observe this same block — a block owned by a snapshot would
|
||||
// leave the drain's still-sounding voices deaf to the knob under them.
|
||||
instrument::engine::LiveParams liveParams_;
|
||||
// The drawn-contour block, SampleData::liveContours' one target, under liveParams_' ordering
|
||||
// constraint and for its reason. No automation merge: no contour is a host parameter, so both
|
||||
// engines read the model/editor publish directly.
|
||||
instrument::engine::LiveContourBlock liveContours_;
|
||||
// The block the ENGINE reads, and the ONE thing SampleData::live points at. Written only by
|
||||
// the audio thread, which merges liveParams_ with the host's automation points once per block
|
||||
// and republishes ONLY when the RESULT moved — so neither an unchanged model nor a lane
|
||||
@@ -404,10 +415,10 @@ private:
|
||||
// The host lane's state and its release protocol; automation_channel.h owns the mechanism and
|
||||
// this directory's CLAUDE.md the authority model it enforces.
|
||||
AutomationChannel automation_;
|
||||
// Serializes liveParams_.publish's two writer sites (reloadInstrument, publishLiveParams)
|
||||
// only — separate from reloadMutex_ so a knob drag's publish never blocks behind a
|
||||
// reload's WAV decode. The audio thread never takes this; process() only reads via
|
||||
// LiveParams::read's lock-free seqlock retry.
|
||||
// Serializes the writer sites of liveParams_ (reloadInstrument, publishLiveParams) and of
|
||||
// liveContours_ (reloadInstrument, publishLiveContours) only — separate from reloadMutex_ so
|
||||
// a drag's publish never blocks behind a reload's WAV decode. The audio thread never takes
|
||||
// this; it only reads via the seqlock's lock-free retry.
|
||||
std::mutex livePublishMutex_;
|
||||
// The rate the loaded capture was decoded/built at, so a live republish resolves the
|
||||
// stored wall-clock seconds to exactly the frames the built SampleData carries. 0 = nothing
|
||||
|
||||
Reference in New Issue
Block a user