Trouble implementing IIRFilter


#1

Hi, I want to implement the IIRFilter class to the sinewave tutorial but having trouble wrapping my head around it. I.e. I get no sound when the filter is applied. It works fine otherwise.

N.B. I iterate through all samples before iterating through all channels, otherwise I’l get phasing issues.

This is my code so far:

void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) override
{
    lowPassFilter.reset();
    const double localTargetFrequency = targetFrequency;
    
    if ( localTargetFrequency != currentFrequency)
    {
        
        const double frequencyIncrement = (localTargetFrequency - currentFrequency) / bufferToFill.numSamples;
    
        for (int sample = 0; sample < bufferToFill.numSamples; ++sample)
        {                            
            float currentSample = 0.0f;
            currentFrequency += frequencyIncrement;
            updateAngleDelta();
            
            //calculate fourier series to generate squarewave from sinewave
            for ( float i = 1.0f; i <= iterations; i += 2.0f )
            {
                currentSample += (float) std::sin ( currentAngle * i ) / i;
            }
       
            for (int channel = 0; channel < bufferToFill.buffer->getNumChannels(); ++channel)
            {
                float* const buffer = bufferToFill.buffer->getWritePointer (channel, bufferToFill.startSample);
                    
                currentAngle += angleDelta;
                float lpSample = lowPassFilter.processSingleSampleRaw( currentSample );
                buffer[sample] = lpSample * currentLevel;
            }
        }
    }
    else
    {
        for (int sample = 0; sample < bufferToFill.numSamples; ++sample)
        {
            //calculate fourier series to generate squarewave from sinewave
            float currentSample = 0.0f;
            for ( float i = 1.0f; i <= iterations; i += 2.0f )
            {
                currentSample += (float) std::sin ( currentAngle * i ) / i;
            }
       
            for (int channel = 0; channel < bufferToFill.buffer->getNumChannels(); ++channel)
            {
                float* const buffer = bufferToFill.buffer->getWritePointer (channel, bufferToFill.startSample);
                    
                currentAngle += angleDelta;
                float lpSample = lowPassFilter.processSingleSampleRaw( currentSample );
                buffer[sample] = lpSample * currentLevel;
            }
        }
    }
   
}

Any help would be greatly appreciated!


#2

Haven’t looked very thoroughly through your code, but you need to create an IIRFilter object for each channel.


#3

Also I don’t suppose the filter should be resetted at each getNextAudioBlock call…?


#4

Thanks for your replies, i’ve got it to work. I need to create the filter in NextAudioBlock call…

As for the reset() function, the documentation says this:

Resets the filter’s processing pipeline, ready to start a new stream of data.
Note that this clears the processing state, but the type of filter and its coefficients aren’t changed. To put a filter into an inactive state, use the makeInactive() method.


#5

It is the other way round. You must not create the filter in the getNextAudioBlock call. The filter shall keep it’s state over many audio blocks. Think that the output of the filter does not depend on a single sample, but a series of samples. One sample has no frequency, but a series of samples does.
Hence you need one state for one signal, i.e. one filter for each channel.
If you reset the filter it means the filter will forget, what samples have passed. How would a block of e.g. 64 samples convey a frequency of 100 Hz, when one wavelength is 48000 / 100 = 480 samples?


#6

Hmm, this would explain wy it sounds very buzzy I guess haha.


#7

I meant that I needed to set the coefficients at NextAudioBlock.


#8

Setting the coefficients means to set a specific frequency response, generating a set of filter coefficients from a desired frequency response is just a mathematical operation. In general, the frequency response you set should stay the same over several audio blocks, so there is also no need to set the coefficients with every call to getNextAudioBlock.


#9

So, how would I change the cutoff and Q-factor at ‘runtime’? Or is this simply not possible with this class?