Testing the new "shared filters" feature - a compressor!
Log in to post a comment.
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;
}
debug.probe("overdb", overdb, 10, 2);
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);
debug.probe("gain reduction", gr, 10, 2);
return [input[0] * this.gain, input[1] * this.gain];
}
}, {threshold:-18, ratio:2, attack:0.005, release:0.2});
let comp1 = compressor.createShared({ratio:4, attack:0.008, release:0.7, threshold:-12});
ditty.bpm = 120;
/*
loop( (i) => {
sine.play(c4, {env:adsr, attack:0.001, release:0.01, duration:1});
sleep(1);
sine.play(c4, {env:one, attack:0.001, release:0.01, duration:1, amp:0.1});
sleep(1);
}).connect(compressor.create({attack:0.01, release:0.2}));
*/
const linexp = (x,x0,x1,y0,y1) => y0 * (y1/y0) ** ((x-x0)/(x1-x0));
const linlin = (x,x0,x1,y0,y1) => y0 + (y1 - y0) * clamp01((x-x0)/(x1-x0));
const tri = synth.def((phase, env) => 1.22*(4.*Math.abs(phase % 1 - 0.5) - 1.) * env.value);
const dist = synth.def((phase, env, tick, options) => Math.atan(25*(Math.abs(phase % 1 - 0.5) - 0.25) * env.value));
let rhythm = [16,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.5,0.5,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.5,0.5,
];
loop( (i) => {
// click
//sine.play((tick) => linlin(tick, 0, 0.02, 127, 0), {attack:0.0005, release:0.05, amp:0.1});
// boom
sine.play(
(tick) => linlin(tick, 0, 0.2, a1, f1),
//{env: adsr2, attack:0.01, decay:0.1, decay_level:0.1, sustain:0.15, sustain_level:0.5, release:0.2, amp:2}
{env: adsr, attack:0.01, release:0.2, amp:0.8}
);
// low thump
tri.play(
(tick) => linlin(tick, 0, 0.1, e3, f1),
{env: adsr, attack:0.005, release:0.1, amp:0.6}
);
// high tump
tri.play(
(tick) => linlin(tick, 0, 0.03, a5, a3),
{env: adsr, attack:0.005, release:0.03, amp:0.1}
);
sleep(rhythm.ring(i));
}, {name:"kick"})
.connect(comp1);
const sin2p = (x) => Math.sin(2*Math.PI*x);
const fmsynth = synth.def( (phase, env, tick) => sin2p(phase + 0.5*sin2p(phase)* env.value) * env.value);
const basenotes = [c3,d3,e3,f3,g3,a3];
const M7 = chords.major7, M6 = chords['6'], m7 = chords.m7;
const myChords = [[M7, M6], [m7], [m7], [M7, M6], [M6], [m7]];
let basenote = basenotes[0];
let currentChord = myChords[0].choose();
let offset = 1;
loop( (i) => {
if(i%16 == 0) {
//basenote = c3 + Math.floor(12 * Math.random());
//basenote = basenotes.ring(Math.floor(i/16));
let idx = 0;
do {
idx = Math.floor(basenotes.length * Math.random());
} while (basenote == basenotes[idx]);
basenote = basenotes[idx];
//currentChord = myChords.ring(Math.floor(i/16));
currentChord = myChords[idx].choose();
offset = [1,3].choose();
}
fmsynth.play(basenote - 12, {amp:0.1, release:0.5, pan:2*Math.random()-1}); // spacy bass
fmsynth.play(basenote + currentChord.ring(i+offset), {amp:0.1, attack:0.001, release:1, pan:Math.random()-0.5}); // arpeggios
sleep(0.25);
}, {name:"synth+bass"})
.connect(comp1);
const leadsynth = synth.def(
(phase, env, tick, options) => sin2p(clamp01((phase%1) * (options.formant + options.dformant*sin2p(options.formhz*tick_to_second(tick))))) * env.value,
{attack:0.1, release:0.5, duration:1, amp:0.2, formant:4, dformant:0.6, formhz:5}
);
const penta = [-100, -100, c4, d4, e4, g4, a4];
loop( (i) => {
let note = penta.choose();
leadsynth.play(note, {formant: 3 + 3*Math.random()});
leadsynth.play(note-12.03, {formant: 6, amp:0.1, pan:Math.random()-0.5});
sleep(1);
leadsynth.play(note-0.05, {amp:0.05, release:2, formant:3, dformant:0.3, formhz:3, pan:-0.5});
leadsynth.play(note+0.05, {amp:0.05, release:2, formant:2.8, dformant:0.3, formhz:2.62, pan:0.5});
sleep(3);
}, {name:"lead"})
.connect(comp1);