// https://www.youtube.com/watch?v=lQ6jZgMaZk4 // // the boing is roughly a sawtooth with a root frequency of 96Hz, through a band-pass filter // the center frequency of the filter sits at 1.2kHz for 90ms, then within 90ms sweeps to 2.9kHz were it stays until the end of the sound const poingOsc = synth.def(class { constructor(opt) { this.p = 0; // crude state variable filter, 12dB per octave this.flt = {lp: 0, bp: 0, hp: 0}; this.t = 0; this.svf = (s, inpt, kf, kq) => { var lp, hp, bp; lp = s.lp + kf * s.bp; hp = inpt - lp - kq * s.bp; bp = s.bp + kf * hp; s.lp = lp; s.hp = hp; s.bp = bp; }; } process(note, env, tick, opt) { // create a sawtooth mixed with a slight square timbre, at a fixed frequency var v = (this.p % 1 + (this.p % 1 < .33 ? .1 : -.1) - .5) * env.value; this.p += 96 * ditty.dt; // add a white noise burst at the beginning v += (Math.random() - .5) * Math.exp(-this.t * 60) * .3; // feed it through the bandpass filter and sweep the filter's cutoff frequency this.svf(this.flt, v, lerp(.169, .41, clamp01((this.t - .09) / .09) ** 2), .08); this.t += ditty.dt; // mix the filter output and saturate it sligthly return Math.sin((this.flt.bp + this.flt.lp * .5 + this.flt.hp * .1) * 4 * env.value); } }, {attack: 0, decay: .8, sustain: .2, release: 0.01, duration: .372}); loop( () => { poingOsc.play(c5); sleep(1); }, { name: 'my first loop' });