JUCE filter has popping/clip sound

I chose to use my own specified coefficients to create an iir filter, but there was always noise, and I don’t know what problem I overlooked? (This coefficient is not a problem as it does not produce any popping sound, which I have verified in Python)

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

    for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
        buffer.clear (i, 0, buffer.getNumSamples());
    
     float* channel1Data = buffer.getWritePointer(0);
     float* channel2Data = buffer.getWritePointer(1);


    juce::dsp::IIR::Coefficients<float>coefs(std::array<float, 10>{   0.00117571,  0.        , -0.00235143,  0.        ,  0.00117571,1.        , -3.9201592 ,  5.76585759, -3.77123379,  0.92553541 });

    juce::dsp::IIR::Filter<float>filter;
    //filter.reset();
    juce::ReferenceCountedObjectPtr<juce::dsp::IIR::Coefficients<float>> coefsPtr = new juce::dsp::IIR::Coefficients<float>(coefs);
    filter.coefficients = coefsPtr;
    filter.reset();
    for (int i = 0; i < buffer.getNumSamples(); ++i)
       {
        channel1Data[i] = filter.processSample(channel1Data[i]);
        channel1Data[i] = filter.processSample(channel2Data[i]);
       }

}
  • the result of filtering channel 2 is lost, because it’s assigned to channel 1
  • the same filter is used for both channels, which will lead to discontinuities - instead, keep a separate state/filter per channel

There’s more info here:

I see that the solution you shared is to save an intermediate variable, how to initialize this intermediate variable A and B? I use float A = 0.0f; Deinitialize the two values and the problem is not solved

    for (int i = 0; i < buffer.getNumSamples(); ++i)
       {
        channel1Data[i] = filter.processSample(A);
        A = channel1Data[i];
        channel1Data[i] = filter.processSample(B);
        B = channe2Data[i]
       }

Also you’re creating a new filter each time, so you’ll lose the filter state in each process block. The filters (and since they’re constant also the coefficients) should be a member of your processor that you initialize in prepareToPlay().