hello world

random

Log in to post a comment.

// athibaul's reverb filter with added modulation
class Delayline { constructor(n) { this.n = n; this.p = 0; this.data = new Float32Array(n); } get end() { return this.data[this.p]; } tap(offset) { var x = this.p + offset; x = ~~x; x %= this.n; return this.data[x]; } sample(offset) { if(offset < 0) offset = 0; var p = offset; var pi = ~~p; return lerp(this.tap(pi), this.tap(pi+1), p-pi); } clock(input) { var end = this.data[this.p]; this.data[this.p] = input; if(++this.p >= this.n) { this.p = 0; } return end; } }  const ISQRT2 = Math.sqrt(0.5); const SQRT2 = Math.sqrt(2); const SQRT8 = Math.sqrt(8); const ISQRT8 = 1/SQRT8;  const fibodelays = [1467,1691,1932,2138,2286,2567,3141,3897]; const fiboshort = [465, 537, 617, 698, 742, 802, 963, 1215]; let meandelay = fibodelays[3] * ditty.dt;
const reverb = filter.def(class { constructor(options) { this.outgain = 0.3; this.predl = [new Delayline(1000), new Delayline(1000)]; this.dls = []; this.s0 = new Float32Array(8); for(let i=0; i<8; i++) { this.dls.push(new Delayline(fibodelays[i])); this.dls[i].i = i; this.s0[i] = 0; } this.a0 = clamp01(2*Math.PI*options.cutoff*ditty.dt);  this.dls_nr = []; for(let i=0; i<4; i++) { this.dls_nr.push(new Delayline(fiboshort[i*2])); } } process(inpt, options) {  let s0 = this.predl[0].clock(inpt[0]), s1 = this.predl[1].clock(inpt[1]); for(let i=0; i<4; i++) { let u0 = 0.6*s0 + 0.8*s1, u1 = 0.8*s0 - 0.6*s1; let u1p = this.dls_nr[i].end; this.dls_nr[i].clock(u1); s0 = u0; s1 = u1p; } let v0 = (s0 + s1); let v1 = (s0 - s1);     let rt60 = options.rt60; let loopgain = 10 ** (-3*meandelay / rt60) * ISQRT8; let higain = 10 ** (-3*meandelay / options.rtHi) * ISQRT8; let mod = 10; let v = this.dls.map( (dl) => dl.sample((1 + Math.sin(ditty.tick * (3 + dl.i * 2))) * mod));   let w = [v[0]+v[4], v[1]+v[5], v[2]+v[6], v[3]+v[7], v[0]-v[4], v[1]-v[5], v[2]-v[6], v[3]-v[7]]; let x = [w[0]+w[2], w[1]+w[3], w[0]-w[2], w[1]-w[3], w[4]+w[6], w[5]+w[7], w[4]-w[6], w[5]-w[7]]; let y = [x[0]+x[1], x[0]-x[1], x[2]+x[3], x[2]-x[3], x[4]+x[5], x[4]-x[5], x[6]+x[7], x[6]-x[7]]; y[0] += v0; y[2] += v1; for(let i=0; i<8; i++) { let hipass = y[i] - this.s0[i]; let lopass = this.s0[i]; this.dls[i].clock(lopass * loopgain + hipass * higain); this.s0[i] += this.a0 * hipass; }  return [lerp(inpt[0], v[0], options.mix), lerp(inpt[1], v[2], options.mix)]; } }, {mix:1, rt60:10, cutoff:20000, rtHi:0.9});


ditty.bpm = 140;

class SVF {
    constructor() {
        this.b = this.l = this.h = 0;
    }
    process(input, f, r) {
        this.h = input - this.b * (1-r) - this.l;
        this.b += this.h * f;
        this.l += this.b * f;
        return this;
    }
}
class SVF2 {
    constructor() {
        this.a = new SVF();
        this.b = new SVF();
    }
    process(input, f, r) {
        return this.b.process(this.a.process(input, f, r).l, f, r).l;
    }
}

input.tune = .73; // min=.5,max=2,step=.01

class Hihat {
    constructor() {
        this.osc = [245, 306, 365, 415, 437, 619];
        this.oscp = [];
        this.osc.forEach(o => this.oscp.push(Math.random()));
        this.bp = new SVF();
        this.hp = new SVF();
    }
    process(f, env, t, o) {
        let v = 0;
        let tun = input.tune * ditty.dt;
        for(let i = 0; i < this.osc.length; ++i) {
            this.oscp[i] += this.osc[i] * tun;
            while(this.oscp[i] >= 1)
                this.oscp[i] -= 1;
            v += this.oscp[i] > 0.5 ? .16 : -.16;
        }
        v = this.bp.process(v, .5, .5).b;
        v += Math.random() * .2;
        v = clamp(v*2, -.2, .2) * env.value;
        v = this.hp.process(v, .5, .0).h;
        return v;
    }
}

let hihat = synth.def(Hihat);

class Bassdrum {
    constructor(opt) {
        this.ph = 0;
        this.flt = [new SVF(), new SVF(), new SVF()];
        this.freq = midi_to_hz(opt.note);
        this.body = 0;
    }
    process(note, env, tick, opt) {
        let tattack = .1;
        let fattack = .1;
        let attack = clamp01((tattack - tick) / tattack);
        this.body = Math.sin((this.ph+this.body*-0.0) * Math.PI * 2);
        let v = this.body;
        this.ph += ditty.dt * (this.freq + attack * 100);
        //v *= (.5 + Math.random() * .5);
        //v += Math.random();
        let attack2 = clamp01((fattack - tick) / fattack) * opt.velocity;
        v = this.flt[0].process(v, .5, attack2 * .2 + .025).l;
        v += (Math.random()-.5) * attack2 * .1;
        v = clampWave(v * clamp(env.value, 0., 1) * 1.2);
        this.t += ditty.dt;
        return v * opt.velocity;
    }
}

const kick = synth.def(Bassdrum, {
    attack: 0.001, decay: .1, sustain: .2, release: 0.1, velocity: 1, duration: .5
});

loop( (lc) => {
    kick.play(c2);
    sleep(1);
    kick.play(c2);
    sleep(1);
    kick.play(c2);
    sleep(1);
    if(lc % 2) {
        kick.play(c2);
        sleep(.5);
        kick.play(c2);
        sleep(.5);
    }
    else {
        kick.play(c2);
        sleep(1);
    }

}, { name: 'k' });

loop( () => {
    hihat.play(f4, { attack: 0.001, release: 0.05 });
    sleep(.25);
    hihat.play(f4, { attack: 0.001, release: 0.02 });
    sleep(.25);
    hihat.play(f4, { attack: 0.001, release: .1, duration: .1 });
    sleep(.25);
    hihat.play(f4, { attack: 0.001, release: 0.02 });
    sleep(.25);

}, { name: 'h' });

const wrap01 = p => p < 0 ? p % 1 + 1 : p % 1;
function softclip(x) {
    return x<-1?-1:x>1?1:1.5*(1-x*x/3)*x;
}
function varsaw(p, formant) {
    let x = wrap01(p);
    return (x - 0.5) * softclip(formant*x*(1-x));
}
let bob = synth.def((p,e,t,o) => varsaw(p + o.phase, ditty.sampleRate / midi_to_hz(o.note) * (o.c * Math.exp(-t * 20) + .01)) * e.value);
let saw = synth.def((p,e,t,o) => varsaw(p + o.phase, ditty.sampleRate / midi_to_hz(o.note)) * e.value);

function softclip(x) {
    return x<-1?-1:x>1?1:1.5*(1-x*x/3)*x;
}

class Unison {
    constructor(opt) {
        this.tupd = 0;
        this.semitone = .2;
        let n = 16;
        this.phas = new Float32Array(n);
        this.mul = [new Float32Array(n), new Float32Array(n)];
        this.dt = new Float32Array(n);
        let a = 2 ** (n * -.02 - 1);
        for(let i = 0; i < n; ++i) {
            this.phas[i] = Math.random();
            let t = i / (n-1);
            let x = 1 / Math.sqrt(1+2*(t*t-t));
            this.mul[0][i] = t * x * a;
            this.mul[1][i] = (1-t) * x * a;
        }
    }
    process(note, env, tick, opt) {
        if(this.tupd <= 0) {
             this.tupd += 1;
             this.freq = midi_to_hz(note) * ditty.dt;
             for(let i = 0; i < this.phas.length; ++i) {
                 let mul = 2 ** (Math.sin(ditty.tick*4+i)*this.semitone / 12);
                 this.dt[i] = this.freq * mul;
             }
        }
        this.tupd -= ditty.dt * 60;
        
        let vl = 0, vr = 0;
        for(let i = 0; i < this.phas.length; ++i) {
            let x = this.phas[i];
            let v = (x - .5) * softclip(1 / this.dt[i] * x * (1-x));
            //v += Math.sin(v * Math.PI * (4 - tick) * 8) * .1;
            vl += v * this.mul[0][i];
            vr += v * this.mul[1][i];
            this.phas[i] = (this.phas[i] + this.dt[i]) % 1;
        }
        return [vl * env.value, vr * env.value];
    }
};

class Synth {
    constructor(opt) {
        this.osc = new Unison(opt);
        this.svf = [new SVF2(), new SVF2()]
    }
    process(note, env, tick, opt) {
        let s = this.osc.process(note, env, tick, opt);
        s[0] = this.svf[0].process(s[0], .7 * Math.exp(-tick * 4) + .01, 0);
        s[1] = this.svf[1].process(s[1], .7 * Math.exp(-tick * 4) + .01, 0);
        return s;
    }
}

let bass = synth.def(Unison);
let lead = synth.def(Synth);


loop((lc) => {
    let bar = [a0,a0,a0,a0,a0,a0,a0,b0,c1,c1,c1,c1,g0,g0,g0,g0];
    let pat = 0xA4;
    let n = bar[(lc>>1)&15] + 12-4 + 12 * (1&(pat>>(lc&7)));
    bob.play(n, {phase: Math.random(), duration: .1 + Math.random() * .1, release: .01, c: Math.sin(lc*.1) * .4 + .5, pan: -1});
    bob.play(n, {phase: Math.random(), duration: .1 + Math.random() * .1, release: .01, c: Math.sin(lc*.1) * .4 + .5, pan: 1});
    sine.play(n, { duration: .2, release: .01, amp: .5});
    sleep(.25);
}, {amp: .8});

loop( (lc) => {
    let bar = [a0,a0,a0,a0,a0,a0,a0,b0,c1,c1,c1,c1,g0,g0,g0,g0];
    sleep(.5);
    let n = bar[(lc*2)&15]+24-4;

    bass.play(n, { attack: .01, amp: 1, duration: .2, release: .1 });

    sleep(.5);
}, { name: 'multi2', amp: 1.5 }).connect(reverb.create({mix: .1}));

loop( (lc) => {
    const seq1 = {
        x:[.5,,1,.5,1.5,.5,.5,.25,.75,.5,.75,.75,.5,.5,,1,.5,1.5,.5,.5,.25,.75,.5,.25,.25,.5,.5,.5],
        d:[.281,.073,.865,.271,.354,.219,.219,.281,.406,.24,.531,.354,.354,.281,.073,.865,.271,.354,.219,.219,.281,.406,.24,.354,.354,.354,.354,.354],
        v:[.76,.67,.84,.72,.79,.8,.75,.72,.76,.76,.84,.84,.84,.76,.67,.84,.72,.79,.8,.75,.72,.76,.76,.84,.84,.84,.84,.84],
        tp:-30-4,
        p:"jnomjjhjhfcagjnomjjhjhfcefcg",
    };
    const seq2 = {
        x:[.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.135,.115,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.25,.135,.115,.25,.25],
        d:[.115,.115,.115,.115,.115,.115,.115,.115,.115,.115,.115,.115,.115,.115,.115,.115,.115,.177,.115,.177,.115,.177,.115,.177,.219,.177,.219,.177,.115,.073,.073,.115,.177,.115,.115,.115,.115,.115,.115,.115,.115,.115,.115,.115,.115,.115,.115,.115,.115,.115,.177,.115,.177,.115,.177,.115,.177,.219,.177,.219,.177,.115,.073,.073,.115,.177],
        v:[.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84,.84],
        tp:-30-4,
        p:"jcochcjcgchcafchjfofhfjffjhjjmmfoocochcjcgchcmecojfofhfjffjhjjmmfo",
    };
    const seq = [seq1, seq1, seq2, seq2][lc % 4];
    for (let i=0; i < seq.p.length; i++) {
        let n = seq.p.charCodeAt(i)+seq.tp;
        lead.play(n, { attack: .01, duration: seq.d[i], release: .1 });
        sleep(seq.x[i]||0);
    }
}, { name: 'multi' }).connect(reverb.create({mix: .2 }));