// dither.ck
// demo of dithering
//
// can use any UGen as source in play_with_dither()
// qbits : number of bits to quantize to
// do_dither : whether to dither
//
// gewang
// patch
Impulse imp => dac;
// sine wave generator
SinOsc s => blackhole;
220 => s.freq;
// go
play_with_dither( s, 2::second, 6, false );
play_with_dither( s, 2::second, 6, true );
.5::second => now;
play_with_dither( s, 2::second, 5, false );
play_with_dither( s, 2::second, 5, true );
.5::second => now;
play_with_dither( s, 2::second, 4, false );
play_with_dither( s, 2::second, 4, true );
.5::second => now;
// dither
fun void play_with_dither( UGen src, dur T, int qbits, int do_dither )
{
// sanity check
if( qbits <= 0 || qbits > 24 )
{
<<< "quantization bits out of range (1-24)", "" >>>;
return;
}
// loop
float sample;
int quantized;
(1 << 24) => int max;
while( T > 0::second )
{
// get the last sample
src.last() => sample;
// quantize it
if( do_dither ) // dither
((sample + Math.random2f(0,Math.pow(2,-qbits))) * max) $ int => quantized;
else // no dither
(sample * max) $ int => quantized;
// throw away extra resolution
quantized >> (24-qbits) << (24-qbits) => quantized;
// cast it back for playback
(quantized $ float) / max => imp.next;
// advance time
1::samp => now;
// decrement
1::samp -=> T;
}
}