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-]
An IIR filter gain questio
Started by ●May 13, 2006
Reply by ●May 13, 20062006-05-13
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
Reply by ●May 14, 20062006-05-14
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
Reply by ●May 14, 20062006-05-14
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
Reply by ●May 14, 20062006-05-14
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
Reply by ●May 14, 20062006-05-14
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
Reply by ●May 14, 20062006-05-14
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
Reply by ●May 14, 20062006-05-14
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
Reply by ●May 14, 20062006-05-14
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
Reply by ●May 14, 20062006-05-14
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