Hi,
I’m trying to make a filter in JUCE with sharp cutoff corners and steep slopes and cannot figure out how.
I want the same shape as the screenshot fabfilter.png, a setting in my FabFilter Pro-Q2.
The Pro-Q2 setting is a combined high pass filter (250Hz corner frequency, 36dB/octave, Q=1) and low pass filter (2500Hz corner frequency, 36dB/octave, Q=1)
As you can see, the Pro-Q2 is flat on top and steep on the sides.
The second screenshot plugindoctor,myfilter.png is what my JUCE filter is making. I’m using the default makeLowPass and makeHighPass filter objects. As you can see, the slopes are not sharp at all. The top is not flat at all.
The final screenshot is plugindoctor,fabfilter_and_myfilter.png showing both.
I know enough to realize I need to make custom filters, but how? Where do I start?
Here is my filter code; I put three filters in series to create 36dB/octave slopes:
from the constructor:
//hpf
double hpfCutoffFrequency;
dsp::IIR::Filter<float> hpfSignalLeft1;
dsp::IIR::Filter<float> hpfSignalRight1;
dsp::IIR::Filter<float> hpfSignalLeft2;
dsp::IIR::Filter<float> hpfSignalRight2;
dsp::IIR::Filter<float> hpfSignalLeft3;
dsp::IIR::Filter<float> hpfSignalRight3;
//lpf
double lpfCutoffFrequency;
dsp::IIR::Filter<float> lpfSignalLeft1;
dsp::IIR::Filter<float> lpfSignalRight1;
dsp::IIR::Filter<float> lpfSignalLeft2;
dsp::IIR::Filter<float> lpfSignalRight2;
dsp::IIR::Filter<float> lpfSignalLeft3;
dsp::IIR::Filter<float> lpfSignalRight3;
hpfCutoffFrequency = 250.0;
lpfCutoffFrequency = 2500.0;
from prepareToPlay:
hpfSignalLeft1.reset();
hpfSignalRight1.reset();
hpfSignalLeft2.reset();
hpfSignalRight2.reset();
hpfSignalLeft3.reset();
hpfSignalRight3.reset();
//each one is 12dB/oct
hpfSignalLeft1.coefficients = dsp::IIR::Coefficients<float>::makeHighPass (sampleRate, hpfCutoffFrequency);
hpfSignalRight1.coefficients = dsp::IIR::Coefficients<float>::makeHighPass (sampleRate, hpfCutoffFrequency);
hpfSignalLeft2.coefficients = dsp::IIR::Coefficients<float>::makeHighPass (sampleRate, hpfCutoffFrequency);
hpfSignalRight2.coefficients = dsp::IIR::Coefficients<float>::makeHighPass (sampleRate, hpfCutoffFrequency);
hpfSignalLeft3.coefficients = dsp::IIR::Coefficients<float>::makeHighPass (sampleRate, hpfCutoffFrequency);
hpfSignalRight3.coefficients = dsp::IIR::Coefficients<float>::makeHighPass (sampleRate, hpfCutoffFrequency);
lpfSignalLeft1.reset();
lpfSignalRight1.reset();
lpfSignalLeft2.reset();
lpfSignalRight2.reset();
lpfSignalLeft3.reset();
lpfSignalRight3.reset();
//each one is 12dB/oct
lpfSignalLeft1.coefficients = dsp::IIR::Coefficients<float>::makeLowPass (sampleRate, lpfCutoffFrequency);
lpfSignalRight1.coefficients = dsp::IIR::Coefficients<float>::makeLowPass (sampleRate, lpfCutoffFrequency);
lpfSignalLeft2.coefficients = dsp::IIR::Coefficients<float>::makeLowPass (sampleRate, lpfCutoffFrequency);
lpfSignalRight2.coefficients = dsp::IIR::Coefficients<float>::makeLowPass (sampleRate, lpfCutoffFrequency);
lpfSignalLeft3.coefficients = dsp::IIR::Coefficients<float>::makeLowPass (sampleRate, lpfCutoffFrequency);
lpfSignalRight3.coefficients = dsp::IIR::Coefficients<float>::makeLowPass (sampleRate, lpfCutoffFrequency);
from processBlock:
//do the highpass filtering in series to get 36dB/octave slope
//do the lowpass filtering in series to get 36dB/octave slope
if (channel == 0) {
channelData[sample] = hpfSignalLeft1.processSample(channelData[sample]);
hpfSignalLeft1.snapToZero();
channelData[sample] = hpfSignalLeft2.processSample(channelData[sample]);
hpfSignalLeft2.snapToZero();
channelData[sample] = hpfSignalLeft3.processSample(channelData[sample]);
hpfSignalLeft3.snapToZero();
channelData[sample] = lpfSignalLeft1.processSample(channelData[sample]);
lpfSignalLeft1.snapToZero();
channelData[sample] = lpfSignalLeft2.processSample(channelData[sample]);
lpfSignalLeft2.snapToZero();
channelData[sample] = lpfSignalLeft3.processSample(channelData[sample]);
lpfSignalLeft3.snapToZero();
}
if (channel == 1) {
channelData[sample] = hpfSignalRight1.processSample(channelData[sample]);
hpfSignalRight1.snapToZero();
channelData[sample] = hpfSignalRight2.processSample(channelData[sample]);
hpfSignalRight2.snapToZero();
channelData[sample] = hpfSignalRight3.processSample(channelData[sample]);
hpfSignalRight3.snapToZero();
channelData[sample] = lpfSignalRight1.processSample(channelData[sample]);
lpfSignalRight1.snapToZero();
channelData[sample] = lpfSignalRight2.processSample(channelData[sample]);
lpfSignalRight2.snapToZero();
channelData[sample] = lpfSignalRight3.processSample(channelData[sample]);
lpfSignalRight3.snapToZero();
}
Thanks,
Fred