What do fractals sound like?

Bad

Log in to post a comment.

ditty.bpm = 142;

const osc = synth.def( (phase, env, tick, options) => ((phase%2. - 1.) * Math.sin(phase * 2 * Math.PI)) * env.value );


// Reverb by srtuss
class Delayline {
    constructor(n) {
        this.n = ~~n;
        this.p = 0;
        this.lastOut = 0;
        this.data = new Float32Array(n);
    }
    clock(input) {
        this.lastOut = this.data[this.p];
        this.data[this.p] = input;
        if(++this.p >= this.n) {
            this.p = 0;
        }
    }
    tap(offset) {
        var x = this.p - offset - 1;
        x %= this.n;
        if(x < 0) {
            x += this.n;
        }
        return this.data[x];
    }
}

function allpass(delayline, x, k) {
    var delayin = x - delayline.lastOut * k;
    var y = delayline.lastOut + k * delayin;
    delayline.clock(delayin);
    return y;
}

const reverb = filter.def(class {
    constructor(options) {
        this.lastReturn = 0;
        this.krt = 0.7;
        this.delaylines = [];
        // Create several delay lines with random lengths
        for(var i = 0; i < 12; ++i) {
            this.delaylines.push(new Delayline(10 + Math.floor(Math.random() * 5000)));
        }
    }
    process(input, options) {
        var inv = input[0] + input[1];
        var v = this.lastReturn;
        // Let the signal pass through the loop of delay lines. Inject input signal at multiple locations.
        v = allpass(this.delaylines[0], v + inv, .5);
        v = allpass(this.delaylines[1], v, .5);
        this.delaylines[2].clock(v);
        v = this.delaylines[2].lastOut * this.krt;
        v = allpass(this.delaylines[3], v + inv, .5);
        v = allpass(this.delaylines[4], v, .5);
        this.delaylines[5].clock(v);
        v = this.delaylines[5].lastOut * this.krt;
        v = allpass(this.delaylines[6], v + inv, .5);
        v = allpass(this.delaylines[7], v, .5);
        this.delaylines[8].clock(v);
        v = this.delaylines[8].lastOut * this.krt;
        v = allpass(this.delaylines[9], v + inv, .5);
        v = allpass(this.delaylines[10], v, .5);
        this.delaylines[11].clock(v);
        v = this.delaylines[11].lastOut * this.krt;
        this.lastReturn = v;
        // Tap the delay lines at randomized locations and accumulate the output signal.
        var ret = [0, 0];
        ret[0] += this.delaylines[2].tap(111);
        ret[1] += this.delaylines[2].tap(2250);
        ret[0] += this.delaylines[5].tap(311);
        ret[1] += this.delaylines[5].tap(1150);
        ret[0] += this.delaylines[8].tap(511);
        ret[1] += this.delaylines[8].tap(50);
        ret[0] += this.delaylines[11].tap(4411);
        ret[1] += this.delaylines[11].tap(540);
        // Mix wet + dry signal.
        ret[0] = ret[0] * .2 + input[0];
        ret[1] = ret[1] * .2 + input[1];
        // // Slight stereo widening:
        var m = (ret[0] + ret[1]) * .5;
        var s = (ret[1] - ret[0]) * .5;
        ret[0] = m + s * 1.5;
        ret[1] = m - s * 1.5;
        return ret;
    }
});


var x = 0.5;
var y = 0.5;

loop( (loopCount) => {

    var r = Math.random();
    if(r<0.33){
        x = x*0.5;
        y = y*0.5;
    }
    else if(r<0.66){
        x = (x+1)*0.5;
        y = y*0.5;
    }
    else{
        x = y*0.5;
        y = (x+1)*0.5;
    }
    
    debug.log  ("x", x);
    debug.log  ("y", y);
    
    osc.play(48 + x*48, { attack: 0.01, release: 0.25,  duration: 0.1, pan: x*2. - 1., amp: 0.88 });
    sleep(0.25 + y);

}, { name: 'Sierpinski' }).connect(reverb.create());