Filter both channels using IIR Filter

I want to filter both channels in a VST plugin (IIR Filter). I use:

PluginProcessor.h:

dsp::ProcessorDuplicator<dsp::IIR::Filter<float>, dsp::IIR::Coefficients<float>> lowPassFilter;

PluginProcessor.cpp:

 void Circular_attemptAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
{
    ...
    dsp::ProcessSpec spec;
    spec.sampleRate = sampleRate;
    spec.maximumBlockSize = samplesPerBlock;
    spec.numChannels = getTotalNumOutputChannels();

    lowPassFilter.prepare(spec);
    lowPassFilter.reset();
}

...

void Circular_attemptAudioProcessor::processBlock (AudioBuffer<float>& buffer, MidiBuffer& midiMessages)
{
    ...
    for (int channel = 0; channel < totalNumInputChannels; ++channel)
    {
        ... 
        dsp::AudioBlock<float> block(buffer);
	    *lowPassFilter.state = *dsp::IIR::Coefficients<float>::makeLowPass(sampleRate_, 300.0f, 1.0f);
	    lowPassFilter.process(dsp::ProcessContextReplacing<float>(block));
        ...
    }
}

The result is, that I got very crackling sound. When I filter after the loop going through channels, everything is ok (but it filters AFTER all of the operations on the signal). But I need to filter inside of the loop, because I need to filter BETWEEN other operations in the loop. I understand the problem is, that I need to filter both channels separetly? How to do this?

There are other topics about similar problems but non of them has solved my problem. Thank you.

Well, let’s assume you have 2 channels, than the code snippet you posted will lead to the whole buffer, containing both channels being processed twice as the for loop will iterate over both channels. It is obvious that this leads to unwanted artifacts. Now if you want to do per-channel processing before your filter and after your filter, the easiest solution I see is to just use two loops, like that:

void Circular_attemptAudioProcessor::processBlock (AudioBuffer<float>& buffer, MidiBuffer& midiMessages)
{
    dsp::AudioBlock<float> block(buffer);

    for (int channel = 0; channel < totalNumInputChannels; ++channel)
    {
        // per channel work pre filtering
    }    
	
    lowPassFilter.process(dsp::ProcessContextReplacing<float>(block));    

    for (int channel = 0; channel < totalNumInputChannels; ++channel)
    {
        // per channel work post filtering
    } 
}

Another note: makeLowPass is not intended to be used during processBlock as it allocates memory. Especially as the values seem to fixed, there is no point in computing new coefficients over and over again. Better move it to your prepare function

1 Like