Help - Search - Members - Calendar
Full Version: new article about noise shaping
Hydrogenaudio Forums > Knowledgebase Project > Wiki Discussion
SebastianG
Hi!

I've added a new article about noise shaping. I guess it doesn't fully qualify as a proper encyclopdia article due to the occasional personal/tutorial tone and lack of references but it's a start.

Noise shaping

Cheers!
SG
Nick.C
Many, many thanks Sebastian!
SebastianG
Darn!
I just wanted to fix a typo and pressed reply instead of edit.
Please ignore this.
eevan
Is it „encyclopdia” you wanted to fix? smile.gif

For me, typos are not relevant unless they completely change the meaning of a word. Then they are dangerous wink.gif

Your wiki article is of very good quality!
Slipstreem
Many thanks indeed. Fascinating stuff! smile.gif

Cheers, Slipstreem. cool.gif
2Bdecided
Thank you Sebastian!

The "Decoupling filtering and quantization" was particularly useful and clear.


Please mention somewhere appropriate that SACD is not dithered - or at least, not dither correctly, since this would leave no room for the signal! Hence SACD falls under the criticism you make within the first sentence of the "Limits & filter design restrictions" section. Its placement above implies that it does not have this problem.

Cheers,
David.
SebastianG
Thank you for your kind responses.

As for the SACD dithering issue I think it's on the verge to being off-topic but I added it nonetheless because I covered "undithered quantization" and the SACD example as well.

Cheers!
SG
DualIP
Thx Sebastian for great article.

At the moment I'm adding dither routine based on your algoritm to mplayers ogg and mp3 decoder.
I implemented your article in integer only routine, which takes about 1% CPU on P3@1GHz for stereo 44.1kHz.
Haven't tested with music yet, but on a low amplitude sine generated in C, algoritm works like a charm!

#include "tgmath.h"
#include "stdlib.h"


int NoiseShapedDither(in,ch)
int ch;
long in;
{
/* 32 bit integer in
relation 32bit input sample <==> 16 bit audio output: aud32=aud16<<11;
This gives 11 bits resolution for dither, 5 bits peak headroom */

#define MAXCH 8 /* multi channel audio 8 ch should suffice.
CHANGING MAXCH breaks array initializations!! */
static unsigned long rnd=256; /* 32bits fibonacci shift reg PRNG. Init at any value but 0....*/
long wanted,quantized;
static long h_out [5] [MAXCH] =
{ {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0} };
static long last_error [4] [MAXCH] =
{ {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0} };


h_out[4][ch]=h_out [3][ch];
h_out[3][ch]=h_out [2][ch];
h_out[2][ch]=h_out [1][ch];
h_out[1][ch]=h_out [0][ch];
/* based on 44.1k LAME ath IIR formula for hearing treshold */
h_out[0][ch]= (-17346*h_out[1][ch] -1108*h_out[2][ch] + 9919*h_out[3][ch] + 4486*h_out[4][ch]
+36145*last_error[0][ch] -7710*last_error[1][ch] -4152*last_error[2][ch] -10181*last_error[3][ch]) ;

h_out[0][ch]= h_out[0][ch] >> 14 ; /* compensate for scaling in previous line */

wanted=in-h_out[0][ch];

/* GENERATE 22 new random bits. Generator based on 32 bit Fibonacci shift register. */
rnd= (rnd<<22) + ( 0x003FFFFF & ( (rnd>>9) ^ (rnd>>7) ^ (rnd>>6) ^ rnd ) );
/* from 32bits, use 2 11 bits parts as random numbers (=triangularPDF), offset and quantize ......*/
quantized=0xFFFFF800 & ( wanted - 1024 + ( (rnd>>11)&0x000007FF ) + (rnd&0x000007FF) );

last_error[3][ch]=last_error[2][ch];
last_error[2][ch]=last_error[1][ch];
last_error[1][ch]=last_error[0][ch];
last_error[0][ch]=quantized-wanted;
quantized=quantized>>11;
if ( quantized > 32767)
return(32767);
else if ( quantized < -32768 )
return(-32768);
else return(quantized);
}
SebastianG
The noise shaping part looks good at the first glance. smile.gif

If you like you could get rid of the last_error arrays when swithing from Direct Form I to Direct Form II for H(z). But this would also require to quantize twice to get the filter's output. The danger of getting overflows in DFII is also a bit higher when working with integers.

Your quantization part seems to introduce a bias towards negative infinity which makes the error samples unnecessarily large. I don't think you need the "-1024" here because the binarry "AND" with 0xFFFFF800 already leads to an average reduction of 1024.

inline int zero11LSBs(int x) { return (x+0x400) & (-0x800); } // correct rounding

So, the +1024 for the correct rounding and your -1024 to offset the dither cancel each other out.


Cheers,
SG
DualIP
The line having the -1024 in it needs some comment:
Basically, it performs this function (in floating point):
floor(input+0.5+TPDF)
where tpdf is trianguler PDF dither in range -1....+1
The 0.5 is needed to compensate for offset in floor function

However, my dither is triangular based in range 0....+2 so to compensate, I have to subtract 1, leading to
floor(input-0.5+TPDFoffset1)

I'll have to look into DirectFormII later on...
SebastianG
QUOTE(DualIP @ May 4 2008, 11:10) *

However, my dither is triangular based in range 0....+2 so to compensate, I have to subtract 1, leading to
floor(input-0.5+TPDFoffset1)

You're right. I was mistakenly thinking about a rectangular dither with a range of 0...+1

Cheers,
SG

DualIP
Most textbooks mention 2LSB peak-peak TPD dither as dither source to fully get rid of quantization errors.
Previous code was based on this 2 LSB peak-peak value:
quantized=0xFFFFF800 & ( wanted - 1024 + ( (rnd>>11)&0x000007FF ) + (rnd&0x000007FF) );


However, with the noise shaping loop added, it seems you can get away with a lower value:
I just tried by halving this TPD white noise to 1 LSB peak-peak, and don't see any distorsion showing up on the spectrum using a two-tone test signal, but overall noise floor is lowered a couple of dBs!
quantized=0xFFFFF800 & ( wanted + ( (rnd>>11)&0x000003FF ) + (rnd&0x000003FF) );

For this noise shaping, what's the optimal internal dither source? There's nothing about it in the topic-start wiki.
SebastianG
QUOTE(DualIP @ Jun 4 2008, 09:57) *

However, with the noise shaping loop added, it seems you can get away with a lower value:
[...]
For this noise shaping, what's the optimal internal dither source? There's nothing about it in the topic-start wiki.

From what I know you still need 2 LSBs peak-to-peak to be able to guarantee that there won't be nasty distortions. My personal favorite dither method is a morphed PDF between rectangular and triangular:
CODE

dither_k = (random()-0.5) + s * (random()-0.5);

with random() returning random numbers between 0 and 1 (rectangular probability density) and 's' being a scalar between 0 (=> rectangular) and 1 (=> triangular). This way it's always at least as good as a rectangular dither (important feature!). I also noticed that when noise shaping is in use it's okay to use lower values for 's' like 0.6 without getting noise modulation. The noise floor wil be 1 dB below of what you'd expect from a full triangular dither. However, I know of no proof for it to work all the time. It just does in the cases I checked.

Cheers,
SG
Nick.C
QUOTE(SebastianG @ Jun 4 2008, 12:50) *
From what I know you still need 2 LSBs peak-to-peak to be able to guarantee that there won't be nasty distortions. My personal favorite dither method is a morphed PDF between rectangular and triangular:
CODE

dither_k = (random()-0.5) + s * (random()-0.5);

with random() returning random numbers between 0 and 1 (rectangular probability density) and 's' being a scalar between 0 (=> rectangular) and 1 (=> triangular). This way it's always at least as good as a rectangular dither (important feature!). I also noticed that when noise shaping is in use it's okay to use lower values for 's' like 0.6 without getting noise modulation. The noise floor wil be 1 dB below of what you'd expect from a full triangular dither. However, I know of no proof for it to work all the time. It just does in the cases I checked.

Cheers,
SG
Interesting, very interesting....
HotshotGG
Well seeing that I am writer and not much of a Mathmatician I did manage to add a few sources in your article in particular the one on SACD dithering. Cheers. wink.gif Excellent article btw. I think there are a few other ones that need to be rewritten in the Signal Processing section and we will be in good shape. wink.gif
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Invision Power Board © 2001-2008 Invision Power Services, Inc.