Introduce a CriticalSection controlLock separating control-thread state (matrix, macros, controlLfos) from audio-thread snapshots (audioMatrix, audioMacros, lfos). captureControls() copies under lock at the start of each processBlock; the audio thread never touches control state directly. Cache parameter values in an unordered_map keyed by string_view to avoid per-sample APVTS lookups. Prebuild wavetables in the constructor instead of lazy allocation. Resize mixBuffer only in prepare(), not per block. Render MIDI events at their sample positions using sub-block rendering with renderUntil(), so notes start at the correct sub-sample offset. Make RaveController non-destructive: replace APVTS mutation with a static apply() that boosts the RenderContext and FX slots for the current block only. Remove the snapshot/restore machinery. Make currentProgram atomic. Validate state I/O: check XML tag, clamp program index, sanitize LFO shape data, and use beginChangeGesture/endChangeGesture for RAVE toggle. Reset parameters to defaults before loading preset values.
39 lines
1.2 KiB
C++
39 lines
1.2 KiB
C++
#include "RAVEButton.h"
|
|
#include "SynthVoice.h"
|
|
#include "FXProcessor.h"
|
|
|
|
namespace serum
|
|
{
|
|
|
|
void RaveController::apply (RenderContext& context, FxSlotParams* slots, int numSlots) noexcept
|
|
{
|
|
// Boost the static rendering parameters.
|
|
context.oscA.unison = juce::jlimit (8, kMaxUnison, context.oscA.unison);
|
|
context.oscB.unison = juce::jlimit (8, kMaxUnison, context.oscB.unison);
|
|
context.oscA.spread = 1.0f;
|
|
context.oscB.spread = 1.0f;
|
|
context.oscA.detune = 1.0f;
|
|
context.oscB.detune = 0.7f;
|
|
|
|
// Apply drive boosts.
|
|
context.filters.f1Drive = 0.6f;
|
|
context.filters.f2Drive = 0.6f;
|
|
|
|
// Boost FX-specific params (Hyper intensity / Reverb mix).
|
|
if (slots == nullptr)
|
|
return;
|
|
for (int i = 0; i < juce::jlimit (0, kNumFxSlots, numSlots); ++i)
|
|
{
|
|
auto& slot = slots[i];
|
|
if (slot.type == (int) FxType::Hyper)
|
|
slot.p[0] = 1.0f; // OTT intensity 100%
|
|
else if (slot.type == (int) FxType::Reverb)
|
|
{
|
|
const float mix = std::isfinite (slot.mix) ? slot.mix : 0.0f;
|
|
slot.mix = juce::jlimit (0.0f, 1.0f, mix + 0.4f); // reverb send +6dB-ish
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace serum
|