Shared compressor test

bass, synth + compressor

Log in to post a comment.

const compressor = filter.def(class {
    constructor(options) {
        this.gain = 1;
    }

    process(input, options) {
        const sigPower = input[0] ** 2 + input[1] ** 2;
        
        if (sigPower === 0) return input;

        const sigdb = 10 * Math.log10(sigPower); // Signal in decibels
        const overdb = Math.max(sigdb - options.threshold, 0); 

        debug.probe("overdb", overdb, 10, 2);

        const target_gaindb = overdb * (1 - options.ratio) / options.ratio;
        const target_gain = 10 ** (target_gaindb / 20); 

        const time = this.gain > target_gain ? options.attack : options.release;
        const a0 = Math.min(1, 2.3 * ditty.dt / time); 

        this.gain += (target_gain - this.gain) * a0;

        debug.probe("gain reduction", 20 * Math.log10(this.gain), 10, 2);

        return [input[0] * this.gain, input[1] * this.gain];
    }
}, { threshold: -1, ratio: 8, attack: 0.5, release: 0.2 });

let comp1 = compressor.createShared({ ratio: 4, attack: 0.008, release: 0.7, threshold: -12 });

ditty.bpm = 96;

const linexp = (x, x0, x1, y0, y1) => y0 * (y1 / y0) ** ((x - x0) / (x1 - x0));
const linlin = (x, x0, x1, y0, y1) => y0 + (y1 - y0) * Math.min(1, Math.max(0, (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) => Math.atan(25 * (Math.abs(phase % 1 - 0.5) - 0.25)) * env.value);

const rhythm = [
       16, 32, 16, 8, 8, 8, 8, 4, 8, 8, 4, 12, 14, 16, 16, 16, 16, 16
];

loop((i) => {
    sine.play((tick) => linlin(tick, 0, 0.2, a1, f1), { env: adsr, attack: 0.01, release: 0.2, amp: 0.8 });
    
    tri.play((tick) => linlin(tick, 0, 0.1, e3, f1), { env: adsr, attack: 0.005, release: 0.1, amp: 0.6 });
    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) => sin2p(phase + 0.5 * sin2p(phase) * env.value) * env.value);

const bass808 = synth.def((phase, env) => {
    const vibratoRate = 1; 
    const vibratoDepth = 0.001; 

    const baseFreq = 5 * Math.pow(0.5, phase); 
    
    const vibratoFreq = baseFreq + vibratoDepth * Math.sin(2 * Math.PI * vibratoRate * phase); 

    const wave = Math.sin(2 * Math.PI * vibratoFreq * phase); 

    const glide = Math.exp(-phase * 0.1); 

    return wave * env.value * glide; 
});

// 808 Kick Sound: Low frequency sine wave with a punchy attack and fast decay (unchanged)
const kick808 = synth.def((phase, env) => {
    const freq = 25 * Math.pow(2, phase); // Low frequency for kick
    const wave = Math.sin(2 * Math.PI * freq * phase); // Sine wave
    const envValue = env.value * (1 - Math.pow(phase, 2)); // Exponential decay for punch
    return wave * envValue;
});

const basenotes = [a2, b2, c3, d3, e3]; 

const kickRhythm = [16, 32, 16, 8, 8, 8, 8, 4]; 
const bassRhythm = [8, 16, 8, 8, 16, 4, 8, 8]; 

// Initialize basenote and chord
let basenote = basenotes[0];
let currentChord = chords.major7; 
let offset = 1;

loop((i) => {
    if (i % 4 === 0) {
        kick808.play({ amp: 1.0, attack: 0.001, release: 0.2 });
    }

    if ( i % 4 === 0) {
        bass808.play(basenote - 16, { amp: 1, attack: 0.1, sustain: 0.25, release: 4, pan: 0.25});
    }

    if (i % 16 === 0) {
        let idx;
        do {
            idx = Math.floor(basenotes.length * Math.random() / 1);
        } while (basenote === basenotes[idx]);

        basenote = basenotes[idx];
        currentChord = chords.major7; 
        offset = [1,2,3,4,5,6,7,8].choose();
    }

    // Play a synth bass with current chord progression
    fmsynth.play(basenote - 16, { amp: 0.1, release: 0.5, pan: 1 });
    fmsynth.play(basenote + currentChord.ring(i), { amp: 0.1, attack: 0.001, release: 1, pan: 0.5 });

    sleep(0.25);
}, { name: "Test" }).connect(comp1);