Add multiple IIRFilterAudioSource to MixerAudioSource speeds up audio

Hi all :slight_smile:

I searched in the forum and SO without founding anything so I’m posting here as a last resort.

I’m trying to implement a simple equalizer (bass, mid, treble) and I’m not interested in high quality at the moment, just to make it work.

The code below works but it plays at a higher speed then if I comment 2 of the 3 sources added to the mixer.

I’d appreciate if somebody could point me in the right direction, either with code or some resources from which I can understand what’s happening.

I declared 3 couples of transport source and filter source in the header file as follow

    AudioTransportSource bassTransportSource;
    IIRFilterAudioSource bassFilterSource{&bassTransportSource, false};

    AudioTransportSource midTransportSource;
    IIRFilterAudioSource midFilterSource{&midTransportSource, false};

    AudioTransportSource trebleTransportSource;
    IIRFilterAudioSource trebleFilterSource{&trebleTransportSource, false};

    MixerAudioSource mixerSource;
    ResamplingAudioSource resampleSource{&mixerSource, false, 2};

Then I have

void Equalizer::prepareToPlay (int samplesPerBlockExpected, double sampleRate) 
{
    bassTransportSource.prepareToPlay(samplesPerBlockExpected, sampleRate);
    midTransportSource.prepareToPlay(samplesPerBlockExpected, sampleRate);
    trebleTransportSource.prepareToPlay(samplesPerBlockExpected, sampleRate);

    bassFilterSource.setCoefficients(IIRCoefficients::makeLowPass(sampleRate, 300));
    midFilterSource.setCoefficients(IIRCoefficients::makeBandPass(sampleRate, 4000));
    trebleFilterSource.setCoefficients(IIRCoefficients::makeHighPass(sampleRate, 10000));

    mixerSource.prepareToPlay(samplesPerBlockExpected, sampleRate);

    mixerSource.addInputSource(&bassFilterSource, false);
    mixerSource.addInputSource(&midFilterSource, false);
    mixerSource.addInputSource(&trebleFilterSource, false);

    resampleSource.prepareToPlay(samplesPerBlockExpected, sampleRate);
}

void Equalizer::getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill)
{
    resampleSource.getNextAudioBlock(bufferToFill);
}

And finally I call this method when clicking on a button:

void Equalizer::start()
{
    bassTransportSource.start();
    midTransportSource.start();
    trebleTransportSource.start();
    playing = true;
}

Thank you in advance!

PS
I’m not touching the value of the ResamplingAudioSource and I tried play mixerSource directly to the same effect.

Did you find any solution for this? I’m having the same issue.

How are you initializing the transport sources, what sources are feeding into those?

14 years ago IIRFilterAudioSource was added to Juce. Number of code examples on the internet? Well, if you include the above, approximately 1 - and as the poster says, it doesn’t work.

If you look into the sources, the IIRFilterAudioSource is extremely trivial, so it is hard to imagine, that it resamples the audio.
But on the other hand the TransportAudioSource has a mechanism built in to resample. So it is fair to ask, if the people experiencing that problem are aware of that and how you are using the TransportAudioSource.

Unrelated remark: You are aware that the start/stop of TransportAudioSource are handled asynchronously, so even without knowing your exact use case, I am confident to say that TransportAudioSource is not the right approach in that setup. If at all you could put the TransportAudioSource AFTER the MixerAudioSource, so that all sources stay in sync.