SynthMaker

High/Low Shelf Parametric EQ

Archive · 2008 37 old posts

From the original SynthMaker forum (2004–2014), with its members’ names and dates.

electrogear ·

Hi,

I am trying to design an EQ with high/low shelf settings. So far I have got as far as making a non-code version of Shifrins Robert Bristow-Johnson EQ Cookbook Biquad low shelf filter. (RBJ Filters ported UPDATED... ) to get the coefficients (a0, a1, a2, b0, b1, b2) for the graph part. It does sort of work, in that it shows a shelf, but it is totally wrongly scaled and it's not acting as it should do. Can anyone have a look and give me any tips? I've just started on the first of the freq/phase calc modules.

Would really appreciate any input on this.

Thanks 🙂

electrogear ·

OK I've gone through a lot of the scaling and sorted it, but I think there's a problem with some of my interpretation of the code. I have a question:

Is the (float) sin component the same as using sin1 in the code?

Here's an example. I have taken the line of code:

snb = sin1(0.5*freq)*beta;

and this is my interpretation using SM components:

MyCo ·

the green "sin" is a mathematical correct sin() function so you have to do sin(freq*PI) instead of sin(freq*0.5)

electrogear ·

Hey thanks for your help. I'm just working on the graph at the moment - trying to get it to display the low shelf, high shelf, or peaking for each node. It still seems to be acting strangely. Would you be so kind as to take a look at it for me? I think all of my interpretations of the code are correct now, I'm just wondering if it's still something to do with the scaling of gain/freq?

Thanks

MyCo ·

I've tried to build the shelfing filters from the original documentation, it looks like it does what it should do, but drag points are out of position. I don't know if this is how it should be.

electrogear ·

MyCo wrote: I've tried to build the shelfing filters from the original documentation, it looks like it does what it should do, but drag points are out of position. I don't know if this is how it should be.

My word, you are a genius, to do that in such little time. Thankyou so much, I will look at this in more detail to see what you have done. Did you use the Tobybear program to get the calculations? I think that's how the offset should be, in the centre of the shelf slope as you have done it..

electrogear ·

Myco I can't thank you enough for this, everything you have done is perfect, and the way you have laid it out will make it easy to get to grips with the filter calculations and learn for myself, as most websites I have looked at so far have been very poor at explaining calculations. I'm guessing you must have had most of these modules made up already, because you can't have put it together that fast from scratch? 😮

MyCo ·

well, the calculations for the shelf filters are from the Audio-EQ-Cookbook, that's where the RBJ filter of S|M come from. I had to transform one formula to calculate the slope from the Q input. Everything else is directly from the "book".

electrogear ·

Hey Myco,

I had a go at making the Low Pass & High Pass versions using green maths taking the calculations from the Audio Cookbook. I've got so far, and the result seems like it's almost there. The problem is, instead of letting high/low frequencies pass, it appears to be boosting them, and the audio output becomes a series of clicks....

any ideas what I'm doing wrong?

Cheers,

Mike

MyCo ·

I've checked everything, and for me, your green math seems to be correct. So I guess you use it in a wrong way. See attachment. It needs to be adjusted eg. clipping the input parameters. And it isn't optimized... but that shouldn't be a problem.

electrogear ·

Thanks Myco, I'll check it out later. I was wondering something else also:

Why do the high/low shelfs sometimes cause the sound to stutter & distort when moving the nodes around, but with the peaking mode it's fine? Sometimes in high/low shelf mode the EQ cuts out altogether and won't work until the sound outputs are reset...

Cheers,

Mike

MyCo ·

don't know where it comes from, the filter looks stable, the reset happens even on safe pole/zero positions. May be, there is a division by zero or close to zero value, but I haven't found a position where the problem happens everytime so I could look at the values.

electrogear ·

Aha, I see what you mean... I'll check it out too, although I expect you'll know what you're doing with it where as mine will be guess work. Cheers for the help dude, really appreciate it.

🙂

Mike

electrogear ·

Not having much luck with this, I can't seem to get my head around how to find divide by ~0 values...

infuzion ·

electrogear wrote: I can't seem to get my head around how to find divide by ~0 values...

Perhaps multiply by the inverse?

electrogear ·

I can't find what is causing the glitching. Could I maybe put in a Min/Max somewhere so to prevent it distorting?

theun ·

Hi Mike,

I played a bit with your HPF [filter] coefficient calculator [old link] and MyCo's osm [old link] that integrates your coefficients into a bilinear filter. (I didn't really look at the LPF variant, but what goes for the HPF also goes for the LPF, as long as the formula's are OK).

Like MyCo said, the green math is OK. The filter analysis tool made by bashert (it's in the WIKI) [old link] shows the filter works fine, see the picture.

I cannot fully explain the stutter and plop effect when turning the Q and f0 knobs too fast, but my reasoning is as follows:

This type of filter (biquad IIR) is derived by mathematically transforming an (existing, proven) analogue filter into a digital filter. [more exactly, by means of a z-transform the filter is transformed from the complex s-domain into the digital z-domain]. Theoretically this should result in a perfect representation of the original filter in the digital domain. However when you take into account

• mathematical conditions (the usual such as linearity, continuity, ...boy, that seems long ago!) that may or may not be fully fulfilled • approximations and/or simplifications used when performing the transform • quantization error that is introduced using the filter in the z-domain it seems apparant that the filter that's created probably will have some flaws. Some documented flaws of this type of filter are non-linear phase response and low-frequency sensitivity (below appr 250 Hz at 44.1 kHz sample rate). And as this is a recursive filter once there goes something wrong (quantization errors, some kind of oscillation, ..) the result is fed back in the filter, making it worse.

I am not saying this type of filter is poor, on the contrary, this is a well known and well documented filter type, that is in many cases first choice. Moreover, the RB-J cookbook formula's compensate for some non-linearities. But I just try to give some explanation for what happens.

Part of the solution is indeed changing min max values, e.g. a min value for f0 that gives some improvement is 250 or 300 Hz (to be honest a cut off frequency of 0Hz doesn't make much sense), just change the min value in the knob.

Another part of the solution is to prevent users to turn the knobs too quickly, decoupling using dezippers doesn't seem to help enough. A solution with slew rate limiters forces that there is a maximum speed for changing the parameters and is rather effective.

I must admit that even with both solutions implemented it still is possible to make the stuttering effect by quickly turning the knobs, anyway, there is a big improvement. I suppose further optimization is possible. Further, I suppose that there are more/other/different (partly) solutions, e.g. double precision for calculation of the coefficients.

Enough for today, I hope this helps you a bit further,

theun

electrogear ·

Hi theun. That shows a high shelf, not a nigh pass, I think you must have downloaded the wrong one. Thanks for the slew trick, I'll try it later!

Cheers,

Mike

theun ·

No, I didn't ...... 😀

It really is the HPF filter you made using green math calculations ... Maybe you recognize it better this way:

Different Q value, different curve ...

Here's the osm:

regards theun

electrogear ·

Ah yes, my apologies. I've tried the slew limit trick but it doesn't seem to make any difference for me. Still getting super-glitches that cut the sound, no matter how slowly or fast I move the controls...

infuzion ·

electrogear wrote: Ah yes, my apologies. I've tried the slew limit trick but it doesn't seem to make any difference for me. Still getting super-glitches that cut the sound, no matter how slowly or fast I move the controls...

I seem to remember having issues if one of the values hit 0.

electrogear ·

Yeah it does happen quite often on going from + > - and vice versa, but it also happens at other times too, not just with 0 crossing...

theun ·

electrogear wrote: Still getting super-glitches that cut the sound, no matter how slowly or fast I move the controls...

Strange, I didn't say there were no crackles left, but I think I really got it down for the bigger part .... here's my osm ....

Still getting super glitches ?

Anyway I've read and learned a lot about DSP filtering the last few weeks, I hope to come up with some other improvements next week or so.

electrogear ·

Ah... it wasn't the High Pass I was having trouble with, it was the high shelf... I'll do some more testing and get back to you later 🙂

Thanks for the help dude!

MyCo ·

The way, theun uses for smoothing the input is not very CPU friendly, because the green math is forced to recalculate 10 times per second.

I just found out, that not all problems are caused by division by zero. There is also another problem, there are 6 coeffs that are processed in green math, so let's say, the poly code starts when not all coeffs are calculated, then at least one coeff is wrong and may cause an unstable filter.

But there might be a way to smooth everything: use a hop inside the code, in this hop you load all coeffs into new variables, and the filter kernel uses the new coeff-variables instead of the real input coeffs.

electrogear ·

Aha... I will look into the 'hop' if I can find some info on it somewhere on the forum or wiki, and I'll give it a shot. Thanks for the tip!

Cheers,

Mike

electrogear ·

OK, please don't laugh if I've totally gone the wrong way about this, but this is what I gathered from your explanation:

streamin in left; streamin in right; streamout out left; streamout out right;

streamin a0; streamin a1; streamin a2; streamin b0inv; streamin b1; streamin b2; // mem float y0,y1,y2,x0,x1,x2; float y0b,y1b,y2b,x0b,x1b,x2b; // coeffs float a0b0,a1b0,a2b0,b1b0,b2b0;

//load coefficients into new variables float a0z, a1z, a2z, b0invz, b1z, b2z; hop(64){ a0z = a0; a1z = a1; a2z = a2; b0invz = b0inv; b1z = b1; b2z = b2; }

// /a0 optimisation in left = in left + 0.0000000001; in right = in right + 0.0000000001;

a0b0 = a0z*b0invz a1b0 = a1z*b0invz; a2b0 = a2z*b0invz; b1b0 = b1z*b0invz; b2b0 = b2z*b0invz; x0 = in left; x0b = in right; y0 = a0b0*x0 + a1b0*x1 + a2b0*x2 - b1b0*y1 - b2b0*y2; y0b = a0b0*x0b + a1b0*x1b + a2b0*x2b - b1b0*y1b - b2b0*y2b; // push vars to mem x2 = x1; x1 = x0; y2 = y1; y1 = y0;

x2b = x1b; x1b = x0b; y2b = y1b; y1b = y0b; out left = y0; out right = y0b; in left = in left - 0.0000000001; in right = in right - 0.0000000001;

This doesn't seem to give any better results. The EQ still works, but I'm still getting glitching - possibly even worse now. I've tried a few different values for the hop. This got me thinking, should I be interpolating the values now that we are giving it a new set of values every 64 (or whatever) samples?

Can you let me know if I'm on the right track, or if I'm being totally stupid?

Thanks,

Mike

electrogear ·

Just in case you are confused by the code, I have just made 6 new variables with the same names as the coefficients but with a 'z' on the end.

MyCo ·

well, the way is right. But you shouldn't use spaces in variable names. I didn't know that this even works, because there is no other programming language that can do that 😈

electrogear ·

Spaces where? after/before the variable name? I do it in Javascript. Makes everything look neater and I find it easier to read. It ignores white space before/after a variable name - it only takes into account white space between characters within a variable name. Anyway, aside from me not knowing how to code properly, it doesn't seem to solve the problem. Should I be interpolating somewhere? Am I using the correct hop value?

Thanks,

Mike

MyCo ·

interpolation could help, but if you do this, you could also use the code version of the RBJ filters that already exists.

electrogear ·

Hmm... I think this is way above my head.

electrogear ·

Hi dude,

I re-designed it so it uses the RBJ coded versions as you suggested, and all clicks & pops are gone. 😀 Can I get your full name so I can credit you for your help on this? PM me if you like.

Thanks 🙂

hudson_m ·

Hi

I'm fairly new to Synthmaker and have been trying to to adapt the EQ module to have low & high shelf filters, and have just found this old discussion thread. I can get a good visual shelf by just calculating new coefficients for the graph module but am stuck on the same problem electrogear had with the audio cutting out when exported as a VST.

I see the last post by electrogear was that by using the RBJ coded filters this fixed the problem, but I cant get it to work.

If electrogear is reads this (or anyone else?)... any chance of an OSM with your solution?

Mark

cyto ·

Hi Mark.

The RBJ shelving filters often do exhibit strange behavior depending on the ranges, etc. of the controls. RBJ himself has gone on record saying the reason there is no "formal" presentation of his paper is that he has not gotten the shelving filters quite right. Add to that the non-linearity of the coeff calculations (that really must be done in sync) and you have a very tricky task at hand. For your project, do you really need the amount of control of the biquads? If not, here is a stereo hi/lo shelving filter I put together awhile ago...

Each stage is just a simple first-order filter. They process the signal in series (loShelf->hiShelf), but using some asm wizardry, all four stages (rLo,rHi,lLo,lHi) are technically calculated by the CPU in parallel. IIRC, the filter section only uses about ten opcodes. I have found them to be perfectly fine for "EQ" type shelving (as opposed to precision "sculpting"). You can change some of the ranges (freq & gain, I think) in the various "properties" panels of the sub-modules. Anyway, if you just want a simple, stable solution, feel free to use them. If not, maybe post your working OSM and some of us might be able to point you in the right direction.

-cyto

hudson_m ·

Thanks for the fast reply, cyto!

No I don't need anything fancy, but I do need something that works so I will have a good look at your OSM. I just want a working 4 band EQ with LSH,PEQ,PEQ,HSH and graphical display to use in my teaching, so having top quality sound isn't a priority as much as just some thing that works. I am making a small set of VST and/or small .exes, so I can distribute to my pupils without any licensing issues. They can use these to learn with at home and then apply their knowledge in Logic, ProTools etc back in school.

Have learnt loads by this not working for me though... about filter equations and how SM functions, although the more complicated GUI stuff in the EQ module is challenging my brain.

Best Mark

hudson_m ·

Hi Again

Have fiddled around a bit and have managed to get a working Low Shelf using the RBJ module.

Attached is a very stripped down OSM EQ module with the RBJ Low Shelf placed inside the 'Graph' module... just to keep everything in one place whilst testing. Also in there is my LS Coeff module that feeds the graphical display (from the cookbook). All other filters and the phase parts are taken out so that the only thing left is the low shelf.

By no means finished... slope is just set to 1 and the gain range is -40 to +40 (from the original EQ module) whereas I guess it should be in the range -24 to +24 for the RBJ filter.

Still, at least I now have a low shelf VST that doesn't crash out or make nasty glitch noises 🙂

Any thoughts appreciated though, and if anyone else has been trying to do this, please use/fix/improve 😉

Mark

Wrote something here? To have a post removed or your name hidden, write to [email protected].

Before your first post

A few rules keep this a friendly place. You agree to them once.

Shown next to what you post, here and in the app. It doesn’t have to be your real name: 3–24 lower-case letters, digits or _ (capitals become lower case, spaces become _).

    Then your post goes up straight away.

    Delete this reply?

    Open it in SynthMaker?

    It goes on the track you’re editing there, in place of that track’s sound, and into My sounds. Your other tracks stay as they are.

    Want to keep that track’s sound? Start a new song in SynthMaker first (Song › New song), then open this.

    Report this reply?

    Only the developer reads reports. The person isn’t told who reported them.

    What’s wrong with it?

    Block this person?

    You won’t see their posts and replies here any more. They aren’t told, and you can unblock them at any time.

    People you’ve blocked

    Their posts and replies are hidden from you. Unblock someone to see them again.

    The community rules

    A few rules keep this a friendly place. Everyone agrees to them once, before their first post.