IIR FILTER + stereo operation


#1

Hello fellow Jucers,
i want to create a HighPass - LowPass filter plugin using the IIR filter,
in my PluginProcessor.h i have included as private:
IIRFilter monoFilterHighP, monoFilterLowP;
and my PluginProcessor.cpp looks like this:

void DaBorderAudioProcessor::prepareToPlay(double newSampleRate, int /*samplesPerBlock*/)
{
	// Use this method as the place to do any pre-playback
	// initialisation that you need..
	sampleRate = newSampleRate;

	monoFilterHighP.setCoefficients(IIRCoefficients::makeHighPass(newSampleRate, *LPFREQParam, q));
	monoFilterLowP.setCoefficients(IIRCoefficients::makeLowPass(newSampleRate, *HPFREQParam, q));

	reset();
}

void DaBorderAudioProcessor::processBlock(AudioBuffer<float>& buffer, MidiBuffer& midiMessages)
{
	auto totalNumInputChannels = getTotalNumInputChannels();
	auto totalNumOutputChannels = getTotalNumOutputChannels();


	for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
		buffer.clear(i, 0, buffer.getNumSamples());

	monoFilterHighP.setCoefficients(IIRCoefficients::makeHighPass(sampleRate, *LPFREQParam, q));
	monoFilterLowP.setCoefficients(IIRCoefficients::makeLowPass(sampleRate, *HPFREQParam, q));

	
	for (int channel = 0; channel < totalNumInputChannels; ++channel)
	{
		auto* channelData = buffer.getWritePointer(channel);

		monoFilterHighP.processSamples(channelData, buffer.getNumSamples());
		monoFilterLowP.processSamples(channelData, buffer.getNumSamples());
	}

} 

The problem is that i get some kind of unstable operation for the Hipass filter on the Right channel,
Any ideas?


#2

You called your filter correctly monoFilterXY… but then you process both channels through the same filter instance…

Since the filters are stateful, you need an instance per channel…


#3

You need separate filter objects for each audio channel.


#4

Many thanks!
i did the following:

PluginProcessor.h :
IIRFilter monoFilterHighPLeft, monoFilterLowPLeft , monoFilterHighPRight, monoFilterLowPRight;

PluginProcessor.cpp :

void DaBorderAudioProcessor::prepareToPlay(double newSampleRate, int /*samplesPerBlock*/)

monoFilterHighPLeft.setCoefficients(IIRCoefficients::makeHighPass(newSampleRate, *LPFREQParam, q));
	monoFilterLowPLeft.setCoefficients(IIRCoefficients::makeLowPass(newSampleRate, *HPFREQParam, q));
	monoFilterHighPRight.setCoefficients(IIRCoefficients::makeHighPass(newSampleRate, *LPFREQParam, q));
	monoFilterLowPRight.setCoefficients(IIRCoefficients::makeLowPass(newSampleRate, *HPFREQParam, q));


void DaBorderAudioProcessor::processBlock(AudioBuffer<float>& buffer, MidiBuffer& midiMessages)
{
	auto totalNumInputChannels = getTotalNumInputChannels();
	auto totalNumOutputChannels = getTotalNumOutputChannels();


	for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
		buffer.clear(i, 0, buffer.getNumSamples());

	monoFilterHighPLeft.setCoefficients(IIRCoefficients::makeHighPass(sampleRate, *LPFREQParam, q));
	monoFilterLowPLeft.setCoefficients(IIRCoefficients::makeLowPass(sampleRate, *HPFREQParam, q));

	monoFilterHighPRight.setCoefficients(IIRCoefficients::makeHighPass(sampleRate, *LPFREQParam, q));
	monoFilterLowPRight.setCoefficients(IIRCoefficients::makeLowPass(sampleRate, *HPFREQParam, q));

	//float * channelDataL = buffer.getWritePointer(0);
	
	for (int channel = 0; channel < totalNumInputChannels; ++channel)
	{
		//auto* channelData = buffer.getWritePointer(channel);
		float *dataLeft = buffer.getWritePointer(0);
		float *dataRight = buffer.getWritePointer(1);

		monoFilterHighPLeft.processSamples(dataLeft, buffer.getNumSamples());
		monoFilterLowPLeft.processSamples(dataLeft, buffer.getNumSamples());

		monoFilterHighPRight.processSamples(dataRight, buffer.getNumSamples());
		monoFilterLowPRight.processSamples(dataRight, buffer.getNumSamples());
	}
} 

and i still have the same problem…


#5

You no longer must have this loop in the code :

for (int channel = 0; channel < totalNumInputChannels; ++channel)

#6

Solved !!!
Many thanks!
Here is the code in case somebody is interested:

void DaBorderAudioProcessor::processBlock(AudioBuffer<float>& buffer, MidiBuffer& midiMessages)
{
	auto totalNumInputChannels = getTotalNumInputChannels();
	auto totalNumOutputChannels = getTotalNumOutputChannels();


	for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
		buffer.clear(i, 0, buffer.getNumSamples());

	monoFilterHighPLeft.setCoefficients(IIRCoefficients::makeHighPass(sampleRate, *LPFREQParam, q));
	monoFilterLowPLeft.setCoefficients(IIRCoefficients::makeLowPass(sampleRate, *HPFREQParam, q));

	monoFilterHighPRight.setCoefficients(IIRCoefficients::makeHighPass(sampleRate, *LPFREQParam, q));
	monoFilterLowPRight.setCoefficients(IIRCoefficients::makeLowPass(sampleRate, *HPFREQParam, q));

	float *dataLeft = buffer.getWritePointer(0);
	float *dataRight = buffer.getWritePointer(1);

	monoFilterHighPLeft.processSamples(dataLeft, buffer.getNumSamples());
	monoFilterLowPLeft.processSamples(dataLeft, buffer.getNumSamples());

	monoFilterHighPRight.processSamples(dataRight, buffer.getNumSamples());
	monoFilterLowPRight.processSamples(dataRight, buffer.getNumSamples());

}