StateVariableFilter Logic


/** The type of the IIR filter */
Type type = Type::lowPass;

    /** Sets the cutoff frequency and resonance of the IIR filter.
        Note: The bandwidth of the resonance increases with the value of the
        parameter. To have a standard 12 dB/octave filter, the value must be set
        at 1 / sqrt(2).
    void setCutOffFrequency (double sampleRate, NumericType frequency,
                             NumericType resonance = static_cast<NumericType> (1.0 / MathConstants<double>::sqrt2)) noexcept
        jassert (sampleRate > 0);
        jassert (resonance > NumericType (0));
        jassert (frequency > NumericType (0) && frequency <= NumericType (sampleRate * 0.5));

        g  = static_cast<NumericType> (std::tan (MathConstants<double>::pi * frequency / sampleRate));
        R2 = static_cast<NumericType> (1.0 / resonance);
        h  = static_cast<NumericType> (1.0 / (1.0 + R2 * g + g * g));

    /** The Coefficients structure is ref-counted, so this is a handy type that can be used
        as a pointer to one.
    using Ptr = ReferenceCountedObjectPtr<Parameters>;

    Parameters() = default;
    Parameters (const Parameters& o) : g (o.g), R2 (o.R2), h (o.h) {}
    Parameters& operator= (const Parameters& o) noexcept    { g = o.g; R2 = o.R2; h = o.h; return *this; }

    NumericType g   = static_cast<NumericType> (std::tan (MathConstants<double>::pi * 200.0 / 44100.0));
    NumericType R2  = static_cast<NumericType> (MathConstants<double>::sqrt2);
    NumericType h   = static_cast<NumericType> (1.0 / (1.0 + R2 * g + g * g));


} // namespace dsp
} // namespace juce

Can anyone please explain this logic used for StateVariable Filter?
Thanks in advance.



You mean the assertions? The sample rate needs to have been set before setting the filter parameters (and cannot be 0), the resonance can’t be 0, and the cutoff frequency has to be between 0 and Nyquist, exclusive. Otherwise the coefficient calculation (which you can find derivations for in “the Art of VA Filter Design” by Zavalishin) will have zeros in denominators… which is not numerically stable.



NO, I meant what are the parameters g, R2 and h?
Also, from the book by Zavalishin, What type of it has been considered the linear or nonlinear?



Those are internal filter coefficients. g is the forward gain of the integrators inside the filter (the SVF uses 2, in series), R2 is usually denoted 2R in the literature (but variables can’t use numbers as their first character in C++), and it’s the internal feedback coefficient from the first integrator to the input, and h is a scaling factor to compensate for the gain of the entire filter. Zavalishin goes through how to derive those in the paper from the analog filter topology, the code you posted is just how they’re initialized in the filter.

The JUCE implementation is the linear model.