How to fix JUCE Slider Updating Filter Delay?

Hello, I’m new to JUCE and I was testing filters on some input. I’m using the Slider component to adjust the frequency, but I realized the filter updates extremely slowly. When I suddenly change the frequency slider, it takes about half a second for me to actually hear the filter change. Am I doing something wrong?

This is my processBlock function:

    void processBlock (AudioBuffer<float>& buffer, MidiBuffer& midiMessages)
{
	filter.setCoefficients(IIRCoefficients::makeHighPass(getSampleRate(), std::max(0.000000001,frequencyPercentage*0.5f*getSampleRate())));
    auto totalNumOutputChannels = getTotalNumOutputChannels();
	for (int channel = 0; channel < totalNumOutputChannels; ++channel)
	{
		auto* outData = buffer.getWritePointer(channel);
		for (int sample = 0; sample < buffer.getNumSamples(); ++sample)
		{
			outData[sample] = random.nextFloat() - 1;
		}
		filter.processSamples(outData, buffer.getNumSamples());
	}

This is my sliderValueChanged function:

    void sliderValueChanged(Slider* slider)
{
	processor.frequencyPercentage = frequencySlider.getValue();
}

How long is the processing buffer? (buffer.getNumSamples()) What operating system/device are you trying it on?

I’m on windows 10, and getNumSamples() returns 2560

That’s already a relatively long buffer and an experienced user/musician would easily notice it, but it wouldn’t cause a latency of “half a second” by itself. Maybe there’s additional latency coming from your sound hardware or its driver…? What hardware/device are you using to listen to the sound? (Or are you running the code as a plugin inside some host application? If yes, which host?)

Never mind, I don’t know how but somehow it’s fixed. But now I’m running into another problem, my highpass filter is producing a horrible Buzz when there’s any input audio and I can’t see why.

processBlock (AudioBuffer<float>& buffer, MidiBuffer& midiMessages)
{
    auto totalNumInputChannels  = getTotalNumInputChannels();
    auto totalNumOutputChannels = getTotalNumOutputChannels();
	for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
		buffer.clear (i, 0, buffer.getNumSamples());
	for (int channel = 0; channel < totalNumOutputChannels; ++channel)
	{
		float* channelData = buffer.getWritePointer(channel);
		mFrequencySmoothed = mFrequencySmoothed - 0.4*(mFrequencySmoothed - mFrequencyParameter->get());
		filter->setCoefficients(IIRCoefficients::makeHighPass(getSampleRate(), mFrequencySmoothed));
		filter->processSamples(channelData, buffer.getNumSamples());
	}
}

An IIR filter maintains internal state from the previous call to processSamples so you can’t reuse the same filter instance across multiple channels.

You need to have an instance of the filter for each channel and then in the code above, assuming you did that by declaring an array of filters, use filter[channel]->…

2 Likes

Thanks for the reply! Maybe add a section called “Common mistakes” in the “learn” section of the main website, that may stop beginners from repeating the same mistakes again and again.