is there an easy way of drawing the ladder filters frequency response? The IIR coefficients classes have the handy getMagnitudeForFrequency(). What’s the easiest way of doing this?
Thanks!
Edit: is there maybe a way of approximating the various modes using IIR coefficients?
Well, JUCE LadderFilter can be seen as a processing class not related with IIRFilter, even if it is made of 4 first order IIR filters in cascade and a feedback loop. So you can’t just get something which looks like IIR filter coefficients directly from it, unless you want to do the calculus of the (linear) transfer function by yourself.
However, you can still send an input which is one and a given number of zeroes through the process function, and then you do the FFT of the result to get the impulse response of the LadderFilter in the frequency domain
You need the transfer function. Then to get the response you compute the complex number result by plugging in the ratio of the frequency you want to the cutoff of the filter.
Here’s an example for a one-pole low-pass filter.
Transfer function is: H(s) = 1 / (1 + s)
Let: ratio = frequency_to_measure / filter_cutoff
Then H(i * ratio) = 1 / (1 + i * ratio)
Then you take the amplitude of the result for the frequency response or the phase of the result for the phase response.
Just do that with the transfer function for the ladder filter instead. As @IvanC pointed out this method can only give you the result of the linear version (without distortions). You can’t show the non-linear version because the response is dependent on the audio input.
@Holy_City just beat me to recommending this book.
Hi there,
This is a bit of a late reply but it would be useful for anyone in the future.
As @IvanC mentioned, you can get this by doing an fft.
std::pair<float,std::vector<float>> getMagnitudeResponse(float cutOff, float resonance, Mode mode)
{
// Create a ladder filter as described right now without drive
LadderFilter ladderFilter;
ladderFilter.setResonance(resonance);
ladderFilter.setMode(mode);
ladderFilter.setCutoffFrequencyHz(cutOff);
// Set a pretty low fft order
const int fftOrder = 6;
// set sample rate depending on mode and cutoff, this is done so we get maximum definition where we need it.
const float multiplier = mode == Mode::HPF24 || mode == Mode::HPF12 ? 16 : 4;
float sampleRate = cutOff * multiplier;
// set a blocksize of twice the fft size
const int blockSize = 2 * pow(2, fftOrder); // Double the fft order
//create the fft and the ladder filter
const dsp::FFT fastFourierTransform(fftOrder);
ladderFilter.prepareToPlay( int(sampleRate), blockSize,1);
// Pass in Impulse and process it 1,0,0,...
auto output = std::vector<float>(blockSize);
output[0] = ladderFilter.processSampleRaw(1.0f);
for(auto i = 1; i < output.size(); i++)
{
output[i] = ladderFilter.processSampleRaw(0.f);;
}
// perform fft
fastFourierTransform.performFrequencyOnlyForwardTransform(&output[0]);
// return the samplerate used and the output vector
return {sampleRate, output};
}
Then you can plot it easily using a
frequency = (sampleRate * x) / fftSize;
and transorming output[i] into y in the path, ideally using gainToDecibels.