// Forked from "d-layers" by markknol // https://dittytoy.net/ditty/461bb6b7cf const tri = synth.def( (phase, env, tick, options) => { const v = (phase % 1) * 4; return (v < 2 ? v - 1 : 3 - v) * env.value }, { attack: 0.025, release: 0.5, amp: .8, env: adsr2 }); const noise = synth.def( (phase, env, tick, options) => (Math.random() * 2 - 1) * env.value, { attack: 0.0125, release: 0.15, env: adsr2 }); const kick = synth.def( (phase, env, tick, options) => Math.sin(phase * 2 * Math.PI * Math.exp( - tick)) * env.value, { attack: 0.025, release: 0.15, amp: 1, env: adsr2 }); const delay = filter.def(class { constructor(options) { this.index = 0; this.length = options.interval * ditty.sampleRate * 60 / ditty.bpm | 0; this.left = new Float32Array(this.length); this.right = new Float32Array(this.length); } process(input, options) { if (input) { const s = options.strength; this.index = (this.index + 1) % this.length; const hist = (this.index + 1) % this.length; this.left [this.index] = input[0] + s * this.right[hist]; this.right[this.index] = input[1] + s * this.left [hist]; return [ this.left[this.index], this.right[this.index] ]; } } }, { interval: 1/3, strength: 0.25 }); const lowpass = filter.def(class { constructor(options) { this.hist0 = [0, 0]; this.hist1 = [0, 0]; } process(input, options) { const alpha = options.cutoff; if (input) { for (let i = 0; i < 2; i++) { this.hist0[i] += alpha * (input[i] - this.hist0[i]); this.hist1[i] += alpha * (this.hist0[i] - this.hist1[i]); } return this.hist1; } } }, {cutoff: 1}); loop((i) => { tri.play ([c3,c4,c3,c5,c3,c4,f3,g5, c3,c4,c3,c5,c3,c4,g5,d5 ].ring(i) + (i/32|0)%2*2 - 12, { attack: 0.05 * Math.random(), release: 0.4, pan: 0.5 - Math.random() }); sine.play([c3,c4,c3,c5,c3,c4,f3,g5, c3,c4,c3,c5,c3,c4,g5,d5 ].ring(i) - (i/32|0)%2*3 - 36, { attack: 0.1, release: 0.2, pan: 0.5 - Math.random(), amp: .25 }); sleep(0.5); }, { name: '📢', amp: .8 }) .connect( delay.create( { interval: 1.25, strength: 0.25 }) ) .connect( delay.create( { interval: 2/3, strength: 0.15 }) ) .connect( delay.create( { interval: 1/2, strength: 0.25 }) ) .connect( delay.create( { interval: 1.5, strength: 0.33 }) ); loop( (loopCount) => { 'x---x---x-x-x-xx'.ring(loopCount) == 'x' && kick.play(c3); sleep(.25); }, { name: 'kick', amp: 0.75 }); loop( (loopCount) => { '--x---x---x---xx'.ring(loopCount) == 'x' && noise.play(c3, { amp: 2}); sleep(.5); }, { name: 'snare' }) .connect( lowpass.create( { cutoff: 0.15 } )) .connect( delay.create( { interval: 0.25, strength: 0.15 })); loop( () => { noise.play(c, { amp: 0.02 + 0.01 * Math.random(), pan: Math.sin(ditty.time * 2) }); sleep(0.25); }, { name: 'hi-hat' }) .connect( lowpass.create( { cutoff: .9} )) .connect( delay.create( { interval: 0.25, strength: 0.5 }));