// WIP function synthharmonics(outp, harm, len, nh) { for(var j = 0; j < len; ++j) { outp[j] = 0; } for(var i = 0; i < nh; ++i) { var f = i + 1; var amp = harm[i]; for(var j = 0; j < len; ++j) { var x = j / len; outp[j] += Math.sin(x * f * Math.PI * 2) * amp; } } } function fract(x) { return x - Math.floor(x); } class MorphWave { constructor(len) { this.len = len; this.data = new Float32Array(len); this.nharm = len >> 4; this.update(); } update() { var nh = this.nharm; var harm = new Float32Array(nh); for(var i = 0; i < nh; ++i) { harm[i] = .3 / (1 + i); } for(var i = 0; i < nh; i += 1) { harm[i] *= Math.pow(Math.random(), 2); } synthharmonics(this.data, harm, this.len, nh); } } class Morph { } const syn = synth.def( class { constructor(opt) { this.nwtb = 1024; this.wtbs = [new MorphWave(this.nwtb), new MorphWave(this.nwtb)]; for(var k = 0; k < 2; ++k) { this.wtbs[k].update(); } this.ops = []; var nop = 8; for(var i = 0; i < nop; ++i) { this.ops.push({ t: Math.random(), ff: 1 + Math.random() * .01, p: i / (nop-1)}); } this.morph = 0; this.shimmerc = 0; this.morphdt = .000005; } process(note, env, tick, options) { var suml = 0; var sumr = 0; var dt = midi_to_hz(note) * ditty.dt; dt += Math.sin(tick * 9) * .00002; this.morph += this.morphdt; if(this.morph >= 1) { this.morph -= 1; var t = this.wtbs[0]; this.wtbs[0] = this.wtbs[1]; this.wtbs[1] = t; this.wtbs[1].update(); } var wtb0 = this.wtbs[0].data, wtb1 = this.wtbs[1].data, wtbm = this.morph; if(++this.shimmerc >= 70) { this.shimmerc = 0; for(var i = 0, ni = this.ops.length; i < ni; ++i) { this.ops[i].ff = 1 + Math.random() * .15; } } for(var i = 0, ni = this.ops.length; i < ni; ++i) { var op = this.ops[i]; var idx = Math.floor(op.t * this.nwtb); var opv = wtb0[idx] * (1-wtbm) + wtb1[idx] * wtbm; suml += opv * op.p; sumr += opv * (1 - op.p); op.t += dt * op.ff; while(op.t >= 1) { op.t -= 1; } } return [suml * env.value, sumr * env.value]; } }); loop(() => { var k = [0, 2, -2, -4]; for(var i = 0; i < 3; ++i) { var o = k[i]; syn.play(c2+o, {duration: 16, attack: 5, release: 5}); syn.play(d4+o, {duration: 16, attack: 5, release: 5}); syn.play(c4+o, {duration: 16, attack: 5, release: 5}); syn.play(e4+o, {duration: 16, attack: 5, release: 5}); syn.play(b4+o, {duration: 16, attack: 5, release: 5}); sleep(16); } }, {name: "pad"});