biquad output noise

Status
Not open for further replies.

do7jbh

New member
Hello *,
im am working on a SDR receiver based on the Teensy 3.6.
The receiver is based on the Weaver Mothod for SSB reception.
Bascialy I do filter and process the I2S audio signal comming from the SGTL5000.
I observed the following strage behaviour:
- The RMS level is lower at the I2S input (30 digits peak to peak ~ 4bits) than at the output of the biquad filter (150 digits peak to peak ~ 6 bits)
- The biquad is a low pass fc=6khz 8 pole 96ks

I checked the frequency response of the filter and it seems ok, filter coeffs have been calculated with iowahils.
What could that be?
 
Hi,

I found out the same a little while ago...
I think it is something called limit cycles. It is present when the input to the filter is very low. The filter itself will make the noise. With fixed points it will be a quite uniform/stable noise. But if you use floating points it will jump up and down in level...
There are several ways to "fix" it. But it is in the nature of IIR filters. So the simple solution is to use FIR filters...
You can read more about it here:
https://www.rane.com/note157.html#ref

or here:
http://freeverb3vst.osdn.jp/tips/iir_filter.shtml
 
Hi,
thanks for your answer.
I am still using the IIR because they are very god, knowing this (noisy output round 60 dB under max output) you can work on a work around.....thats what I did :)
 
Summarizing the main points from the links given above and summing this up with my own experience with IIR filters on the Teensy and having read pages 280ff in the excellent book by Rick Lyons (Understanding Digital Processing), maybe there is a simple solution to the problem:

* it seems the main problem in implementing IIR filters is the arithmetic accuracy of

1.) the filter coefficients (= coefficient quantization = limited precision coefficients),
2.) overflow errors in fixed-point calculations,
3.) roundoff errors = limit cycles = deadband effects

They cause "ringing" of the filter, also called "filter makes the noise", "self-oscillations", "stable noise", "biquad noise" etc.

(So it seems we also have a multitude of nomenclatural problems here ;-), but I personally think it breaks down to some simple recommendations.)

re 1.)
* using single precision floating point precision seems to be a good solution. 16-bit coefficients do not seem to provide enough precision (one of the sources says we need at least 20 bits for the recursive path and 16 bits for the non-recursive part)

2.) / 3.)

* use cascaded 2nd-order IIRs --> thats perfectly implemented in the audio lib by using cascaded biquad filters ! However, the user should ensure that the filter stages with the highest Q are placed first [but that is only possible in floating point implementations . . .]

* "the MAC operation should have at least 52 bits integer or double floating point precision" --> now thats really a hard criterion, eg. the variables in the Teensy audio lib are only 32bit precision

* to be honest, I have not understood noise shaping/dithering, so I will not comment on that, but it seems a possibility to improve the filters SNR for low frequencies, but increases SNR at high frequencies


CONCLUSION ("SIMPLE" SOLUTION):

* for most applications, the audio lib with 16bit fixed point coeffs as it is now, will be of sufficient quality!

* however, if you want lower noise, use float coefficients with single precision AND use floating point implementation of the calculations, as provided by the CMSIS implementations:

https://www.keil.com/pack/doc/CMSIS/DSP/html/group__BiquadCascadeDF1.html

Coefficients can be calculated by Iowa Hills IIR Filter designer (if you want fixed filter responses) or can be dynamically calculated (for 2nd order filters) by using these formulae http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt

For testing your filters and as a didactical excercise I would recommend the option "TestFilter" in the Iowa Hills IIR filter designer. Click on fixed point and change precision to 16bit. You will see that -caused by the limited precision- the filter response is entirely different than what you intended it to be . . . If you designed for 60dB stopband attenuation, it can easily be that the noise is 15 dB higher at only 45dB below the signal (especially for more exotic filter responses like the elliptic filter). This is the effect of the imprecision of the coeffs and the calculations that can be simulated and visualized in that program (however, I understand only part of the options that can be tweaked in the simulation program. Test it by yourself: try a lowpass with 80dB stopband attenuation and compare the output of a sinewave with 16bit fixed point and 32bit floating point respectively in the "TestFilter" option).

All the best,

Frank DD4WH
 
Last edited:
* for most applications, the audio lib with 16bit fixed point coeffs as it is now, will be of sufficient quality!

We're already using 32 bit coefficients and all 32 bit calculations within the biquad filter.

The 32 bits are truncated to 16 bit for the final output, and the low 16 bit are (perhaps incorrectly) fed back using the "noise shaping" technique described at this page. Scroll down to "Direct form I with first-order noise shaping".

http://www.earlevel.com/main/2003/02/28/biquads/

The audio lib's biquad coefficients have never been 16 bits.
 
Sorry, my mistake, I thought "int" was 16bit. So the coeffs have 32bit precision, I agree.

So, we boiled the problem down to the internal precision of the calculations:

The link you mentioned states:

In general, 16-bit fixed point processing is not suitable for audio without double precision coefficients and computation.

So, I think we would need double = 64bit calculations inside the code, which is 32bit at the moment.

This is also highlighted by http://freeverb3vst.osdn.jp/tips/iir_filter.shtml

The MAC operation should have at least 52 bits integer or double floating point precision.

As far as I can interpret the code with those highly optimized calculations, it has 32bit precision at the moment, but please correct me, if I am wrong.

How much performance you can gain from "noise shaping" and whether that is good for every desired frequency bandwidth, I simply do not know.

However, as I already stated, the current implementation of the biquad in the audio lib is still good enough for most applications!

But in the special case highlighted by the OP DO7JBH, to use IIRs as the main filter in an SDR, you will soon run into noise problems, especially if you design steep filter skirts with elliptic filter response.

However, I do not know if that is the filter response you chose in your design, DO7JBH? And what do you mean by "workaround", would be interesting to know!
 
We're already using 32 bit coefficients and all 32 bit calculations within the biquad filter.

The 32 bits are truncated to 16 bit for the final output, and the low 16 bit are (perhaps incorrectly) fed back using the "noise shaping" technique described at this page. Scroll down to "Direct form I with first-order noise shaping".

http://www.earlevel.com/main/2003/02/28/biquads/


The audio lib's biquad coefficients have never been 16 bits.

Seems like this is dithering? As dithering use a random signal injected into the filter. And the lowest bits are random(the noise floor) it should be about the same. But maybe worth a try to use white noise instead?
I don't fully understand the code, but is this feedback on every stage inside the filter or is it only a feedback at the end of the four stages?
 
But in the special case highlighted by the OP DO7JBH, to use IIRs as the main filter in an SDR, you will soon run into noise problems, especially if you design steep filter skirts with elliptic filter response.

However, I do not know if that is the filter response you chose in your design, DO7JBH? And what do you mean by "workaround", would be interesting to know!

Hi everyone,
I was not aware of the noise, I expected similar response to FIR at this point.
And because I build a receiver as described to be the third method (Weaver) I had not have to use the FIR Hilberts. In this case the IIR should offer better shape factors for less computing power.
At this point I measured the input signal direct after the filter with a regular bandwidth of e.g. 3kHz, I was wondering about the high noise level, this noise level was higher than at the input of the SGTL5000 which at this point had more than facto 30 higher bandwidth.
My workaround is like using the FFT (before any filtering) and only compute the energy at the bins representing the filter bandwidth.

daba
 
I don't fully understand the code, but is this feedback on every stage inside the filter or is it only a feedback at the end of the four stages?

Each biquad stage is implemented as the "Direct form I with first-order noise shaping" diagram on the Earlevel Biquads page.

BiquadDFIN.gif


Seems like this is dithering?

No, not dithering. This is feedback of the difference between the full 32 bit output state and the truncated 16 bits output (of each biquad stage).


But maybe worth a try to use white noise instead?

Seems unlikely to do anything but add noise, but who knows, maybe? Are you going to implement this and then carefully verify the result with and without the noise source added? Would you do this by actually running the code on Teensy? Or running numerically identical integer-only code on a PC? Or some other simulation that's not numerically identical to the actual implementation on Teensy?
 
Each biquad stage is implemented as the "Direct form I with first-order noise shaping" diagram on the Earlevel Biquads page.

View attachment 16246




No, not dithering. This is feedback of the difference between the full 32 bit output state and the truncated 16 bits output (of each biquad stage).




Seems unlikely to do anything but add noise, but who knows, maybe? Are you going to implement this and then carefully verify the result with and without the noise source added? Would you do this by actually running the code on Teensy? Or running numerically identical integer-only code on a PC? Or some other simulation that's not numerically identical to the actual implementation on Teensy?

I am running my code on Teensy yes. At the moment I am working on the HW on my project, but I will investigate this further when I get to the programming again and publish the results here.
 
Status
Not open for further replies.
Back
Top