2008/5/18 Atte André Jensen <atte.jensen@gmail.com>:
Hi

Hey, Atte!
 

I'd like to resample a 44100 signal to something like 10K *and* hear the alias noise. Also I'd like to resample to lower bitdepth, something like 8 or 6 bit.

Cool, me too. Morning coffee is a bit late today but it's a Sunday and there's a nice ChucK puzzle to go with it. Oh, and it's nice coffee :¬)
 

1) How it that most efficiently done with chuck?

Well, quantising in time (sample rate) is without any doubt done most easily by writing the .last() of some signal to the .next of a Step at the required period.

Quantising in amplitude (bit depth) means rounding. I think my proposal below might be quite efficient but I'm not 100% sure there. It does work fine though and Std has several other rounding schemes you may wish to try for CPU performance and/or sound quality.

Here you go; This example should be quite clear and suitable for extending for your own purposes, I think, but if I'm wrong please do shout.
=============================
//replace with more interesting signal.
SinOsc my_signal => blackhole;

Step resampled => dac;

resample();
//remove shred to quit....


fun void resample()
    {
    //8 KHz
    ms / 8 => dur re_samp_rate;
   
    //set bits here
    8 => int bits;
   
    //calculate the maximum integer value of the signal's amplitude at this bitdepth
    Math.pow(2, bits) * .5 => float scale;
    //division is expensive and we only need to do it once
    1/scale => float downscale;
   
    while(true)
        {
        //digital clipping
        if (my_signal.last() > 1) 1 => resampled.next;
        else if (my_signal.last() < -1) -1 => resampled.next;
       
        else
            {
            //cast to int for cheep&cheerful rounding
            //then multiply back into the range
            //write result to output
            downscale * ( (my_signal.last() * scale) $ int) => resampled.next;
           
            }
       
        //samplerate is implicid in controll-rate
        re_samp_rate => now;
        }
    }
===================

 

2) I event thought it might be possible for me to implement this as a real UGen. My plan would be to start from one of the simple UGens (gain), and expand/modify from there, but before even looking into the chuck source, is there any documentation about doing this? Should I expect this to be more effective in implenenting in chuck-code, and if so about how much? Also. supposed I actually succed in making something that works, could it be included in future chuck-releases?

Me too!

I'd also like the following to work but it seems like I can extend Step but the result will -for some strange reason- not be a Ugen. I'm not the greatest OOP wizard but I really feel that if I extend  Ugen the result should be a Ugen as well. Right now we can extend it but not actually do anything with the result.

========================
//example code, doesn't actually work

//this is the offending line
LowRezNoise n => dac;

minute => now;


class LowRezNoise extends Step
    {
   
    ms => dur rate;
   
    spork ~ fakeTick();
   
    fun void freq( float input)
        {
        second / input => rate;
        }
       
    fun void fakeTick()
        {
       
        while(1)
            {
            Std.rand2f(-1,1) => this.next;
           
            rate => now;
            }
        }
   
    }
====================

Hope that helps?

Yours,
Kas.