ditty.bpm = 130;
const compressor = filter.def(class {
constructor(options) {
this.gain = 1;
}
process(input, options) {
let sigdb = 10 * Math.log10(input[0]**2 + input[1]**2);
let overdb = sigdb - options.threshold;
if(overdb < 0) {
overdb = 0;
}
let target_gaindb = overdb * (1 - options.ratio)/options.ratio;
let target_gain = 10 ** (target_gaindb / 20);
let time = this.gain > target_gain ? options.attack : options.release;
let a0 = clamp01(2.3 * ditty.dt / time); // 'time' to go to within 10% of the final value
this.gain = lerp(this.gain, target_gain, a0);
let gr = 20 * Math.log10(this.gain);
return [input[0] * this.gain, input[1] * this.gain];
}
}, {threshold:-16, ratio:2, attack:0.005, release:0.2});
let sharedCompressor = compressor.createShared();
const kick = synth.def( (phase, env) => (Math.tanh(Math.sin(Math.sqrt(phase)**.1*256+phase))) * env.value *32);
const hh = synth.def(class {
constructor(options) {
this.prev = 0;
}
process(note, env, tick, options) {
let unfilt = Math.random()-.5;
this.prev += (unfilt-this.prev)*.7;
return (this.prev-unfilt) * env.value*8;
}
});
const snare = synth.def((phase, env) => (Math.tanh(Math.sin(30/(phase)-phase*Math.PI)+(Math.random()-.5)*(env.value**2))) * env.value*32 );
const gro = synth.def(class {
constructor(options) {
this.phase = 0;
this.smooth = 0;
}
process(note, env, tick, options) {
this.phase += midi_to_hz(note) * ditty.dt;
let o = this.phase*Math.PI*2;
this.smooth += (options.vale-this.smooth)/800;
return Math.tanh(Math.sin(o+(Math.sin(o*3+Math.sin(o/2))+Math.sin(o*3)/2)*this.smooth)*3) * env.value;
}
}, { xenv: 0.5, amp: 1, attack: 0.01, release: 0.3, vale: 1});
loop( () => {
kick.play(g3, { attack: 0.001, release: 0.3, duration: 0.0 });
sleep(1.5)
kick.play(g3, { attack: 0.001, release: 0.3, duration: 0.0 });
sleep(.5)
kick.play(g3, { attack: 0.001, release: 0.3, duration: 0.0 });
sleep(.75)
kick.play(g3, { attack: 0.001, release: 0.3, duration: 0.0 });
sleep(.75)
kick.play(g3, { attack: 0.001, release: 0.3, duration: 0.0 });
sleep(.5)
}).connect( sharedCompressor );
loop( () => {
sleep(1)
snare.play(a3, { attack: 0., release: 0.2, duration: 0.0 });
sleep(1)
}).connect( sharedCompressor );
loop( () => {
hh.play(0, { attack: 0., release: 0.05, duration: 0.0 });
sleep(.25)
}).connect( sharedCompressor );
let cyr;
loop( () => {
let cyr = gro.play(c3, { attack: 0., release: 0., duration: 8. });
cyr.options.vale = 4;
sleep(2);
cyr.options.vale = 2;
sleep(.5)
cyr.options.vale = 0;
sleep(.5)
cyr.options.vale = 32;
sleep(.5)
cyr.options.vale = 3;
sleep(.5)
cyr.options.note = g3;
cyr.options.vale = 2;
sleep(.5)
cyr.options.vale = 0;
sleep(.5)
cyr.options.vale = 2;
sleep(.5)
cyr.options.vale = 0;
sleep(.5)
cyr.options.note = a3;
for (i=0;i<8;i++) {
cyr.options.vale = (8-i)/2;
sleep(.125/2);
}
for (i=0;i<8;i++) {
cyr.options.vale = (8-i)/2;
sleep(.125/2);
}
cyr.options.note = a2;
cyr.options.vale = 4;
sleep(.5);
cyr.options.note = a1;
cyr.options.vale = 8;
sleep(.5);
}).connect( sharedCompressor );