Hi! I have a parameter in my plugin that changes the number of filters applied to the audio in series to have a smooth/hard cut at the target frequency. The problem is that when the user bypasses the processing or changes this number using the plugin UI controls I get a click/pop in the audio (audible). How can I solve this problem? thank you
Code:
void FilterExample::processBlock (AudioBuffer& buffer, MidiBuffer& midiMessages)
{
ScopedNoDenormals noDenormals;
auto totalNumInputChannels = getTotalNumInputChannels();
auto totalNumOutputChannels = getTotalNumOutputChannels();
//get parameters
float freqValue = *treeState.getRawParameterValue("cutoff");
int bladeState = (int) *treeState.getRawParameterValue("blades"); //let's say this is the number of consecutive filters
int powerStateRaw = (int)*treeState.getRawParameterValue("power");
bool powerState = powerStateRaw == 1;
if (!isBypassed) {
for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
buffer.clear (i, 0, buffer.getNumSamples());
dsp::AudioBlock<float> block(buffer);
//apply filtering
switch(bladeState) {
case 1: {
highPassFilter.process(dsp::ProcessContextReplacing<float>(block));
break;
}
case 2: {
highPassFilter.process(dsp::ProcessContextReplacing<float>(block));
highPassFilter1.process(dsp::ProcessContextReplacing<float>(block));
break;
}
case 3: {
highPassFilter.process(dsp::ProcessContextReplacing<float>(block));
highPassFilter1.process(dsp::ProcessContextReplacing<float>(block));
highPassFilter2.process(dsp::ProcessContextReplacing<float>(block));
break;
}
case 4: {
highPassFilter.process(dsp::ProcessContextReplacing<float>(block));
highPassFilter1.process(dsp::ProcessContextReplacing<float>(block));
highPassFilter2.process(dsp::ProcessContextReplacing<float>(block));
highPassFilter3.process(dsp::ProcessContextReplacing<float>(block));
break;
}
case 5: {
highPassFilter.process(dsp::ProcessContextReplacing<float>(block));
highPassFilter1.process(dsp::ProcessContextReplacing<float>(block));
highPassFilter2.process(dsp::ProcessContextReplacing<float>(block));
highPassFilter3.process(dsp::ProcessContextReplacing<float>(block));
highPassFilter4.process(dsp::ProcessContextReplacing<float>(block));
highPassFilter5.process(dsp::ProcessContextReplacing<float>(block));
break;
}
}
//update the filter state
*highPassFilter.state = *dsp::IIR::Coefficients<float>::makeHighPass(getSampleRate(), freqValue);
*highPassFilter1.state = *dsp::IIR::Coefficients<float>::makeHighPass(getSampleRate(), freqValue);
*highPassFilter2.state = *dsp::IIR::Coefficients<float>::makeHighPass(getSampleRate(), freqValue);
*highPassFilter3.state = *dsp::IIR::Coefficients<float>::makeHighPass(getSampleRate(), freqValue);
*highPassFilter4.state = *dsp::IIR::Coefficients<float>::makeHighPass(getSampleRate(), freqValue);
*highPassFilter5.state = *dsp::IIR::Coefficients<float>::makeHighPass(getSampleRate(), freqValue);
}
//check at the end of the block processing to avoid clicks
if(powerState) {
isBypassed = false;
}else {
isBypassed = true;
}
//std::cout << freqValue << " " << bladeState << " " << powerState << " " << std::endl;
}