IIR Filters and threads


#1

I have a bank of 8 IIR filters with 2 sets of very specific non-user adjustable parameters. Meaning, the user can select which bank, A or B, but nothing else. I’m wondering what’s the best/proper way to change the coefficients in response to the UI change.

Must I change the coefficients in the audio thread to prevent pops? Or can I change them in the UI thread risk free?

Also, do I need to call IIRFilter::reset() if I change the type of filter?

Thanks.


#2

I might get it wrong, but eventually the coefficients will be changed in the audio thread. So why not make a routine right there? I would think of something like this in the processBlock:

void ExampleAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
{
const int totalNumInputChannels = getTotalNumInputChannels();
const int totalNumOutputChannels = getTotalNumOutputChannels();

if(chosenBank != previousBank) {
  applyNewCoefficients();
  previousBank = chosenBank;
}

//[…]
}

Maybe you need to apply interpolation somehow to avoid clicks and pops, which is a topic that I’m not familiar yet…


#3

We’ve solved it by just cross fading quickly between A and B. For us A was filter off and B was filter on and after the crossfade had finished, we only calculated the filter the user had picked. Maybe interpolating coefficients works as well, but I’m sure it has to be done in the audiothread.

Could be some issues during the crossfade with phase relationship, if this is important to you.


#4

There are not thousands of solutions. If you want to keep using the same filter objects, you need to monitor that a change is requested, and to perform it in the beginning of your processBlock. It will be “thread-safe” but you’ll get artefacts by doing so because IIRFilter algorithms use the transposed direct form II, unless the change isn’t that heavy. Resetting the state variables or not doing anything to them won’t change that fact.

A solution to remove these artefacts is to have two objects A and B, and interpolate between their output when you need to use a new one.

The best solution would be to use a TPT structure for the implementation instead of the TDF2 from IIRFilter. You can see some information about that on KVR, it has been introduced by Vadim Zavalishin in a public PDF book. And you can also wait for my talk at ADC 2016 for more information :wink:


#5

Thank you everyone for the replies. I think best solution for me will be to just have another set of filters and do a quick crossfade when the user changes the filter bank.

Sometimes I get so caught up in trying to be as efficient as possible in the audio thread that I miss the forest for the trees. Thanks again.


#6

You could try:

  • Convert the IIR filter in a cascade of 2nd-order sections
  • Convert the 2nd-order sections into a state-space representation
  • Interpolation of the state-space coefficients; all coefficients simultaneously across some common interpolation kernel.

AFAIK this is the most elegant solution, but may require quite some work. At least you don’t have to cross-fade between two filter outputs, which can cause comb-filtering artefacts due to mismatching phase responses.