IIR filter control and addition


#1

good day all :slight_smile:

I am trying to run 1 audio signal through 3 filters. a low shelf, a band pass and a high shelf.
The idea is to have variable pots like that on a mixer.
As yet all they do is change the gain of the output signal. so you could say I’m getting ahead of myself but I can’t work out how addFrom() or getFrom() work :slight_smile:

I have set up a buffer for each of the filters and made them the filters i need. I have 3 sliders that control the gain within them, for example:
lowFilter->makeLowShelf(sampleRate, 200.0, 1.0, bassGain);
my thought process was that i need to add each of the filtered signals into a mixedBuffer and have that as my output instead of bufferToFill. this way when you adjust the relative gain the signal will be boosted or attenuated.

this code is contained within an audioSource that is called by the audio I/O callback in my main app component.
What i want is the output signal to be the combination of the filtered signal :slight_smile:

Any help will be greatly appreciated.

code :

[code]//==============================================================================
//Audio
//==============================================================================
void Player::prepareToPlay (int samplesPerBlockExpected,double sampleRate)
{
resamplingAudioSource->prepareToPlay(samplesPerBlockExpected, sampleRate);
lowFilter->makeLowShelf(sampleRate, 200.0, 1.0, bassGain);
midFilter->makeBandPass(sampleRate, 4000, 880, midGain);
highFilter->makeHighShelf(sampleRate, 22000.0, 1.0, highGain);
}

void Player::releaseResources()
{
resamplingAudioSource->releaseResources();
}

void Player::getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill)
{
resamplingAudioSource->getNextAudioBlock(bufferToFill);

AudioSampleBuffer lsbuf(*bufferToFill.buffer);
lowFilter->processSamples(lsbuf.getSampleData(0), lsbuf.getNumSamples());
bufferToFill.buffer->applyGain(0, lsbuf.getNumSamples(), bassGain);
// have different buffers fo mid low and high, add them together and then use get???() to add them to buffer to fill

AudioSampleBuffer bpbuf(*bufferToFill.buffer);
midFilter->processSamples(bpbuf.getSampleData(0), bpbuf.getNumSamples());
bufferToFill.buffer->applyGain(0, bpbuf.getNumSamples(), midGain);

AudioSampleBuffer hsbuf(*bufferToFill.buffer);
highFilter->processSamples(hsbuf.getSampleData(0), hsbuf.getNumSamples());
bufferToFill.buffer->applyGain(0, hsbuf.getNumSamples(), highGain);

mixedBuffer->copyFrom(0, 0, lsbuf, lsbuf.getNumSamples());


//	if (bufferToFill.buffer->getNumChannels() > 1) 
//{

// lowFilter2->processSamples(bufferToFill.buffer->getSampleData(1), bufferToFill.buffer->getNumSamples());
// }
}[/code]


#2

So far you’re only copying the output of the lowfilter to the mixed buffer. Also, do the processSamples routines work with the original data (pointers, references) or copies?


#3

Thanks for your reply :slight_smile:

I have since changed the code to:

[code]
void Player::prepareToPlay (int samplesPerBlockExpected,double sampleRate)
{
resamplingAudioSource->prepareToPlay(samplesPerBlockExpected, sampleRate);

lowFilter->makeLowPass(sampleRate, 300);
midFilter->makeBandPass(sampleRate, 4000, 200, 1.0f);
highFilter->makeHighPass(sampleRate, 20000);

//	lowFilter->makeLowShelf(sampleRate, 200.0, 1.0, 1.0f);
//	midFilter->makeBandPass(sampleRate, 4000, 880, 1.0f);
//	highFilter->makeHighShelf(sampleRate, 22000.0, 1.0, 1.0f); 

}

void Player::releaseResources()
{
resamplingAudioSource->releaseResources();
}

void Player::getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill)
{
resamplingAudioSource->getNextAudioBlock(bufferToFill);

AudioSampleBuffer hsbuf(*bufferToFill.buffer);
highFilter->processSamples(hsbuf.getSampleData(0), hsbuf.getNumSamples());
bufferToFill.buffer->applyGain(0, hsbuf.getNumSamples(), highGain);

AudioSampleBuffer bpbuf(*bufferToFill.buffer);
midFilter->processSamples(bpbuf.getSampleData(0), bpbuf.getNumSamples());
bufferToFill.buffer->applyGain(0, bpbuf.getNumSamples(), midGain);

AudioSampleBuffer lsbuf(*bufferToFill.buffer);
lowFilter->processSamples(lsbuf.getSampleData(0), lsbuf.getNumSamples());
bufferToFill.buffer->applyGain(0, lsbuf.getNumSamples(), bassGain);

//mixedBuffer->addFrom(0, 0, hsbuf.getSampleData(0), hsbuf.getNumSamples());
//mixedBuffer->addFrom(0, 0, bpbuf.getSampleData(0), bpbuf.getNumSamples());
//mixedBuffer->addFrom(0, 0, lsbuf.getSampleData(0), lsbuf.getNumSamples());

//bufferToFill.buffer->addFrom(0, 0, mixedBuffer->getSampleData(0), mixedBuffer->getNumSamples(), 1.0f);

if (bufferToFill.buffer->getNumChannels() == 2) 
{
	AudioSampleBuffer lsbuf2(*bufferToFill.buffer);
	lowFilter2->processSamples(lsbuf2.getSampleData(0), lsbuf2.getNumSamples());
	bufferToFill.buffer->applyGain(0, lsbuf2.getNumSamples(), bassGain);
	
	
}

}[/code]

resamplingAudioSource is passed the data from my transport source:

To have the data from bufferToFill shoul i use copyFrom(); as apposed to initialising them with bufferToFill do you think?

If I un-comment the mixedBuffer lines the program runs but quits with BAD_EXC err.


#4

the way you wrote it, you’ll allocate and free memory for the AudioSampleBuffers on each call of getNextAudioBlock().

You could refactor them into member variables, initialize them in prepareToPlay with a reasonable size, and then use copyFrom to copy the output of the resampling source. If bufferToFill.numSamples is larger then your pre-allocated buffers, use AudioSampleBuffer::setSize() to enlarge them as required.


#5

Brilliant :slight_smile:

Thank you for your help.
I will have a pop at this this afternoon.


#6

Just call setSize() every time with keepExistingContent=false, clearExtraSpace=false, and avoidReallocating=false.