// Here are some thoughts I have right now regarding DittyToy:
// - I find that debugging can be quite difficult, because there are many cases in which
// no audio is produced, but no error is shown, e.g. incorrect option name, uninitialized member variable.
// - In particular, the error when the filter returns a single value rather than two is quite cryptic:
// Worker error: this._gen(...) is not iterable
// - The strict CPU limitations are frustrating, is there room for optimization?
// - Ctrl+Enter compiles and runs, but is there a shortcut to pause the synth?
// - I don't like the code completion tool, which suggests inappropriate completions most of the time,
// and gets in my way during coding.
// - Sometimes the code compiles but the synths don't start...?
// - Is it possible to create envs manually, to use in the synth definition and/or in the loop()s?
input.cutoff = 0.5; // min=0, max=1, step=0.001
const saw = synth.def( (phase, env) => (phase%1-0.5) * env.value);
const linexp = (x,x0,x1,y0,y1) => y0 * (y1/y0) ** ((x-x0)/(x1-x0));
// Second order lowpass filter without resonance (mono)
const lpf = filter.def(class {
constructor(options) {
this.s0 = 0;
this.s1 = 0;
}
process(input, options) {
this.a0 = clamp01(2*Math.PI * ditty.dt * options.cutoff);
this.s0 += this.a0 * (input[0] - this.s0);
this.s1 += this.a0 * (this.s0 - this.s1);
//return this.s1; // Uncomment this line to get a cryptic error message
return [this.s1, this.s1];
}
}, {cutoff: 5000});
loop(() => {
saw.play(c4);
sleep(1);
}, {name:"saw"})
.connect( lpf.create({cutoff: () => linexp(input.cutoff,0,1,20,20000)}) );