Forums

Amplitude response of a Biquad Filter

Started by Web Surf January 27, 2006
in article gtKdnSB967nLbXHenZ2dnUVZ_sWdnZ2d@giganews.com, rkthebad at
raviyenduri@gmail.com wrote on 02/10/2006 14:58:
> > I am using a 16-bit fixed point implementation.
oooooooh. <shudder>. you will have real problems with the coefficients for the low band because they will be very close to 1. possibly so close that the difference between 1 and your 16 bit representation is less than an LSB. you might have to tweak the code a little for that and represent your a1/2 and a2 coefficients to be 1 minus their value (possible shifted left a few bits). is not your accumulator a double-wide (32-bits) accumulator?
> I have my filter routine setup in a direct form II configuration.
also, not good. the DF2 is essentially an all-pole filter followed by an all-zero filter. when the poles get real close to the unit circle, the gain gets very high (before any zeros are able to beat the gain down), the intermediate signal (sometimes called "w[n]" or "v[n]", whatever gets multiplied by b0 in the DF2) gets saturated and the information lost or error of that saturation is never recovered, and then the saturated signal goes into the all-zero filter (the numerator coefficients). in article SvadnRQZgaaGY3HeRVn-rw@giganews.com, rkthebad at raviyenduri@gmail.com wrote on 02/10/2006 15:56:
> I did not notice this earlier, but you suggested me to use a DF I > structure. But, isn't this more prone to quantization errors??
not any more than DF1 if your accumulator is double wide.
> Meanwhile, I shall even consider a DF I structure.
yes. that is why it is recommended (and the DF2 is not even mentioned) in the Cookbook. 16 bits, man... tough nut to crack... rots o' ruck. -- r b-j rbj@audioimagination.com "Imagination is more important than knowledge."
rkthebad wrote:

   ...

> I am not able to listen to white noise and differentiate the results. I > assumed that looking at the spectrum would give me a better idea and hence > did the same. > > Is there any other sanity check that I can perform?
Aside from double precision and DF 1, use a single pure sine at some low frequency (with some way to vary its amplitude) and see what settings produce saturation , or if indeed, saturation is the problem at all. Right now, that's just a guess. Jerry -- Engineering is the art of making what you want from things you can get. &#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;&#2013266095;
>in article gtKdnSB967nLbXHenZ2dnUVZ_sWdnZ2d@giganews.com, rkthebad at >raviyenduri@gmail.com wrote on 02/10/2006 14:58: >> >> I am using a 16-bit fixed point implementation. > >oooooooh. <shudder>. you will have real problems with the coefficients
for
>the low band because they will be very close to 1. possibly so close
that
>the difference between 1 and your 16 bit representation is less than an
LSB.
> >you might have to tweak the code a little for that and represent your
a1/2
>and a2 coefficients to be 1 minus their value (possible shifted left a
few
>bits). > >is not your accumulator a double-wide (32-bits) accumulator? > >> I have my filter routine setup in a direct form II configuration. > >also, not good. the DF2 is essentially an all-pole filter followed by
an
>all-zero filter. when the poles get real close to the unit circle, the
gain
>gets very high (before any zeros are able to beat the gain down), the >intermediate signal (sometimes called "w[n]" or "v[n]", whatever gets >multiplied by b0 in the DF2) gets saturated and the information lost or >error of that saturation is never recovered, and then the saturated
signal
>goes into the all-zero filter (the numerator coefficients). > >in article SvadnRQZgaaGY3HeRVn-rw@giganews.com, rkthebad at >raviyenduri@gmail.com wrote on 02/10/2006 15:56: > >> I did not notice this earlier, but you suggested me to use a DF I >> structure. But, isn't this more prone to quantization errors?? > >not any more than DF1 if your accumulator is double wide. > >> Meanwhile, I shall even consider a DF I structure. > >yes. that is why it is recommended (and the DF2 is not even mentioned)
in
>the Cookbook. > >16 bits, man... tough nut to crack... rots o' ruck. > >-- > >r b-j rbj@audioimagination.com > >"Imagination is more important than knowledge." > > >
Thanks for the details R-B-J. I would start with a DF 1 structure and see how it works. ~ R K
in article kradndJF5K8jkHDeRVn-ig@giganews.com, rkthebad at
raviyenduri@gmail.com wrote on 02/10/2006 17:03:

 
> Thanks for the details R-B-J.
you're welcome.
> I would start with a DF 1 structure and see how it works.
i dunno what platform this runs on but when you evaluate: y[n] = b0*x[n] + b1*x[n-1] + b2*x[n-2] - a1*y[n-1] - a2*y[n-2] (assumes a0 is normalized to 1) you should keep the intermediate products (.. b1*x[n-1], etc.) as double precision and add them up as double precision, before doing any rounding or truncating. also, probably more important since you're only 16 bit, you should be real anal about the scaling of the coefficients. i can tell you right now that -2 < a1 < +2 and -1 < a2 < +1 that means that a1 should be represented as half of its value: -1 < a1/2 < +1 and after multiplying, you then shift the product left 1 bit. you might do the same for the numerator coefficients if you know what they are. the last thing to think about (that someone with more bits might not worry about) is what Al Clark mentioned. you might want to do some noise shaping, particularly first order noise shaping with a zero at DC. this is otherwise known as "fraction saving" and is described a little here: http://www.dspguru.com/comp.dsp/tricks/alg/dc_block.htm The easiest way to do it might be to keep your double precision value of y[n] and use that to start with for the next sample. that makes the above DF1 equation look like: y[n] = y[n-1] + b0*x[n] + b1*x[n-1] + b2*x[n-2] - (a1+1)*y[n-1] - a2*y[n-2] the y[n-1] that you start with (on the left) is the double precision result of the previous sample output (before truncating). the other y[n-1] (multiplied by (a1+1) ) is a single precision *truncated* value of that previous double wide y[n-1] (and y[n-2] is the single precision value of the previous y[n-1] and, of course x[n], x[n-1], x[n-2] are single precision values of your input). when you truncate y[n-1], you should always be truncating _down_ (do not round to nearest) when doing this fraction saving. just hack off the 16 LSBs (take your result from the 16 MSBs). other than dithering or rewriting everything to be double precision coefficients, i can't think of anything else to do to make this work as well as can be expected for 16 bits. -- r b-j rbj@audioimagination.com "Imagination is more important than knowledge."
>in article kradndJF5K8jkHDeRVn-ig@giganews.com, rkthebad at >raviyenduri@gmail.com wrote on 02/10/2006 17:03: > > >> Thanks for the details R-B-J. > >you're welcome. > >> I would start with a DF 1 structure and see how it works. > >i dunno what platform this runs on but when you evaluate: > > y[n] = b0*x[n] + b1*x[n-1] + b2*x[n-2] - a1*y[n-1] - a2*y[n-2] > > (assumes a0 is normalized to 1) > >you should keep the intermediate products (.. b1*x[n-1], etc.) as double >precision and add them up as double precision, before doing any rounding
or
>truncating. also, probably more important since you're only 16 bit, you >should be real anal about the scaling of the coefficients. i can tell
you
>right now that > > -2 < a1 < +2 and -1 < a2 < +1 > >that means that a1 should be represented as half of its value: > > -1 < a1/2 < +1 > >and after multiplying, you then shift the product left 1 bit. you might
do
>the same for the numerator coefficients if you know what they are. > >the last thing to think about (that someone with more bits might not
worry
>about) is what Al Clark mentioned. you might want to do some noise
shaping,
>particularly first order noise shaping with a zero at DC. this is
otherwise
>known as "fraction saving" and is described a little here: > > http://www.dspguru.com/comp.dsp/tricks/alg/dc_block.htm > >The easiest way to do it might be to keep your double precision value of >y[n] and use that to start with for the next sample. that makes the
above
>DF1 equation look like: > > > y[n] = y[n-1] + b0*x[n] + b1*x[n-1] + b2*x[n-2] - (a1+1)*y[n-1] -
a2*y[n-2]
> > >the y[n-1] that you start with (on the left) is the double precision
result
>of the previous sample output (before truncating). the other y[n-1] >(multiplied by (a1+1) ) is a single precision *truncated* value of that >previous double wide y[n-1] (and y[n-2] is the single precision value
of
>the previous y[n-1] and, of course x[n], x[n-1], x[n-2] are single
precision
>values of your input). when you truncate y[n-1], you should always be >truncating _down_ (do not round to nearest) when doing this fraction
saving.
>just hack off the 16 LSBs (take your result from the 16 MSBs). > >other than dithering or rewriting everything to be double precision >coefficients, i can't think of anything else to do to make this work as
well
>as can be expected for 16 bits. > > >-- > >r b-j rbj@audioimagination.com > >"Imagination is more important than knowledge." > > >
Thank you. I did start to implement the equalizer in DF 1. Your explanation on the first order noise shaping is really helpful. I came across another point in your reply...about the scaling of the coefficients.I guess I am losing some precision trying to get all the coefficients in the same format. I might have to take that into consideration too. To answer your question, I am using Microsoft VC++ to execute my code. Thanks a ton, ~ R K
rkthebad wrote:

> > Thank you. > I did start to implement the equalizer in DF 1. Your explanation on the > first order noise shaping is really helpful. > I came across another point in your reply...about the scaling of the > coefficients.I guess I am losing some precision trying to get all the > coefficients in the same format. I might have to take that into > consideration too.
the coefficients with a greater range of magnitude (which means you store them scaled down the most) should be used first in the DF1 equation and you ASL (arithmetic shift left) them to the scaling of the next coefficient that you're adding into the accumulator.
> To answer your question, I am using Microsoft VC++ to execute my code.
your answer creates even more questions: 1. why? 2. what the f_ck? 3. running on a PC? why not use floating point? or some wider fixed? 4. are you using VC++ and this 16 bit integer thing to simulate doing this on some 16 bit DSP chip as a future target? does this target DSP have a 32 bit wide accumulator? 5. how do you even get 16 bit ints? ain't "short" a 32 bit int (since the data bus width is 32 bits)? 6. do you get these really fast cars and just drive them around at 30 km/hr?
> Thanks a ton,
7. where do i send the bill? r b-j
>rkthebad wrote: > >> >> Thank you. >> I did start to implement the equalizer in DF 1. Your explanation on
the
>> first order noise shaping is really helpful. >> I came across another point in your reply...about the scaling of the >> coefficients.I guess I am losing some precision trying to get all the >> coefficients in the same format. I might have to take that into >> consideration too. > >the coefficients with a greater range of magnitude (which means you >store them scaled down the most) should be used first in the DF1 >equation and you ASL (arithmetic shift left) them to the scaling of the >next coefficient that you're adding into the accumulator. > >> To answer your question, I am using Microsoft VC++ to execute my code. > >your answer creates even more questions: > >1. why? > >2. what the f_ck? > >3. running on a PC? why not use floating point? or some wider fixed? > >4. are you using VC++ and this 16 bit integer thing to simulate doing >this on some 16 bit DSP chip as a future target? does this target DSP >have a 32 bit wide accumulator? > >5. how do you even get 16 bit ints? ain't "short" a 32 bit int (since >the data bus width is 32 bits)? > >6. do you get these really fast cars and just drive them around at 30 >km/hr? > >> Thanks a ton, > >7. where do i send the bill? > >r b-j > >
Without getting carried away.....a floating point architecture for the equalizer works perfectly right now. am simulating the equalizer on a PC to use it later on a DSP. And, the DSP has a 40-bit accumulator. Thanks, ~ R K
So now my excel spreadsheet implementing R B-J's equations work fine.

R B-J assisted me to build a "Master Volume Control" for the 5 band
equaliser. It adds/subtracts some dB from the reponse of each filter based
on the setting of the Master Volume control, by changing the coefficients (
multiply all the B coefficients with A^2)



However I notice that if I set up a particular Q on the notch and Peak
filters and sweep the Fo from 20 - 20KHz and see the freq graph,

A) The maximum cut/boost varies based on the Fo. Ie for same Q, at some
Fo, the cut is -5 dB and for other Fo it is -50 dB

B) for the same Q and Fo, The shape of the Peak filter is not the mirror
image of the notch.

I was not expecting this as the shape of the Low pass/High Pass/Low
Shelf/Hi Shelf do not change with different Fo.

Any ideas ? 
>rkthebad wrote: > >> >> Thank you. >> I did start to implement the equalizer in DF 1. Your explanation on
the
>> first order noise shaping is really helpful. >> I came across another point in your reply...about the scaling of the >> coefficients.I guess I am losing some precision trying to get all the >> coefficients in the same format. I might have to take that into >> consideration too. > >the coefficients with a greater range of magnitude (which means you >store them scaled down the most) should be used first in the DF1 >equation and you ASL (arithmetic shift left) them to the scaling of the >next coefficient that you're adding into the accumulator. > >> To answer your question, I am using Microsoft VC++ to execute my code. > >your answer creates even more questions: > >1. why? > >2. what the f_ck? > >3. running on a PC? why not use floating point? or some wider fixed? > >4. are you using VC++ and this 16 bit integer thing to simulate doing >this on some 16 bit DSP chip as a future target? does this target DSP >have a 32 bit wide accumulator? > >5. how do you even get 16 bit ints? ain't "short" a 32 bit int (since >the data bus width is 32 bits)? > >6. do you get these really fast cars and just drive them around at 30 >km/hr? > >> Thanks a ton, > >7. where do i send the bill? > >r b-j > >
I did implement a DF-1 structure with first order noise shaping. The output sounds much better for an 8-bit input. Thanks a lot for your suggestions. ~ R K
>>rkthebad wrote: >> >>> >>> Thank you. >>> I did start to implement the equalizer in DF 1. Your explanation on >the >>> first order noise shaping is really helpful. >>> I came across another point in your reply...about the scaling of the >>> coefficients.I guess I am losing some precision trying to get all the >>> coefficients in the same format. I might have to take that into >>> consideration too. >> >>the coefficients with a greater range of magnitude (which means you >>store them scaled down the most) should be used first in the DF1 >>equation and you ASL (arithmetic shift left) them to the scaling of the >>next coefficient that you're adding into the accumulator. >> >>> To answer your question, I am using Microsoft VC++ to execute my
code.
>> >>your answer creates even more questions: >> >>1. why? >> >>2. what the f_ck? >> >>3. running on a PC? why not use floating point? or some wider fixed? >> >>4. are you using VC++ and this 16 bit integer thing to simulate doing >>this on some 16 bit DSP chip as a future target? does this target DSP >>have a 32 bit wide accumulator? >> >>5. how do you even get 16 bit ints? ain't "short" a 32 bit int (since >>the data bus width is 32 bits)? >> >>6. do you get these really fast cars and just drive them around at 30 >>km/hr? >> >>> Thanks a ton, >> >>7. where do i send the bill? >> >>r b-j >> >> >I did implement a DF-1 structure with first order noise shaping. The >output sounds much better for an 8-bit input. > >Thanks a lot for your suggestions. >~ R K > >
I implemented the EQ with the DF-1 structure with first order noise shaping. There appears to be some problem though. A desired output is obtained only for some settings of the EQ. If the settings (coefficients) are changed, the output goes wild. Any suggestions? I have observed that when I am trying to boost the BASS of the system, my system behaves erratically. But, this problem was overcome by placing the coefficients of the first band at the end of the cascaded structure. Why is this so? Thanks in anticipation, ~ R K