Draw frequency response of ladder filter

Hi,

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?

Hello ! Are you talking about the JUCE class LadderFilter or your own implementation ?

The JUCE class

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

This pdf has a chapter on the ladder filter including the analog and iirc discretized transfer functions. It’s been awhile since I used it.

You can also just use the filter coefficients to get the transfer function.

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.

Here’s some code even:

float ratio = frequency_to_measure / filter_cutoff;
std::complex<float> numerator(1.0f, 0.0f);
std::complex<float> denominator(1.0f, ratio);
std::complex<float> result = one_pole_mult / one_pole_shift;
float amplitude_response = std::abs(result);
float phase_response = std::arg(result);

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.

The question was more about a built in solution like with the IIR coefficients which would have been handy. But there doesn’t seem to be one.

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.

Hope this helps

2 Likes