# dsp::IIR::Filter: noise/glitches when automating frequency via (slow) LFO

**URL:** <https://forum.juce.com/t/dsp-noise-glitches-when-automating-frequency-via-slow-lfo/63949>\
**Category:** Audio Plugins\
**Created:** [October 26, 2024, 7:56am UTC](https://forum.juce.com/t/dsp-noise-glitches-when-automating-frequency-via-slow-lfo/63949 "2024-10-26T07:56:37Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![dfilaretti](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/dfilaretti/32/16818_2.png) [@dfilaretti](https://forum.juce.com/u/dfilaretti)\
**Post date:** [October 26, 2024, 7:56am UTC](https://forum.juce.com/t/dsp-noise-glitches-when-automating-frequency-via-slow-lfo/63949/1 "2024-10-26T07:56:37Z")

</div>

Hi all,

I’m working on a plugin that takes the incoming signal and applies a simple EQ boost (bell shaped) where the frequency of the filter moves up and down between a fixed range using an LFO (we can control the speed of the motion via a knob).

For the filter I’m using `juce::dsp::IIR::Filter<float>` and the frequency is controlled by a `juce::dsp::Oscillator`.

Here’s the problem: if I update the filter coefficients at each sample, then there are no artefacts when the filter sweeps (but this eats up a lot of CPU). If, however, I update the filter every say 100 samples or so, I start to hear some high-frequency noise/glitches, especially if I set the frequency range to move into the upper frequencies, say from 200hz to 17000hz (I tried setting the range from 200hz to 2000hz and seems fine!) .

Those glitches are not really audible when processing an a complex signal, but they become evident when processing a simple sine wave (which I’ll probably never do in real life, but just did as a test).

I have read that if you require “fast modulation” it is better to use a `StateVariableFilter` however from what I can see that only supports low-pass, high-pass and band-pass, while I need a “bell” filter (notch?). Also, I’m not sure what “fast modulation” is in this context; my LFO will actually be very slow, say from 0.01hz to 0.5hz maximum.

On a related note, I noticed that also quickly moving e.g. the Q or gain knobs produces the same issue; I’m using `SmoothedValue`s already, with a ramp time of 0.0005; I can get the artefacts to disappear if I set the number to something much bigger, but then the plugin becomes unusable.

Does anybody have any thoughts about this? Am I doing something wrong or that’s just the way it works?

Thanks!

---

<div class="post-metadata">

**Author:** ![kerfuffle](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/kerfuffle/32/11805_2.png) [@kerfuffle](https://forum.juce.com/u/kerfuffle)\
**Post date:** [October 26, 2024, 9:01am UTC](https://forum.juce.com/t/dsp-noise-glitches-when-automating-frequency-via-slow-lfo/63949/2 "2024-10-26T09:01:31Z")

</div>

Sounds like this is zipper noise indeed. You’re already smoothing the knobs but still updating the filter coefficients in steps, so that still gives zipper noise. You can try doing a linear interpolation between the filter coefficients over those 100 samples.

The StateVariableFilter can be used to create a bell or notch filter by combining the different outputs. But the problem you’re having doesn’t sound like it’s due to fast modulation, since your modulation is very slow, and it works OK if you calculate the coefficients on every sample.

---

<div class="post-metadata">

**Author:** ![Mrugalla](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/mrugalla/32/13092_2.png) [@Mrugalla](https://forum.juce.com/u/Mrugalla)\
**Post date:** [October 26, 2024, 10:45am UTC](https://forum.juce.com/t/dsp-noise-glitches-when-automating-frequency-via-slow-lfo/63949/3 "2024-10-26T10:45:01Z")

</div>

if you imagine non-sample accurate filter updates as a signal it would be a steppy one, a little discontinuity every 100th sample. that’s why it makes noise at that implied frequency

---

<div class="post-metadata">

**Author:** ![dfilaretti](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/dfilaretti/32/16818_2.png) [@dfilaretti](https://forum.juce.com/u/dfilaretti)\
**Post date:** [October 26, 2024, 12:02pm UTC](https://forum.juce.com/t/dsp-noise-glitches-when-automating-frequency-via-slow-lfo/63949/4 "2024-10-26T12:02:41Z")

</div>

Thanks for your input!

So are you suggesting every 100 (or whatever I’ll set this interval to be) samples instead of just getting the LFO value and calculating the new frequency, to instead calculate this new frequency, interpolating with the previous one (that I’ll have saved as a member) and then use the interpolated frequency?

Or are you referring to actually interpolating all the coefficients?  
The way I obtain the coefficients is via `juce::dsp::IIR::Coefficients<float>::makePeakFilter(...)`.

I wonder in general what’s the standard way to solve this problem? It sounds like virtually every plugin must deal with this, is there any best practice or standard solution?

---

<div class="post-metadata">

**Author:** ![dfilaretti](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/dfilaretti/32/16818_2.png) [@dfilaretti](https://forum.juce.com/u/dfilaretti)\
**Post date:** [October 26, 2024, 12:05pm UTC](https://forum.juce.com/t/dsp-noise-glitches-when-automating-frequency-via-slow-lfo/63949/5 "2024-10-26T12:05:04Z")

</div>

Yeah, that makes sense.  
How would you approach a possible fix or at least reducing the effect?

---

<div class="post-metadata">

**Author:** ![kerfuffle](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/kerfuffle/32/11805_2.png) [@kerfuffle](https://forum.juce.com/u/kerfuffle)\
**Post date:** [October 26, 2024, 1:28pm UTC](https://forum.juce.com/t/dsp-noise-glitches-when-automating-frequency-via-slow-lfo/63949/6 "2024-10-26T13:28:20Z")

</div>

You can interpolate either but the coefficients is more efficient. Interpolating between the frequencies would be the same as smoothing the parameter and calculating the coefficients on every sample.

---

<div class="post-metadata">

**Author:** ![dfilaretti](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/dfilaretti/32/16818_2.png) [@dfilaretti](https://forum.juce.com/u/dfilaretti)\
**Post date:** [October 26, 2024, 6:19pm UTC](https://forum.juce.com/t/dsp-noise-glitches-when-automating-frequency-via-slow-lfo/63949/7 "2024-10-26T18:19:22Z")

</div>

Ah - I think I misunderstood your initial answer then. Let me check if I’m understanding correctly now…

So, what I’m doing at the moment is computing the coefficients and updating the filter once every 100 samples (which means the filter frequency is updated in steps, possibly causing zipper noise).

Are you suggesting I could still compute the coefficients once every 100 samples but update the filter at each sample instead of every 100 (using interpolated coefficients in between those 100 samples)?

If so, isn’t that still expensive? Isn’t the point of “control rate” modulation to avoid updating certain DSP blocks at each sample? Or is this gonna be ok because the actually expensive bit is calculating the coefficient but once we have them, updating the filter is basically just a few assignments?

Am I on the right path?

---

<div class="post-metadata">

**Author:** ![zsliu98](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/zsliu98/32/22502_2.png) [@zsliu98](https://forum.juce.com/u/zsliu98)\
**Post date:** [October 26, 2024, 8:15pm UTC](https://forum.juce.com/t/dsp-noise-glitches-when-automating-frequency-via-slow-lfo/63949/8 "2024-10-26T20:15:01Z")

</div>

In my dynamic EQ plugin, when I change the coeff updating scheme from per 1ms to per sample, Reaper shows that the CPU load increases from 0.06% to 0.13% (of one filter). I still think this kind of CPU consumption is acceptable. If your CPU load rises much more than that, better check you code to make sure there is no allocation (e.g., `juce::dsp::IIR::Coefficients<float>::makePeakFilter`) or system calls. You may also re-write the IIR filter to avoid some redundant calculations.

You can map coefficients of TDF-II to coefficients of SVF easily. It does become more stable. However, it introduces much more phase shift (even for peaking filters). See the reference below for details.

> **[dafx14\_aaron\_wishnick\_time\_varying\_filters\_for\_.pdf](https://www.dafx14.fau.de/papers/dafx14_aaron_wishnick_time_varying_filters_for_.pdf)**
>
> 315.64 KB

---

<div class="post-metadata">

**Author:** ![dfilaretti](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/dfilaretti/32/16818_2.png) [@dfilaretti](https://forum.juce.com/u/dfilaretti)\
**Post date:** [October 27, 2024, 9:53am UTC](https://forum.juce.com/t/dsp-noise-glitches-when-automating-frequency-via-slow-lfo/63949/9 "2024-10-27T09:53:13Z")

</div>

Yeah my CPU goes from 1% (which is already a lot I guess) if I update the filter every 100 samples, to about 7% if I update the filter at each sample. Definitely something wrong there 🙂

In my `processBlock` I actually use `juce::dsp::IIR::Coefficients<float>::makePeakFilter` to generate the new coefficients every time, could that be part of the problem? But if I’m not supposed to use `makePeakFilter` inside `processBlock`, what should I use instead?

---

<div class="post-metadata">

**Author:** ![kerfuffle](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/kerfuffle/32/11805_2.png) [@kerfuffle](https://forum.juce.com/u/kerfuffle)\
**Post date:** [October 27, 2024, 10:24am UTC](https://forum.juce.com/t/dsp-noise-glitches-when-automating-frequency-via-slow-lfo/63949/10 "2024-10-27T10:24:12Z")

</div>

Calculating the coefficients from the frequency and Q factor is relatively slow because it involves a `tan` or `sin` and `cos` function. However, if you only calculate them every 100 samples this is not so bad.

Doing a linear interpolation between the new and old coefficients over those 100 steps is pretty fast and simple to code:

```c+
current_coeff = old_coeff + (new_coeff - old_coeff) * step * 0.01;

```

where `step` goes between 0 and 99 (or 1 and 100). After 100 steps, you set `old_coeff = new_coeff` and calculate a new `new_coeff` from the current filter frequency and Q.

It’s fairly common for things like synths to do their parameter updates every 32 samples or so and interpolate everything in between.

---

<div class="post-metadata">

**Author:** ![zsliu98](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/zsliu98/32/22502_2.png) [@zsliu98](https://forum.juce.com/u/zsliu98)\
**Post date:** [October 27, 2024, 10:33am UTC](https://forum.juce.com/t/dsp-noise-glitches-when-automating-frequency-via-slow-lfo/63949/11 "2024-10-27T10:33:44Z")

</div>

> [@dfilaretti](#):
>
> Yeah my CPU goes from 1% (which is already a lot I guess) if I update the filter every 100 samples, to about 7% if I update the filter at each sample. Definitely something wrong there 🙂
> 
> In my `processBlock` I actually use `juce::dsp::IIR::Coefficients<float>::makePeakFilter` to generate the new coefficients every time, could that be part of the problem? But if I’m not supposed to use `makePeakFilter` inside `processBlock`, what should I use instead?

That CPU usage is abnormal. Never use `juce::dsp::IIR::Coefficients<float>::makePeakFilter ` in `processBlock`. Use `ArrayCoefficients` instead. See more info at:

> [@Non-allocating alternatives for the IIR::Coefficients::make... functions](https://forum.juce.com/t/non-allocating-alternatives-for-the-iir-make-functions/38335/21):
>
> Yes, the ArrayCoefficients functions are designed so that they do not need to allocate.

BTW, I see about 5~10% reduction in CPU usage if I use my own IIR filter (basically copy most code from juce::dsp::IIR and remove some redundant checks).

---

<div class="post-metadata">

**Author:** ![dfilaretti](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/dfilaretti/32/16818_2.png) [@dfilaretti](https://forum.juce.com/u/dfilaretti)\
**Post date:** [October 27, 2024, 4:52pm UTC](https://forum.juce.com/t/dsp-noise-glitches-when-automating-frequency-via-slow-lfo/63949/12 "2024-10-27T16:52:15Z")

</div>

Right, got it - thanks! 🙂

Just a quick follow up: since the coefficients are wrapped inside a `dsp::IIR::Coefficients` struct, what’s the easiest way to do this interpolation in practice? Should I handle each of the 6 coefficients separately as a plain `float` and then wrap them into a `dsp::IIR::Coefficients` again when it’s time to update the filter? Or is there a more convenient or built-in way to do it?

---

<div class="post-metadata">

**Author:** ![dfilaretti](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/dfilaretti/32/16818_2.png) [@dfilaretti](https://forum.juce.com/u/dfilaretti)\
**Post date:** [October 27, 2024, 4:54pm UTC](https://forum.juce.com/t/dsp-noise-glitches-when-automating-frequency-via-slow-lfo/63949/13 "2024-10-27T16:54:30Z")

</div>

Thanks for the tips. I’m going to take a look at the post you linked and will definitely investigate using `ArrayCoefficients` so that we avoid allocating in the `processBlock` 🙂

---

<div class="post-metadata">

**Author:** ![daniel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/daniel/32/790_2.png) [@daniel](https://forum.juce.com/u/daniel)\
**Post date:** [October 27, 2024, 5:10pm UTC](https://forum.juce.com/t/dsp-noise-glitches-when-automating-frequency-via-slow-lfo/63949/14 "2024-10-27T17:10:26Z")

</div>

Just a side note: % of CPU is very coarse and machine dependant, so you cannot compare with other developers  
And of course never look at CPU readings of a debug build.

---

<div class="post-metadata">

**Author:** ![dfilaretti](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/dfilaretti/32/16818_2.png) [@dfilaretti](https://forum.juce.com/u/dfilaretti)\
**Post date:** [October 27, 2024, 6:25pm UTC](https://forum.juce.com/t/dsp-noise-glitches-when-automating-frequency-via-slow-lfo/63949/15 "2024-10-27T18:25:39Z")

</div>

good point, noted!  
(also reminds me: I was indeed testing on a debug build!!)

---

<div class="post-metadata">

**Author:** ![kerfuffle](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/kerfuffle/32/11805_2.png) [@kerfuffle](https://forum.juce.com/u/kerfuffle)\
**Post date:** [October 28, 2024, 9:16am UTC](https://forum.juce.com/t/dsp-noise-glitches-when-automating-frequency-via-slow-lfo/63949/16 "2024-10-28T09:16:29Z")

</div>

The filter internally does `coefficients->getRawCoefficients()` to get the coefficient values. So if you modify the `coefficients` member of the `IIR::Coefficients` object, then the next time the filter runs it will pick up the new coefficients. Like so:

```c++
filter.coefficients->coefficients[0] = ...;
filter.coefficients->coefficients[1] = ...;
filter.coefficients->coefficients[2] = ...;
filter.coefficients->coefficients[3] = ...;
filter.coefficients->coefficients[4] = ...;

```

---

<div class="post-metadata">

**Author:** ![dfilaretti](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/dfilaretti/32/16818_2.png) [@dfilaretti](https://forum.juce.com/u/dfilaretti)\
**Post date:** [October 28, 2024, 6:05pm UTC](https://forum.juce.com/t/dsp-noise-glitches-when-automating-frequency-via-slow-lfo/63949/17 "2024-10-28T18:05:33Z")

</div>

thanks, sorted 🙂

---

<div class="post-metadata">

**Author:** ![dfilaretti](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/dfilaretti/32/16818_2.png) [@dfilaretti](https://forum.juce.com/u/dfilaretti)\
**Post date:** [October 30, 2024, 9:16am UTC](https://forum.juce.com/t/dsp-noise-glitches-when-automating-frequency-via-slow-lfo/63949/18 "2024-10-30T09:16:36Z")

</div>

> [@zsliu98](#):
>
> That CPU usage is abnormal. Never use `juce::dsp::IIR::Coefficients<float>::makePeakFilter ` in `processBlock`. Use `ArrayCoefficients` instead. See more info at:

Hey, I’m trying to replace `dsp::IIR::Coefficients<float>::makePeakFilter` with `dsp::IIR::ArrayCoefficients<float>::makePeakFilter` based on your suggestion.

I’m not sure what I’m doing wrong but as soon as I do the swap the filter stops working; it does a “pop” when it’s loaded and then complete silence.

All I’ve done is essentially replacing

```auto
juce::dsp::IIR::Coefficients<float>::makePeakFilter (
   getSampleRate(),
   cutoffFreqHz,
   currentIntensitySmoothed,
   juce::Decibels::decibelsToGain (currentAmountSmoothed))->coefficients;

```

with

```auto
juce::dsp::IIR::ArrayCoefficients<float>::makePeakFilter (
   getSampleRate(),
   cutoffFreqHz,
   currentIntensitySmoothed,
   juce::Decibels::decibelsToGain (currentAmountSmoothed));

```

before assigning the returned coefficients to my variable and using them.

The first works, the second doesn’t.

Am I missing something? 🤔

---

<div class="post-metadata">

**Author:** ![zsliu98](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/zsliu98/32/22502_2.png) [@zsliu98](https://forum.juce.com/u/zsliu98)\
**Post date:** [October 30, 2024, 11:54am UTC](https://forum.juce.com/t/dsp-noise-glitches-when-automating-frequency-via-slow-lfo/63949/19 "2024-10-30T11:54:39Z")

</div>

The first one is a `juce::Array` while the second one is a `std::array`. I am not sure whether it makes a difference in your code. You may want to check the following demo:

> <https://github.com/juce-framework/JUCE/blob/master/examples/DSP/IIRFilterDemo.h>

---

<div class="post-metadata">

**Author:** ![dfilaretti](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/dfilaretti/32/16818_2.png) [@dfilaretti](https://forum.juce.com/u/dfilaretti)\
**Post date:** [October 31, 2024, 8:52am UTC](https://forum.juce.com/t/dsp-noise-glitches-when-automating-frequency-via-slow-lfo/63949/20 "2024-10-31T08:52:23Z")

</div>

Thanks for your reply! I’m not sure what’s wrong but still have the filter not working when replacing `IIR::Coefficients<float>::makePeakFilter` with `IIR::ArrayCoefficients<float>::makePeakFilter`.

Here’s how my code is set up: in the processor class, I have a member

```auto
std::array<float, 6> newCoefficients;

```

that will be combined with other things and eventually the values will be fed into the filter coeffs.

Then, in `processBlock`, every few samples I update it using one of the two methods above; one works and the other doesn’t; here’s the test code I’m looking at:

```auto
// OK - filter works
auto testCoefficients_ok = juce::dsp::IIR::Coefficients<float>::makePeakFilter (
    getSampleRate(),
    cutoffFreqHz,
    currentIntensitySmoothed,
    juce::Decibels::decibelsToGain (currentAmountSmoothed))->coefficients;

// FAILS (filter does initial "pop" then silence)
auto testCoefficients_broken = juce::dsp::IIR::ArrayCoefficients<float>::makePeakFilter (
    getSampleRate(),
    cutoffFreqHz,
    currentIntensitySmoothed,
    juce::Decibels::decibelsToGain (currentAmountSmoothed));

// copy into our member variable (will be used for processing)
for (auto c = 0; c < 6; ++c)
{
    newCoefficients[c] = testCoefficients_ok[c];
    //newCoefficients[c] = testCoefficients_broken[c]; // not working!!
}

```

I’m pretty sure there’s something stupid going on here, but I really can’t understand what… The difference between `std::array` and `juce::Array` shouldn’t be a problem here I think? I’d expect those two things to be completely interchangeable but something else is going on apparently!

[Next page](https://forum.juce.com/t/dsp-noise-glitches-when-automating-frequency-via-slow-lfo/63949.md?page=2)
