#pragma once #include "../SynthVoice.h" void NeuralSynthVoice::renderFlanger(int numSamples, int numCh) { // ================================================================ // Flanger (pre-filter) – manual per-sample to set varying delay // ================================================================ auto& flanger = chain.get(); const bool enabled = shared.flangerOn && shared.flangerOn->load() > 0.5f; if (enabled) { const float rate = shared.flangerRate ? shared.flangerRate->load() : 0.0f; float lfoPhase = shared.flangerPhase ? shared.flangerPhase->load() : 0.0f; const float flangerDepth = shared.flangerDepth ? shared.flangerDepth->load() : 0.0f; // ms const float mix = shared.flangerDryMix ? shared.flangerDryMix->load() : 0.0f; const float feedback = shared.flangerFeedback ? shared.flangerFeedback->load() : 0.0f; const float baseDelayMs = shared.flangerDelay ? shared.flangerDelay->load() : 0.25f; for (int i = 0; i < numSamples; ++i) { const float in = tempBuffer.getReadPointer (0)[i]; const float lfo = std::sin (lfoPhase); const float delayMs = baseDelayMs + 0.5f * (1.0f + lfo) * flangerDepth; const float delaySamples = juce::jmax (0.0f, delayMs * 0.001f * (float) spec.sampleRate); flanger.setDelay (delaySamples); const float delayed = flanger.popSample (0); flanger.pushSample (0, in + delayed * feedback); const float out = in * (1.0f - mix) + delayed * mix; for (int ch = 0; ch < numCh; ++ch) tempBuffer.getWritePointer (ch)[i] = out; lfoPhase += juce::MathConstants::twoPi * rate / (float) spec.sampleRate; if (lfoPhase > juce::MathConstants::twoPi) lfoPhase -= juce::MathConstants::twoPi; } } }