From the original SynthMaker forum (2004–2014), with its members’ names and dates.
oddson ·
I'm finally trying to understand filters and I'm starting with the bi-quad.
Here are two block schematics I found on the web...
{edit 2012}The image from JoS is different than it was when this thread was being discussed and i think the parameters used then may have been different too. {/edit}
So I'm a little confused...
Are these equivalent or not?
Is one the standard?
Is one in error?
Why are there sometimes 5 and sometimes 6 coefficients for the biquad (including in SM where the 2p2z primative - the tool-tip for which says it is a biquad - has no 'b0' but the frequency and phase response analyzers do)?
As best as I can tell the extra coefficient seems to be related to the gain of the system and so there are less than 6 degrees of freedom (but is it 5 or 4?)
😕
stefan ·
They are "equivalent". They have just swapped the a and the b coefficients. They are also swapped in the coefficient calculation, so you end up with the same coeffs at the same places really. But it is confusing nonetheless.
In the first picture, they have left out "a0", which is the "gain" of the entire filter. This is probably because they have normalized the coefficients by a0, which you do by dividing all the other coefficients with a0. or. Actuall, not "all the other", but "all coefficients". a0/a0 ends up being 1, hence, that one can be stripped out from the schematic.
a0 would normally reside right above "-a1", as a gain stage.
Sometimes people don't use "-a1" and "-a2", but just "a1" and "a2" instead, and make sure that the actual coefficient have the right sign instead.
Now, to mess things up for you, in the ParametricEQ and the biquad analysers, we use the 2nd picture version, but unnormalized, so b0 is kept and used. The normalization is made within the filter / analysers.
Sorry if biquads are a bit messy. Not my fault there's no "standard" way to do it 🙂
oddson ·
Thanks, I almost get it now...
Shouldn't the SM primative use the same conventions as the SM Freq/Phase analyzers?
stefan ·
oddson wrote: Thanks, I almost get it now...
Shouldn't the SM primative use the same conventions as the SM Freq/Phase analyzers?
I guess... I didn't even think about the primitive when I implemented the EQ or when I told jorge how to make the analysers. Is it not better to use the implementations in the EQ? (since there are two flavors I mean, stream coeffs and green float data coeffs).
I don't know really 🙂
oddson ·
It's better for all the parts of SM to be internally consistent...
I'm using your code for the EQ for learning purposes, I just noticed the lack of a 'b0' coefficient in the 2P2Z today...
I'm still thinking your first response through... expect more questions..
A little suggesstion to the SM team: Expand the tooltip text of the 2P2Z module, so that it shows the biquad's transfer function. I'm always confused when using it and have to cross-check with an example jorge posted here some months ago.
oddson wrote:
My algebra is 20 years rusty but, couldn't you use:
I think so too. Your calculation also uses less multiplies -> less clock cyles.
But care has to be taken on lengthy expressions since there is only a limited set of SSE registers. The code module gives no indication when an expression cannot be mapped to the SSE register set.
I could get the discrete version out of the "before normalization" transfer function, if you really really really need it 🙂 In the end, we will turn out calculating the same thing though.
oddson wrote: Second, why would you caluclate all those intermediaries instead of using the distributive property of multiplication?
My algebra is 20 years rusty but, couldn't you use:
so, was this a mistake, or are you using some secret wisdom? 😉
stefan ·
mistake 🙁
infuzion ·
rl wrote: But care has to be taken on lengthy (Code) expressions since there is only a limited set of SSE registers. The code module gives no indication when an expression cannot be mapped to the SSE register set.
I never thought of that, but it makes sence... how many registers are there? How can we tell if we hit the limit?
TIA
rl ·
Jorge has given an example here
oddson ·
rl wrote: ...so, was this [in = in - 0.00000000001] a mistake, or are you using some secret wisdom?
That's that thing I found when trying to make a A/D envelope for my Karplus... the input variables are read-only, correct?
stefan wrote: ...[the two diagrams] are "equivalent". They have just swapped the a and the b coefficients. They are also swapped in the coefficient calculation, so you end up with the same coeffs at the same places really. But it is confusing nonetheless.
OK, first I know they are functionally equivalent, but are the coefficient groups actually interchangable? I'm dubious about ending up with the "same coeffs at the same places"
Especially given the first direct form
y[n] = (b0/a0)*x[n] + (b1/a0)*x[n-1] + (b2/a0)*x[n-2] - (a1/a0)*y[n-1] - (a2/a0)*y[n-2]"
In this, only a0 is in a denominator position... so why are we dividing by b0?
But if you've used the other version of the output transform, how can you use the coefficient recipes from the cookbook? [e.i. shouldn't a0 be b0 etc...]
But clearly it's working for your peaking filters, but I can't make anything else work by following the cookbook...
😕 ^2
infuzion ·
rl wrote: Jorge has given an example here
Dang, that was almost a year ago! Before my time.
thanks for the link 🙂
stefan ·
oddson wrote:
rl wrote: ...so, was this [in = in - 0.00000000001] a mistake, or are you using some secret wisdom?
That's that thing I found when trying to make a A/D envelope for my Karplus... the input variables are read-only, correct?
stefan wrote: ...[the two diagrams] are "equivalent". They have just swapped the a and the b coefficients. They are also swapped in the coefficient calculation, so you end up with the same coeffs at the same places really. But it is confusing nonetheless.
OK, first I know they are functionally equivalent, but are the coefficient groups actually interchangable? I'm dubious about ending up with the "same coeffs at the same places"
Especially given the first direct form
y[n] = (b0/a0)*x[n] + (b1/a0)*x[n-1] + (b2/a0)*x[n-2] - (a1/a0)*y[n-1] - (a2/a0)*y[n-2]"
In this, only a0 is in a denominator position... so why are we dividing by b0?
But if you've used the other version of the output transform, how can you use the coefficient recipes from the cookbook? [e.i. shouldn't a0 be b0 etc...]
But clearly it's working for your peaking filters, but I can't make anything else work by following the cookbook...
😕 ^2
The thing is that we also swap the _calculations_ of the coefficients.
That is, in the second schematic (the picture) b1 is calculated like a1 is calculated for the first schematic. And so forth...
oddson ·
Sorry if I'm seeming to be dense, but sometimes I am...
Is this the correct block diagram for the SM biquad freq/phase analyzers?
That is, would this diagram lead to the correct interpretation of the coefficients used in the analyzers?
Are the signs correct on the b1 and b2? So positive values of the coefficients result in inverted phase signals?
For this diagram would the (direct, non-normalized) output function be?:
I'm usually using this post as a reference:
Equalizer
Borogove ·
Then there's Direct Form II...
oddson ·
Borogove wrote: Then there's Direct Form II...
Right, but that's with the other assignation of the coefficients (ur, um, the 'a's and 'b's are switched).
It also lacks b0 (a0 with it's conventions).
Direct Form II is the form in Jorge's block flow diagram that rl's post above links to.
sambean ·
For this diagram would the (direct, non-normalized) output function be?:
Try not to think of the coefficients as the 'a coefficients' and the 'b coefficients' as I don't think there's a set convention. To distinguish them think of them as the 'feedforward coefficients' and the 'feedback coefficients'. In most cases the biquads will be normalised so you'll have 3 feedfoward (either a's or b's) and 2 feedback coefficients...