Using the DSP module process function (IIR) twice causes noisy signal

Hi!

I have been learning JUCE for my thesis and I’m stuck at creating a crossfade feature that I hope would smooth out the change in filter parameters. The main goal for this audio application would be to change an IIR filter in realtime based on instructions from the editor. For this, I’m trying to use an updateFilter() function that would change the state of the filter.

However, I’m stuck even prior to going to the updateFilter, in that just using the DSP module process function (ProcessContextReplacing) twice on two different buffers (the output buffer and the crossfade buffer) creates noticeable artifacts and noise in the sound. I imagine somehow processing the temporary crossfade buffer somehow messes up the filter for the output buffer, but I don’t know how or why.

I would also like to point out that I’m very much a novice in C++ and JUCE, so I apologize for any inconsistent terminology use and blatant programming errors I might have conducted. Please bear with me and let me know if I can provide additional information to solve this issue. Here is the code that I’m having the issue with. I’m using a simple audio player that feeds the audio buffer via the transport when I press play. The code works fine if I remove the line where the block_CF is processed.

void MainComponent::getNextAudioBlock(const juce::AudioSourceChannelInfo& bufferToFill)
{
    bufferToFill.clearActiveBufferRegion();
    scratchBuffer.clear();
    transport.getNextAudioBlock(bufferToFill);
    dsp::AudioBlock<float> block(*bufferToFill.buffer,
        (size_t)bufferToFill.startSample);

    scratchBuffer.copyFrom(0, 0, bufferToFill.buffer->getReadPointer(0), bufferToFill.numSamples);
    scratchBuffer.copyFrom(1, 0, bufferToFill.buffer->getReadPointer(1), bufferToFill.numSamples);

    dsp::AudioBlock<float> block_CF(scratchBuffer, 0);

    lowPassFilter.process(dsp::ProcessContextReplacing <float>(block_CF));
    lowPassFilter.process(dsp::ProcessContextReplacing <float>(block));
}

Thank you!

The filters are stateful. If you feed different signals through the same filter, there are discontinuities in the fed signal that will become audible as noises.

Jules tried to give a general answer here

TL;DR: you need a filter per signal you feed. If you want to filter the signal twice with the same filter, you still need two instances that you call one after the other in always the same order.

Thank you Daniel, that clears it up. Apologies for asking about such an obvious mistake. I did try to search the forums for a couple days for answers, but apparently wasn’t skilled enough to find it.

No worries, we all made (some of) those mistakes…
Glad it helps

1 Like