Snare Drum

Realistic snare drum / hand clap with many options.
clap: Snare Drum (variation)
another snare: Snare Drum (variation)

Log in to post a comment.

// srtuss, 2023


input.snareDecay = 10; // min=5,max=30,step=1
input.snareTone = 1.7; // min=.25,max=2,step=.01
input.snareResonance = .7;
input.snareBatterSpeed = 150; // min=5,max=150,step=1
input.snareBatterAmt = .9;
input.snareStereo = .6;
input.snareVelocity = 1; // min=.1,max=1,step=.05
input.snareFlavor = .7; // min=.5,max=2,step=.05
input.snareAttack = 666; // min=100,max=1000,step=1
input.snareSub = .5;

class SVF {
    constructor() {
        this.lp = 0; this.bp = 0; this.hp = 0;
    }
    clock(v, q, k) {
        q = 1-q;
        this.hp = v - this.bp * q - this.lp;
        this.bp += this.hp * k;
        this.lp += this.bp * k;
    }
}

const snare = synth.def(class {
    constructor(opt) {
        this.t = 0;
        this.flt = [new SVF(), new SVF(), new SVF()];
        console.log(opt);
    }
    process(note, env, tick, opt) {
        // a dip in amplitude when the snare is struck
        let batter = Math.min(1, (1-opt.batterAmt) + Math.abs(this.t - 1 / opt.batter) * opt.batter);
        // tone generation using 3 filters
        let tone = opt.tone;
        this.flt[0].clock(Math.random(), .999 * opt.resonance, .03 * tone * opt.flavor);
        this.flt[1].clock(Math.random(), .5 * opt.resonance,   .3 * tone);
        this.flt[2].clock(Math.random()-.5, .9,   .01 * tone);
        // add signals with different decay times
        var v;
        let l = opt.falloff + (1-opt.velocity) * 30;
        v  = this.flt[0].bp * Math.exp(-this.t * l);
        v += this.flt[1].hp * Math.exp(-this.t * 30) * .3;
        v += this.flt[1].bp * Math.exp(-this.t * (l+10));
        v += this.flt[2].lp * Math.exp(-this.t * (l+1)) * 3 * opt.sub;
        // attack phase generation
        v *= Math.min(1, this.t * (opt.velocity + .01) * opt.sattack);
        v *= batter;
        this.t += ditty.dt;
        return v;
    }
}, {
    // replace this section with your parameters of choice
    batter: (_,__) => input.snareBatterSpeed,
    velocity: 1,
    falloff: (_,__) => input.snareDecay,
    batterAmt: (_,__) => input.snareBatterAmt,
    resonance: (_,__) => input.snareResonance,
    flavor: (_,__) => input.snareFlavor,
    sattack: (_,__) => input.snareAttack,
    tone: (_,__) => input.snareTone,
    sub: (_,__) => input.snareSub,
});


ditty.bpm = 120;

if(false) {
    loop( (lc) => {
        sine.play(lc % 4 == 0 ? c5 : c7, {attack:.0001, release:.0001, duration: .1, amp: .1});
        sleep(1);
    }, { name: 'metronome' });
}

var swing = 0.02;
input.pattern = 1; // min=0,max=1,step=1 (complex, simple)
loop( () => {
    var pa = input.pattern ? "9......." :
    //0-------1-------2-------3-------4-------5-------6-------7-------
     '9...1...7...151.9.......7...111.9..1..1.9..14.1.5...1.9.5...9...';
    for(let i = 0; i < pa.length; ++i) {
        if(pa[i] != '.') {
            let velocity = 2 ** (2 * ((pa[i] / 9) - 1));
            snare.play(10, { duration: .5, pan: (x,y) => -input.snareStereo, velocity: (x,y) => velocity * input.snareVelocity });
            snare.play(10, { duration: .5, pan: (x,y) => input.snareStereo, velocity: (x,y) => velocity * input.snareVelocity });
        }
        sleep(i & 2 ? 1/8 - swing : 1/8 + swing);
    }

}, { name: 'snare' });