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);