#pragma once #include "../SynthVoice.h" void NeuralSynthVoice::renderADSR(int numSamples, int numCh) { // ================================================================ // Filter with per-sample ADSR modulation (poly) // ================================================================ const bool enabled = shared.filterOn && shared.filterOn->load() > 0.5f; // Update filter type every block (cheap) const int ftype = (int) std::lround (juce::jlimit (0.0f, 2.0f, shared.filterType ? shared.filterType->load() : 0.0f)); switch (ftype) { case 0: svf.setType (juce::dsp::StateVariableTPTFilterType::lowpass); break; case 1: svf.setType (juce::dsp::StateVariableTPTFilterType::highpass); break; case 2: svf.setType (juce::dsp::StateVariableTPTFilterType::bandpass); break; default: break; } const float qOrRes = juce::jlimit (0.1f, 10.0f, shared.filterResonance ? shared.filterResonance->load() : 0.7f); svf.setResonance (qOrRes); const float baseCutoff = juce::jlimit (20.0f, 20000.0f, shared.filterCutoff ? shared.filterCutoff->load() : 1000.0f); const float envAmt = shared.fenvAmount ? shared.fenvAmount->load() : 0.0f; for (int i = 0; i < numSamples; ++i) { const float envVal = filterAdsr.getNextSample(); const float cutoff = juce::jlimit (20.0f, 20000.0f, baseCutoff * std::pow (2.0f, envAmt * envVal)); svf.setCutoffFrequency (cutoff); if (enabled) { for (int ch = 0; ch < numCh; ++ch) { float x = tempBuffer.getSample (ch, i); x = svf.processSample (ch, x); tempBuffer.setSample (ch, i, x); } } } }