DSPRelated.com
Forums

An IIR filter gain questio

Started by Rick Lyons May 13, 2006

Hi Guys,

I have a (probably simple) question about 
"scaling" the coeffs of an IIR filter.
I've been workin' on an simple 2nd-order
biquad filter that takes the standard form:

 x --->(+)----->----------b0----->(+)---> y   
        ^           |              ^
        |         [z^-1]           |
        |           |              |
       (+)<---a1----+------b1---->(+)
        ^           |              ^
        |         [z^-1]           |
        |           |              |
        +----a2-----+------b2------+

(I stole this ASCII diagram from Jim Thomas.)

Now, due to the values of the coefficients of the 
filter I'm working on, the filter's gain is huge!  
In the hundreds!

Seeking to reduce the filter's gain I started 
to try to learn more about how to "scale" a 
biquad's coefficients to reduce its inherent gain 
without changing its freq response.
(There's not much material on this "IIR scaling" 
topic in the DSP books on my bookshelf.  Then, 
again, I don't have Al Clark's bookshelf.)

Reviewing the exciting narrative on "IIR filter 
scaling" in Dale Grover's and John Deller' DSP 
book, I have arrived at the IIR filter shown as: 

 x --->(+)--1/Gb-->------Gf*b0--->(+)---> y   
        ^           |              ^
        |         [z^-1]           |
        |           |              |
       (+)<--a1/Gb--+----Gf*b1--->(+)
        ^           |              ^
        |         [z^-1]           |
        |           |              |
        +---a2/Gb---+----Gf*b2-----+

That is, the original IIR filter's feedback coeffs 
are divided by a feedback gain factor "Gb", 
and feedforward coeffs are multiplied by a 
feedforward gain factor "Gf".  The result of 
using these two Gb & Gf gain factors is a new biquad 
whose gain is the original biquad's gain multiplied 
by "Gb times Gf" (GbGf).  

So my MATLAB modeling is telling me that 
if I want to increase the original biquad's gain 
by 8, I can set Gb=4 & Gf=2.  On the other hand, 
if I want to decrease the original biquad's gain 
by 0.25, I can set Gb=0.5 & Gf=0.5.

So here are my questions that I hope you guys can 
help me answer: Is the above "scaled" block 
diagram correct?  Is it really that simple to 
control the gain of a biquad IIR filter?  

The reason I ask those questions is because I've 
learned that when I think I see something "simple" 
in DSP I must remember what Gina Davis (Veronica) 
said in the movie The Fly.  She said, "Be afraid. 
Be very afraid."   

I think of Gina's quote because too many times in 
the past when I thought I had a "simple" solution 
to a problem it turned out later that my "simple" 
solution spun around to bite me in the rear end!

OK guys, am I missing something important here 
in my simple IIR biquad scaling technique?

Thanks much for your advice,
[-Rick-]


On Sun, 14 May 2006 02:02:41 GMT, R.Lyons@_BOGUS_ieee.org (Rick Lyons)
wrote:

>That is, the original IIR filter's feedback coeffs >are divided by a feedback gain factor "Gb", >and feedforward coeffs are multiplied by a >feedforward gain factor "Gf". The result of >using these two Gb & Gf gain factors is a new biquad >whose gain is the original biquad's gain multiplied >by "Gb times Gf" (GbGf).
Before scaling, you had this: -1 -n b + b z + ... + b z Y(z) 0 1 n ---- = ----------------------- U(z) -1 -d 1 + a z + ... + a z 1 d After scaling, you have this: -1 -n b + b z + ... + b z Y'(z) Gf 0 1 n ----- = ---- * ----------------------- U'(z) 1/Gb -1 -d 1 + a z + ... + a z 1 d or: Y'(z) Gf Y(z) ----- = ---- * ---- U'(z) 1/Gb U(z) Y(z) = GbGf * ---- U(z) You do have to be aware of the possibility of internal numerical overflows, in the numerator if Gf > 1 and in the denominator if Gb < 1. Since you have control over how to distribute the quantity "GbGf" among Gf and Gb, you should be able to minimize this. It might even be wise, in some circumstances, to apply part of the total gain modification externally: -1 -n b + b z + ... + b z Y"(z) Gf 0 1 n ----- = Ge * ---- * ----------------------- U"(z) 1/Gb -1 -d 1 + a z + ... + a z 1 d Greg
Rick Lyons wrote:

> > Reviewing the exciting narrative on "IIR filter > scaling" in Dale Grover's and John Deller' DSP > book, I have arrived at the IIR filter shown as: > > x --->(+)--1/Gb-->------Gf*b0--->(+)---> y > ^ | ^ > | [z^-1] | > | | | > (+)<--a1/Gb--+----Gf*b1--->(+) > ^ | ^ > | [z^-1] | > | | | > +---a2/Gb---+----Gf*b2-----+ > > That is, the original IIR filter's feedback coeffs > are divided by a feedback gain factor "Gb", > and feedforward coeffs are multiplied by a > feedforward gain factor "Gf". The result of > using these two Gb & Gf gain factors is a new biquad > whose gain is the original biquad's gain multiplied > by "Gb times Gf" (GbGf).
i think the feedforward gain of 1/Gb needs to be changed to just "Gb" as so: x --->(+)---Gb--->------Gf*b0--->(+)---> y ^ | ^ | [z^-1] | | | | (+)<--a1/Gb--+----Gf*b1--->(+) ^ | ^ | [z^-1] | | | | +---a2/Gb---+----Gf*b2-----+ which becomes: x -Gb->(+)-------->------Gf*b0--->(+)---> y ^ | ^ Gb [z^-1] | | | | (+)<--a1/Gb--+----Gf*b1--->(+) ^ | ^ | [z^-1] | | | | +---a2/Gb---+----Gf*b2-----+ and thus: x -Gb->(+)-------->------Gf*b0--->(+)---> y ^ | ^ | [z^-1] | | | | (+)<---a1----+----Gf*b1--->(+) ^ | ^ | [z^-1] | | | | +-----a2----+----Gf*b2-----+
> So here are my questions that I hope you guys can > help me answer: Is the above "scaled" block > diagram correct?
i think it is after i fixed it.
> Is it really that simple to > control the gain of a biquad IIR filter?
i presume the Gf thingie is a non-issue. that sorta thing is done all the time with IIRs. with Gb, you are simply scaling those states with Gb. if you're doing that for fixed-point issues, i think there are better ways to either think about it or to implement it (like ditch the DF2 and do it with DF1). for floating-point, it seems pointless to me, but there is lotsa esoteric stuff that i dunno. r b-j
On 13 May 2006 22:47:55 -0700, "robert bristow-johnson"
<rbj@audioimagination.com> wrote:

>i think the feedforward gain of 1/Gb needs to be changed to just "Gb" >as so: > > x --->(+)---Gb--->------Gf*b0--->(+)---> y > ^ | ^ > | [z^-1] | > | | | > (+)<--a1/Gb--+----Gf*b1--->(+) > ^ | ^ > | [z^-1] | > | | | > +---a2/Gb---+----Gf*b2-----+
Interesting. Bob, if I extract the causal difference equation from your diagram, I get: y(n) = Gb[Gfb0x(n)+Gfb1x(n-1)+Gfb2x(n-2)]+a1y(n-1)+a2y(n-2) = GbGf[b0x(n)+b1x(n-1)+b2x(n-2)]+a1y(n-1)+a2y(n-2) If I do the same for the equation form that I used in my earlier posting, -1 -2 b + b z + b z Y(z) Gf 0 1 2 ---- = ---- * ---------------- U(z) 1/Gb -1 -2 1 + a z + a z 1 2 I get: y(n)/Gb = Gfb0x(n)+Gfb1x(n-1)+Gfb2x(n-2)+[a1/Gb]y(n-1)+[a2/Gb]y(n-2) = Gf[b0x(n)+b1x(n-1)+b2x(n-2)]+[1/Gb][a1y(n-1)+a2y(n-2)] I hadn't realized it without a detailed look, but the output y(n) from your method IS the scaled value. The output y(n)/Gb from my method needs to be multiplied by Gb before it yields the scaled value: y(n) = GbGf[b0x(n)+b1x(n-1)+b2x(n-2)]+a1y(n-1)+a2y(n-2) They are mathematically equivalent, but mine requires an additional step before it comes up with the desired answer. Nice catch. Greg
On 13 May 2006 22:47:55 -0700, "robert bristow-johnson"
<rbj@audioimagination.com> wrote:

>i think the feedforward gain of 1/Gb needs to be changed to just "Gb" >as so: > > x --->(+)---Gb--->------Gf*b0--->(+)---> y > ^ | ^ > | [z^-1] | > | | | > (+)<--a1/Gb--+----Gf*b1--->(+) > ^ | ^ > | [z^-1] | > | | | > +---a2/Gb---+----Gf*b2-----+
Interesting. Bob, if I extract the causal difference equation from your diagram, I get: y(n) = Gb[Gfb0x(n)+Gfb1x(n-1)+Gfb2x(n-2)]+a1y(n-1)+a2y(n-2) = GbGf[b0x(n)+b1x(n-1)+b2x(n-2)]+a1y(n-1)+a2y(n-2) If I do the same for the equation form that I used in my earlier posting, -1 -2 b + b z + b z Y(z) Gf 0 1 2 ---- = ---- * ---------------- U(z) 1/Gb -1 -2 1 + a z + a z 1 2 I get: y(n)/Gb = Gfb0x(n)+Gfb1x(n-1)+Gfb2x(n-2)+[a1/Gb]y(n-1)+[a2/Gb]y(n-2) = Gf[b0x(n)+b1x(n-1)+b2x(n-2)]+[1/Gb][a1y(n-1)+a2y(n-2)] I hadn't realized it without a detailed look, but the output y(n) from your method IS the scaled value. The output y(n)/Gb from my method needs to be multiplied by Gb before it yields the scaled value: y(n) = GbGf[b0x(n)+b1x(n-1)+b2x(n-2)]+a1y(n-1)+a2y(n-2) They are mathematically equivalent, but mine requires an additional step before it comes up with the desired answer. Nice catch. Greg
On 13 May 2006 22:47:55 -0700, "robert bristow-johnson"
<rbj@audioimagination.com> wrote:

>i think the feedforward gain of 1/Gb needs to be changed to just "Gb" >as so: > > x --->(+)---Gb--->------Gf*b0--->(+)---> y > ^ | ^ > | [z^-1] | > | | | > (+)<--a1/Gb--+----Gf*b1--->(+) > ^ | ^ > | [z^-1] | > | | | > +---a2/Gb---+----Gf*b2-----+
Interesting. Bob, if I extract the causal difference equation from your diagram, I get: y(n) = Gb[Gfb0x(n)+Gfb1x(n-1)+Gfb2x(n-2)]+a1y(n-1)+a2y(n-2) = GbGf[b0x(n)+b1x(n-1)+b2x(n-2)]+a1y(n-1)+a2y(n-2) If I do the same for the equation form that I used in my earlier posting, -1 -2 b + b z + b z Y(z) Gf 0 1 2 ---- = ---- * ---------------- U(z) 1/Gb -1 -2 1 + a z + a z 1 2 I get: y(n)/Gb = Gfb0x(n)+Gfb1x(n-1)+Gfb2x(n-2)+[a1/Gb]y(n-1)+[a2/Gb]y(n-2) = Gf[b0x(n)+b1x(n-1)+b2x(n-2)]+[1/Gb][a1y(n-1)+a2y(n-2)] I hadn't realized it without a detailed look, but the output y(n) from your method IS the scaled value. The output y(n)/Gb from my method needs to be multiplied by Gb before it yields the scaled value: y(n) = GbGf[b0x(n)+b1x(n-1)+b2x(n-2)]+a1y(n-1)+a2y(n-2) They are mathematically equivalent, but mine requires an additional step before it comes up with the desired answer. Nice catch. Greg
On 13 May 2006 22:47:55 -0700, "robert bristow-johnson"
<rbj@audioimagination.com> wrote:

>i think the feedforward gain of 1/Gb needs to be changed to just "Gb" >as so: > > x --->(+)---Gb--->------Gf*b0--->(+)---> y > ^ | ^ > | [z^-1] | > | | | > (+)<--a1/Gb--+----Gf*b1--->(+) > ^ | ^ > | [z^-1] | > | | | > +---a2/Gb---+----Gf*b2-----+
Interesting. Bob, if I extract the causal difference equation from your diagram, I get: y(n) = Gb[Gfb0x(n)+Gfb1x(n-1)+Gfb2x(n-2)]+a1y(n-1)+a2y(n-2) = GbGf[b0x(n)+b1x(n-1)+b2x(n-2)]+a1y(n-1)+a2y(n-2) If I do the same for the equation form that I used in my earlier posting, -1 -2 b + b z + b z Y(z) Gf 0 1 2 ---- = ---- * ---------------- U(z) 1/Gb -1 -2 1 + a z + a z 1 2 I get: y(n)/Gb = Gfb0x(n)+Gfb1x(n-1)+Gfb2x(n-2)+[a1/Gb]y(n-1)+[a2/Gb]y(n-2) = Gf[b0x(n)+b1x(n-1)+b2x(n-2)]+[1/Gb][a1y(n-1)+a2y(n-2)] I hadn't realized it without a detailed look, but the output y(n) from your method IS the scaled value. The output y(n)/Gb from my method needs to be multiplied by Gb before it yields the scaled value: y(n) = GbGf[b0x(n)+b1x(n-1)+b2x(n-2)]+a1y(n-1)+a2y(n-2) They are mathematically equivalent, but mine requires an additional step before it comes up with the desired answer. Nice catch. Greg
On 13 May 2006 22:47:55 -0700, "robert bristow-johnson"
<rbj@audioimagination.com> wrote:

>i think the feedforward gain of 1/Gb needs to be changed to just "Gb" >as so: > > x --->(+)---Gb--->------Gf*b0--->(+)---> y > ^ | ^ > | [z^-1] | > | | | > (+)<--a1/Gb--+----Gf*b1--->(+) > ^ | ^ > | [z^-1] | > | | | > +---a2/Gb---+----Gf*b2-----+
Interesting. Bob, if I extract the causal difference equation from your diagram, I get: y(n) = Gb[Gfb0x(n)+Gfb1x(n-1)+Gfb2x(n-2)]+a1y(n-1)+a2y(n-2) = GbGf[b0x(n)+b1x(n-1)+b2x(n-2)]+a1y(n-1)+a2y(n-2) If I do the same for the equation form that I used in my earlier posting, -1 -2 b + b z + b z Y(z) Gf 0 1 2 ---- = ---- * ---------------- U(z) 1/Gb -1 -2 1 + a z + a z 1 2 I get: y(n)/Gb = Gfb0x(n)+Gfb1x(n-1)+Gfb2x(n-2)+[a1/Gb]y(n-1)+[a2/Gb]y(n-2) = Gf[b0x(n)+b1x(n-1)+b2x(n-2)]+[1/Gb][a1y(n-1)+a2y(n-2)] I hadn't realized it without a detailed look, but the output y(n) from your method IS the scaled value. The output y(n)/Gb from my method needs to be multiplied by Gb before it yields the scaled value: y(n) = GbGf[b0x(n)+b1x(n-1)+b2x(n-2)]+a1y(n-1)+a2y(n-2) They are mathematically equivalent, but mine requires an additional step before it comes up with the desired answer. Nice catch. Greg
On 13 May 2006 22:47:55 -0700, "robert bristow-johnson"
<rbj@audioimagination.com> wrote:

>i think the feedforward gain of 1/Gb needs to be changed to just "Gb" >as so: > > x --->(+)---Gb--->------Gf*b0--->(+)---> y > ^ | ^ > | [z^-1] | > | | | > (+)<--a1/Gb--+----Gf*b1--->(+) > ^ | ^ > | [z^-1] | > | | | > +---a2/Gb---+----Gf*b2-----+
Interesting. Bob, if I extract the causal difference equation from your diagram, I get: y(n) = Gb[Gfb0x(n)+Gfb1x(n-1)+Gfb2x(n-2)]+a1y(n-1)+a2y(n-2) = GbGf[b0x(n)+b1x(n-1)+b2x(n-2)]+a1y(n-1)+a2y(n-2) If I do the same for the equation form that I used in my earlier posting, -1 -2 b + b z + b z Y(z) Gf 0 1 2 ---- = ---- * ---------------- U(z) 1/Gb -1 -2 1 + a z + a z 1 2 I get: y(n)/Gb = Gfb0x(n)+Gfb1x(n-1)+Gfb2x(n-2)+[a1/Gb]y(n-1)+[a2/Gb]y(n-2) = Gf[b0x(n)+b1x(n-1)+b2x(n-2)]+[1/Gb][a1y(n-1)+a2y(n-2)] I hadn't realized it without a detailed look, but the output y(n) from your method IS the scaled value. The output y(n)/Gb from my method needs to be multiplied by Gb before it yields the scaled value: y(n) = GbGf[b0x(n)+b1x(n-1)+b2x(n-2)]+a1y(n-1)+a2y(n-2) They are mathematically equivalent, but mine requires an additional step before it comes up with the desired answer. Nice catch. Greg
On 13 May 2006 22:47:55 -0700, "robert bristow-johnson"
<rbj@audioimagination.com> wrote:

>i think the feedforward gain of 1/Gb needs to be changed to just "Gb" >as so: > > x --->(+)---Gb--->------Gf*b0--->(+)---> y > ^ | ^ > | [z^-1] | > | | | > (+)<--a1/Gb--+----Gf*b1--->(+) > ^ | ^ > | [z^-1] | > | | | > +---a2/Gb---+----Gf*b2-----+
Interesting. Bob, if I extract the causal difference equation from your diagram, I get: y(n) = Gb[Gfb0x(n)+Gfb1x(n-1)+Gfb2x(n-2)]+a1y(n-1)+a2y(n-2) = GbGf[b0x(n)+b1x(n-1)+b2x(n-2)]+a1y(n-1)+a2y(n-2) If I do the same for the equation form that I used in my earlier posting, -1 -2 b + b z + b z Y(z) Gf 0 1 2 ---- = ---- * ---------------- U(z) 1/Gb -1 -2 1 + a z + a z 1 2 I get: y(n)/Gb = Gfb0x(n)+Gfb1x(n-1)+Gfb2x(n-2)+[a1/Gb]y(n-1)+[a2/Gb]y(n-2) = Gf[b0x(n)+b1x(n-1)+b2x(n-2)]+[1/Gb][a1y(n-1)+a2y(n-2)] I hadn't realized it without a detailed look, but the output y(n) from your method IS the scaled value. The output y(n)/Gb from my method needs to be multiplied by Gb before it yields the scaled value: y(n) = GbGf[b0x(n)+b1x(n-1)+b2x(n-2)]+a1y(n-1)+a2y(n-2) They are mathematically equivalent, but mine requires an additional step before it comes up with the desired answer. Nice catch. Greg