An experiment to fine-tune the sound of the 12 bar blues by @markknol by adding a low-pass filter to the synth and a delay filter to the loops.
Log in to post a comment.
// Forked from "12 bar blues" by markknol // https://dittytoy.net/ditty/18766aafd1 const tick = synth.def( (phase, env, tick) => 2 * (Math.random() - .5) * Math.exp(-tick * 200) * env.value, {attack: 0.0025, release: 0.01, amp: 4, env: adsr2}); const noise = synth.def( _ => Math.random() * 2 - 1, { amp: 4, env: adsr2 } ); const bluesGuitar= synth.def( class { constructor(options) { this.phase = 0; this.hist0 = 0; this.hist1 = 0; } process(note, env, tick, options) { this.phase += midi_to_hz(note - env.progress * .1) * ditty.dt; let ret = 0; for (let i=1; i<=3; i++) { ret += Math.sign(((this.phase * (2 * i)) % 2) - 1) / (i ** 2); } ret *= Math.exp(-env.progress); // low pass filter, cutoff is based on env.value const alpha = env.value * .12; this.hist0 += alpha * (ret - this.hist0); this.hist1 += alpha * (this.hist0 - this.hist1); return this.hist1; } }, { env: adsr2 } ); const delay = filter.def(class { constructor(options) { this.index = 0; this.length = options.interval * ditty.sampleRate * 60 / ditty.bpm | 0; this.left = new Float32Array(this.length); this.right = new Float32Array(this.length); } process(input, options) { if (input) { const s = options.strength; this.index = (this.index + 1) % this.length; const hist = (this.index + 1) % this.length; this.left [this.index] = (1-s) * input[1] + s * this.right[hist]; this.right[this.index] = (1-s) * input[0] + s * this.left [hist]; return [ this.left[this.index], this.right[this.index] ]; } } }, { interval: 1/3, strength: 0.25 }); const lowpass = filter.def(class { constructor(options) { this.hist0 = [0, 0]; this.hist1 = [0, 0]; } process(input, options) { const alpha = options.cutoff; if (input) { for (let i = 0; i < 2; i++) { this.hist0[i] += alpha * (input[i] - this.hist0[i]); this.hist1[i] += alpha * (this.hist0[i] - this.hist1[i]); } return this.hist1; } } }, {cutoff: 1}); const distortion = filter.def(class { process(input, options) { const amp = options.amp; const cutoff = options.cutoff; if (input) { return [clamp(input[0] * amp, -cutoff, cutoff), clamp(input[1] * amp, -cutoff, cutoff)]; } } }, {cutoff: .7, amp: 1}); const nothing = {}; const progression = [ chord(c3, chords.major), chord(f3, chords.major), chord(c3, chords.major), chord(c3, chords.dom7), chord(f3, chords.major), chord(f3, chords.dom7), chord(c3, chords.major), chord(c3, chords.dom7), chord(g3, chords.major), chord(f3, chords.major), chord(c3, chords.major), chord(g3, chords.dom7), ]; loop(() => { progression.forEach(c => { sleep(playChord(c, 6/8*2)); sleep(playChord(c, 6/8)); }); },{name:'chords', amp: () => clamp01(ditty.time - 8 * 60 / ditty.bpm)}) .connect( delay.create() ); loop(() => { progression.forEach(_ => { sleep(playChord(scale(a3, scales.minor_pentatonic, 3), 6/8*pick(0, 0.5, 1, 2, 4, 8), 6/8, 0.25)); }); },{name:'melody', amp: () => clamp01(ditty.time - 16 * 60 / ditty.bpm) * 1.5}) .connect( delay.create( { interval: 2/3, strength: 0.1 }) ) .connect( distortion.create() ) .connect( delay.create() ) .connect( lowpass.create( { cutoff: .75 }) ); function playChord(c, t = 6/8, interv = 6/8/8, chance = 0.95) { [...c].sort(_ => -0.5 + Math.random()).forEach(n => (Math.random() < chance ? bluesGuitar.play(n, {amp: 0.5 + 0.25 * Math.random()}) : nothing, sleep(interv))); t -= c.length * interv; return t; } function pick(...args) { return args[Math.random() * args.length | 0]; } loop(() => { tick.play(c1); sleep(Math.sqrt(2)); },{name:'tick 1', amp: .25}) .connect( lowpass.create( { cutoff: .2 }) ); loop(() => { tick.play(c1); sleep(1.61803398875); },{name:'tick 2', amp: 1}) .connect( lowpass.create( { cutoff: .1 }) ); loop(() => { noise.play(c1, { env: one, duration: 1e5, amp: () => .5 + .1 * Math.sin(ditty.time)}); sleep(1e5); },{name:'noise', amp: () => .2 * clamp01(ditty.time)}) .connect( lowpass.create( { cutoff: .15 }) );