[chuck-users] DelayC (a delay class with cubic interpolation)

Casper Schipper casper.schipper at gmail.com
Wed Oct 19 07:55:48 EDT 2011


Hi everybody,

because I noticed that the DelayA ugen is not interpolating very smoothly (I find its quality to be much worse than DelayL actually, for modulated delay times),
I made a DelayC class that uses cubic interpolation (with some critical bug fixing help by Kassen !).
It is not very efficient by any standard, but the quality of interpolation is really good, much better than DelayL.
My aim is to turn it into a real uGen, if anybody can help with that, would be great !

Best,
Casper

// Schipper, okt. 2011
class DelayC
{
    Step n; // Output generator
        
    UGen @ input; // nullpointer for input ugen
    
    1024 => int delaySize; // delaySize
    float data[delaySize]; // memory for delayline
    
    int wPos; // writing position in the delayline
    float delay; // delaytime in samples (float)
    
    float L1,L0,H0,H1; // the values used to make the spline interpolation.
    float frac;
    int index;         // position in the buffer
    
    UGen @ delaytime;
    
    spork ~delayShred();
    
    fun void delayShred() 
    {
        while(1) {    
            input.last() => data[wPos]; // writing samples
            clipf(delaytime.last(),2,delaySize-2) => delay; // clipped delaytime (minimum is 2 samples,maximum is delaySize-2)
            interp(wPos-delay) => n.next;
            (wPos + 1) % delaySize => wPos;     // moving writehead to next sample
            samp => now;
        }
    }
    
    // function to make buffer circular
    fun int wrap(int x) {
        if (x < 0) return x + delaySize;
        return x % delaySize;
    }
    
    // three function to connect the delay to other ugens
    fun void connectInput(UGen ugen) {
        ugen @=> input;
    }
    
    fun void connectDelayTime(UGen ugen) {
        ugen @=> delaytime;
    }
    
    fun void connectOutput(UGen ugen) {
        n => ugen;
    }
    
    // sets the maxsize of the delayline     
    fun void setsize(dur size) {     
        (size / samp) $ int => delaySize => data.size;
    }
    
    // simple clipping function
    fun float clipf(float x,float min,float max) 
    {
        if (x < min) return min;
        else if (x > max) return max;
        return x;
    }
    
    // 3rd order spline interpolation based on code from http://www.musicdsp.org/showArchiveComment.php?ArchiveID=62
    fun float interp(float x) {
        Math.floor(x) $ int => index; // finding position in buffer
        x - index => frac; // calc remainder

        // reading 4 adjecent samples
        data[wrap(index-2)] => L1;
        data[wrap(index-1)] => L0;
        data[wrap(index)] => H0;
        data[wrap(index+1)] => H1;
        
        // interp formula
        return L0 + .5*
        frac*(H0-L1+
        frac*(H0 + L0*(-2) + L1 +
        frac*((H0 - L0)*9 + (L1 - H1)*3 +
        frac*((L0 - H0)*15 + (H1 - L1)*5 +
        frac*((H0 - L0)*6 + (L1 - H1)*2 )))));        
    }
}
   
//test code    
DelayC delay;
    
delay.setsize(44100::samp);
    
SinOsc lfo => Gain mod => blackhole; lfo.gain(20000); lfo.freq(.29);
Step offset => mod; 22050 => offset.next;
    
Noise testnoise => BPF f => blackhole;
440 => f.freq;1 => f.Q;
    
delay.connectInput(f);
delay.connectOutput(dac);
delay.connectDelayTime(mod);

hour => now;





More information about the chuck-users mailing list