Commit the limiter's audible state on the click and defer only the host's latency restart
setInstrumentParams now arms a sticky pending restart that flushLatencyRestart drains from the sync tick; setState and the bake's adopt flush at their own tails.
This commit is contained in:
@@ -236,15 +236,23 @@ public:
|
||||
void setMasterGainLinear(double linear); // clamped to [0, masterGainMaxLinear()]
|
||||
|
||||
// The master-bus limiter's single enable (persisted in the parameter set). UI thread only:
|
||||
// a thin wrapper over setInstrumentParams, the one funnel that both mirrors the flag and
|
||||
// requests the host's kLatencyChanged restart, which the SDK requires be issued from the UI
|
||||
// thread and which process() must therefore never trigger. Setting the value it already
|
||||
// holds is a no-op, so repeated clicks on one segment cost no restart.
|
||||
// a thin wrapper over setInstrumentParams, the one funnel that mirrors the flag onto the
|
||||
// audio thread INLINE — the sound follows the click — and only ARMS the host's latency
|
||||
// restart. Setting the value it already holds is a no-op, so repeated clicks on one segment
|
||||
// cost no restart.
|
||||
bool limiterEnabled() const {
|
||||
return limiterEnabled_.load(std::memory_order_relaxed);
|
||||
}
|
||||
void setLimiterEnabled(bool on);
|
||||
|
||||
// Delivers the armed kLatencyChanged restart, at most once per armed window, and does
|
||||
// nothing when none is armed. Split off the commit because the SDK requires this on the UI
|
||||
// thread AND a host may service it synchronously — deactivate/reactivate, which reaches our
|
||||
// setActive(true) and its reloadInstrument — so it must never run nested inside a mouse
|
||||
// handler. The editor's sync tick is the general drain; the two callers that can commit with
|
||||
// no editor open (setState, adoptBakedCapture) flush themselves at their own tails.
|
||||
void flushLatencyRestart();
|
||||
|
||||
// Fires a one-shot preview note-on/off through the live VoiceEngine — the same
|
||||
// noteOn/noteOff host MIDI uses, so a preview is a real voice (counts against voice
|
||||
// count, can steal/be stolen, respects Poly/Mono + Retrigger/Legato). Off the audio
|
||||
@@ -471,6 +479,11 @@ private:
|
||||
// getLatencySamples answers from.
|
||||
instrument::engine::Limiter limiter_;
|
||||
std::atomic<bool> limiterEnabled_{false};
|
||||
// Set by the commit funnel when the enable actually changed, cleared only by
|
||||
// flushLatencyRestart. A sticky bool and not a count on purpose: the host is being told to
|
||||
// re-ASK, so N changes before one flush need exactly one restart, and whatever
|
||||
// getLatencySamples answers at that moment is the truth being announced.
|
||||
std::atomic<bool> latencyRestartPending_{false};
|
||||
|
||||
// What the audio thread publishes about the output bus each block, relaxed. The peaks and
|
||||
// minGain ACCUMULATE (max / min) across every block since the UI last read, and
|
||||
|
||||
Reference in New Issue
Block a user