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(), }); } }