#pragma once #include #include "Params.h" namespace serum { // =========================================================================== // Mono filter with 7 models (Ladder LP/HP/BP, Diode, Comb, Formant, Screamer), // 6/12/24 dB slopes (ladder family) and per-sample drive + keytrack. All state // is clamped to prevent NaN/inf at extreme settings. // =========================================================================== class Filter { public: void prepare (double sampleRate, int maxBlockSize); void reset(); // Process a mono buffer in-place. cutoffNorm is 0..1 (mapped to 20Hz..20kHz). void process (float* samples, int numSamples, float cutoffNorm, float res, float drive, float keytrack, float noteHz, int type, int slope) noexcept; // Single-sample version (used by the comb/naive paths where convenient). float processSample (float in, float cutoffHz, float res, float drive, int type, int slope) noexcept; private: double sr = 44100.0; // TPT SVF state (also reused by formant/screamer). double ic1eq = 0.0, ic2eq = 0.0; double lastG = 0.0, lastK = 0.0; double a1 = 0.0, a2 = 0.0, a3 = 0.0; // Ladder stage state. std::array stage { { 0.0, 0.0, 0.0, 0.0 } }; // Comb delay line. std::vector combLine; int combWrite = 0; double combDamp = 0.0; // Formant: three parallel bandpass SVFs (state pairs). std::array, 3> formantState { { { { 0.0, 0.0 } }, { { 0.0, 0.0 } }, { { 0.0, 0.0 } } } }; void updateSvf (double g, double k) noexcept; double svfLow (double in, double g, double k) noexcept; double svfBand (double in, double g, double k) noexcept; double svfHigh (double in, double g, double k) noexcept; double ladder (double in, double g, double res, double drive, int stages, bool diode) noexcept; double comb (double in, double freqHz, double res, double drive) noexcept; double formant (double in, double morph, double res) noexcept; double screamer (double in, double cutoffHz, double res, double drive) noexcept; }; } // namespace serum