Defining a synth which generates the "filtered sawtooth" sound, characteristic of analog synths
Log in to post a comment.
input.cutoff=0.5; // min=0, max=1, step=0.001
ditty.bpm = 60; // 1 tick = 1 second
const smoothstep = (a,b,x) => { x = clamp01((x-a)/(b-a)); return x*x*(3-2*x); };
const linexp = (x,x0,x1,y0,y1) => y0 * (y1/y0) ** ((x-x0)/(x1-x0));
const osc = synth.def(
class {
constructor(options) {
this.phase = Math.random();
//this.ampHz = linexp(Math.random(), 0, 1, 0.1, 2.0);
//this.ampPhase = Math.random();
}
process(note, env, tick, options) {
let freq = midi_to_hz(note);
// Periodic amplitude variation (tremolo)
let amp = 1 + 0.5*Math.sin(2*Math.PI * (tick*options.ampHz + options.ampPhase));
// Also affect the cutoff
let cfreq = linexp(input.cutoff * amp**0.5, 0,1, 300, 20000);
let w = clamp01(freq/cfreq) * 0.5;
this.phase = (this.phase + freq * ditty.dt) % 1;
let x = this.phase;
let sig = lerp(2*x, 2*(x-1), smoothstep(0.5-w,0.5+w,x));
return sig * env.value * amp;
}
}, { xenv: 0.5, amp: 1, attack: 0.01, release: 0.3 }
);
// Cmin9 chord
chord = [36,48,55, 58,62,63,67];
for(let j=0; j<7; j++) {
let freq = midi_to_hz(chord[j]);
for (let i=0; i<1; i++) { // Create a "supersaw" sound using several synths if your computer can handle it
osc.play(chord[j]+(Math.random()-0.5)*0.05, // slight detune
{
attack: 5,
duration: 60,
release: 10,
amp: 0.2 * (440/freq)**0.5, // higher amplitude for low notes
ampHz: 0.2 * (1.2)**j, // higher notes have faster tremolo
ampPhase: Math.random(),
});
}
}