# Do you know guy can find some filters?

I’m looking for filters to use in a a project that could be updated realtime. Im just looking for the basics and some of the crazier ones like ladder butterworth?

You can probably pluck/hack these apart for what you need:

Oh awesome thanks man!

Those should work I’ve seen the Vinnie filters but not the dim’s which seem right up my alley!

Any chance you know where to find a way to display a filter from it’s biquad coefficients?

I don’t recall entirely off-hand, but it’s possible that Daniel’s already covered this in his repo: GitHub - ffAudio/PluginGuiMagic: Examples for foleys_gui_magic - the styleable plugin gui

1 Like

Ive looked at that before when I first started but didn’t understand it too much. I may be confused but I thought it used the Juce class to plot a filter response.

I was looking for something bi-quad → response.
There was one project on git hub a few years back but it wasn’t too accurate.

I found this…

Math :

``````           a0 + a1 z + a2 z^2 + ... + an z^n
H(z) = -----------------------------------------
b0 + b1 z + b2 z^2 + ... + bn z^n

H(w) = H(z) where z = e^jw = cos(w) + jsin(w)

Frequency (Hz)
w = ------------------- x 2pi (Radians)
Sample Rate (Hz)
``````

Code :

``````#include <complex>
using cmpx = std::complex<float>;

cmpx calc_freq_response (float frequency,
float sample_rate,
size_t order,
const float* a,
const float* b)
{
float w = 2.0 * pi * frequency / sample_rate;
cmpx z (cos(w), sin(w));

cmpx num (0.0, 0.0);
cmpx den (0.0, 0.0);
cmpx zn (1.0, 0.0);

for (auto n = 0; n < order; n++)
{
num += a[n] * zn;
den += b[n] * zn;
zn *= z;
}

return num / den;
}
``````

Magnitude is `std::abs(H)`, phase is `std::arg(H)`.

cpp reference on std::complex: std::complex - cppreference.com

The only “gotcha” is the sign of the denominator coefficients. Depending on your source they may need to be flipped.

2 Likes

I had a question about how to make the filters more stable while moving the frequency

If I’ve understood the request correctly, you’re looking for ways to play around with filter coefficients safely in real-time?

Direct Form II Transposed is the way to go.

You can create some vectors for storing your audio (Xn, Yn, etc) and variables for your coeffs (a0 through b2):

``````private:

//==============================================================================
std::vector<SampleType> Xn_1, Xn_2, Yn_1, Yn_2;

//==============================================================================
SampleType b0_ = 1.0, b1_ = 0.0, b2_ = 0.0, a0_ = 1.0, a1_ = 0.0, a2_ = 0.0;
``````

Prepare and access the variables here:

``````template <typename SampleType>
void Transformations<SampleType>::coefficients(SampleType b0, SampleType b1, SampleType b2, SampleType a0, SampleType a1, SampleType a2)
{
a0_ = (static_cast <SampleType>(1.0) / a0);    // best leave this at (1.0)!!!
a1_ = (static_cast <SampleType>((a1 * a0_) * SampleType (-1.0)));
a2_ = (static_cast <SampleType>((a2 * a0_) * SampleType (-1.0)));
b0_ = (static_cast <SampleType>(b0 * a0_));
b1_ = (static_cast <SampleType>(b1 * a0_));
b2_ = (static_cast <SampleType>(b2 * a0_));
}
``````

Apply your coefficients to inputSample[channel] via DFII transposed:

``````template <typename SampleType>
SampleType Transformations<SampleType>::directFormIITransposed(int channel, SampleType inputValue)
{
SampleType Xn = inputValue;

SampleType Yn = ((Xn * b0_) + (Xn_2[(size_t)channel]));

Xn_2[(size_t)channel] = ((Xn * b1_) + (Xn_1[(size_t)channel]) + (Yn * a1_));
Xn_1[(size_t)channel] = ((Xn * b2_) + (Yn * a2_));

return Yn;
}
``````

Don’t forget to call “resize” on the vectors using the number of channels to process.

You can use available methods to convert from “freq”, “gain”, and “Q” (or whatever you want to call them) into coeffs b0 through a2. Or, if you’re curious, you can attach params to the coefficients directly. I don’t really recommend doing it though, especially on this 2nd-order design - too complicated. Best leave a0 at (1.0) or else the filter explodes. All the rest should often move together, not independently. The 1st-order variety has less coeffs, so less chance of blowing up (I have working code for this also, if curious).

EDIT: If you want to flip the sign of the coefficients, simply change a0 to negative, as in (-1.0). But otherwise, best leave this one coeff alone

The “transposed” forms are much more modulation-friendly, mostly thanks to the order of the unit delay and coefficient gain multipliers. This is before even adding a parameter smoother.

I’ve been working on this sort of “workbench filter” class lately, just out of curiosity - still well under construction, but feel free to browse.

1 Like

I forgot to mention, you can also call the coefficient PTR’s from elsewhere using a “get” method, to display them on a GUI label or something, if you’d just like to view them in real-time without manipulating them directly. I’ll likely do this on my own workbench filter at some point.

1 Like

I will get back to you once I try to carefully implement this among 40 filters! This looks solid, paired with creating a filter object in prepare to play then performing modulation in the block!

I just saw the git hub link, I will check it out! Good looking out, on the Direct Form II Transposed!

I also thought about implementing a step parameter smoother that creates a new filter along each step, like Big Tick’s comment.

I have tried the lowpass filter parameter smoother in the past, however it peaks at 99% of the value inputed.

I’m currently building a synth and think most filters are fine with cleaning the variables every prepare to play. Unless you are changing the order, that shouldn’t be done in real time! haha.

My filters will be controlled by envelope and lfo. So we’ll have to see. I didn’t realize Transposed 2 was the most stable though!

I’ve started formalizing my general-purpose Biquad filter class, implemented as a simple .cpp/.h with (currently un-smoothed) param float inputs for Freq, Res (0 to 1), and Gain (peak-filter mode only), plus param choice inputs for Filter Type and choice of Direct Transform to use. Vectors are all resized on Prepare, zeroed in Reset, and snapped to zero.

I’ll be adding many more filter types in the next few days, including hopefully some one-poles. This can be a pretty good set of building blocks for other filter structures. In time, I’ll be looking more at de-cramping techniques (on the other repo I posted).

FWIW, the factory TPT filters (so called “ZDF”) within the DSP module are pretty hard to beat. You can greatly extend the variety of outputs on the awesome State Variable TPT Filter simply by adding this to ProcessSample:

``````switch (filterType)
{
case Type::lowpass:   return yLP;
case Type::highpass:  return yHP;
case Type::bandpass:  return yBP;
case Type::notch:     return (yLP + yHP);
case Type::peak:      return (yLP - yHP);
case Type::lp:        return (yLP + yBP);            // Single poles
case Type::hp:        return (yHP + yBP);
case Type::bpN:       return (yBP * R2);            // Non-unity gain filters
case Type::lowpassN:  return (yLP * R2);
case Type::highpassN: return (yHP * R2);
case Type::allpass:   return (inputValue - ((yBP * R2) + (yBP * R2)));
default:              return yLP;
}
``````

Happy modulating!

Thats an awesome project! It looks stable…(if I can say that lol)

Thanks for sharing. I’ll definitely get around to trying it out!

1 Like

1 Like

Thanks a lot! I also added smoothers, shelves and single-order filters since the last post. I’m very new to coding in general, let alone C++ and the juce framework. I realize that my implementation is kinda simple, but it’s readable to me which is 110% of everything to me at this stage!

I may do some optimizing in future, but it’s still very lightweight already. Just add the biquad.h/.cpp to a project, and it should fit in nicely alongside the factory DSP modules in terms of useage.

One of the main points in doing it was actually to learn Github, so any issues, pull requests etc are welcome

1 Like

It looks pretty solid, I appreciate you implemented oversampling. I think in theory oversampling besides clearing aliased frequencies. “deltas”/clears the feedback implemented in the delays. Maybe it’s the same thing idk…I read through the documentation!

Isn’t higher orders like 10, 20, 30 achieved by cascading a filter array?

My mind tells me that… however, I’m pretty sure I’ve gotten gnarly feedback looping biquads lol

Good observation. I’ve actually wired the OS changes up specifically to clear the data in memory (i.e., in the feedback loop) when changing settings - same for changing the filter order. It might pop, but it won’t blow up I won’t comment further just now, as I think there’s still a bit more to explore in this section of the code, but haven’t gone ahead with any pushes just yet due to catching up on some other projects. I’m definitely all ears if anyone has anything to add to this part of the discussion

As in 10, 20 etc decibels per decade, yes that’s certainly one way - and hence a good reason to seek to eliminate tiny little artefacts which might quickly stack up (which these things often do).

This goes a bit further than what I covered on my Git so far. In short, there’s at least two ways to do a multi-order Biquad. One of them is to simply cascade them serially (no feedback required between filter orders - just stack up my biquad class one after the other to get higher orders automatically). The other approach, if you check the section about “Direct Form I, II” etc… is that you can accomodate as many (or as few) filter poles as you wish, simply by increasing (or decreasing) the pairs of coefficients.

We’d always have:

b0 = direct signal gain
a0 = coefficient gain

b1 = positive feedback gain 1
a1 = negative feedback gain 1

Place all 4 above coeffs under correct control scheme, and you have access to all 1-order filter types.

b2 = pos feedback gain 2
a2 = neg feedback gain 2

Continue adding further coefficients and pos/neg feedback paths, to continue increasing filter order (but the control scheme needs re-adjusting for each order).

FAR easier to just run them serially, and activate/deactivate them in sequence to change the filter order.

I’m not prepared to die on the biquad hill particularly; I just happen to think they have a bit more potential that is usually credited to them in DSP circles.

Got some pretty fun filters on the backburner at the mo, stay tuned and stay well

took me a second to grasp this in practice.

So using the equation you showed above. Could you replace “order” with the number of samples in a delay line? Then offset the num and den calculations to start 1 after the size of the delay line?

I guess if thats the case it’s possible with smaller delay lines. But I can’t see that being practical with anything larger than 2048…

Idk, thanks for the detailed explanation though! It made plotting frequency responses way less daunting for filters!