[chuck-users] dithering with chuck

eduard aylon eduard.aylon at gmail.com
Sun Dec 10 09:36:54 EST 2006


Hello list,

This is probably not a question about chuck, but as I am trying to  
explain how dither works to other people by using chuck I thought I  
might post the question anyway.
Please correct me if I am wrong... In principle dither is used in  
order to make quantization noise not perceivable. So, taking a 16bit  
audio file down by 60dB and then up again by 60dB without applying  
dither will cause quantization errors to be very audible. However  
when applying dither (both when de-amplifying and amplifying)  a hiss  
maybe perceived but the signal should be recovered in a better way,  
or at least the quantization error should be less perceivable.
In order to achieve this, I have implemented the following function  
in chuck (note that at the moment I am not interested in noise  
shaping techniques, but just adding "pure" white noise )

fun void change_gain_with_dither( float dB, string input_filename,  
string output_filename )
{
     16 => int bit_reso;
     1 << (bit_reso-1) => int max;
     .5/max => float noise_floor; // noise level at half LSB
     <<< "noise floor:", noise_floor >>>;
     Math.pow( 10., dB/20.) => float gain_factor;
     <<<"changing gain to file", input_filename>>>;
     <<<"    amount in dB:", dB >>>;
     <<<"    amount linear:", gain_factor >>>;
     <<<"    dither:", "yes">>>;
     <<<"    output file:" , output_filename >>>;
     sndbuf buf => dac;
     buf.read( input_filename );
     impulse p => WvOut audio => blackhole;
     audio.aifFilename( output_filename );
     now => time begin;
     buf.length() +=> begin;
     while( now < begin )
     {
         std.rand2f(-noise_floor, noise_floor ) => float dither;
         (buf.last() + dither )*gain_factor  => p.next;
         1::samp => now;
     }
     audio.closeFile( output_filename );
}

However, this function seems to not give better results than the one  
below, which doesn't take dither into account:

fun void change_gain_without_dither( float dB, string input_filename,  
string output_filename )
{
     Math.pow( 10., dB/20.) => float gain_factor;
     <<<"changing gain to file", input_filename>>>;
     <<<"    amount in dB:", dB >>>;
     <<<"    amount linear:", gain_factor >>>;
     <<<"    dither:", "no">>>;
     <<<"    output file:" , output_filename >>>;
     sndbuf buf => dac;
     buf.read( input_filename );
     impulse p => WvOut audio => blackhole;
     audio.aifFilename( output_filename );
     now => time begin;
     buf.length() +=> begin;
     while( now < begin )
     {
         buf.last()*gain_factor => p.next;
         1::samp => now;
     }
     audio.closeFile( output_filename );
}


So from the next two options:

A) change_gain_without_dither( -60, file1, file2 );
      change_gain_without_dither( 60, file2, file4 );

and

B) change_gain_with_dither( -60, file1, file3 );
      change_gain_with_dither( 60, file3, file5 );

I would have expected B) giving "better" results than A), but in fact  
I obtain even worse results, i.e.: same quantisation error + hiss.

So, in the end, I am pretty sure that my understanding of dither  
might not be the correct one. Could anyone shred some light on this  
subject?

thanks,

eduard



More information about the chuck-users mailing list