Un synth monofonico suona una nota per volta. Per suonare accordi serve la polifonia: ogni nota è una "voce" indipendente, con il suo oscillatore e il suo inviluppo.
const voci = new Map();
function noteOn(midi) {
const freq = 440 * Math.pow(2, (midi - 69) / 12); // MIDI -> Hz
const osc = ctx.createOscillator();
const gain = ctx.createGain();
osc.frequency.value = freq;
gain.gain.setValueAtTime(0, ctx.currentTime);
gain.gain.linearRampToValueAtTime(0.3, ctx.currentTime + 0.02);
osc.connect(gain).connect(ctx.destination);
osc.start();
voci.set(midi, { osc, gain }); // ricorda la voce per spegnerla
}
function noteOff(midi) {
const v = voci.get(midi);
if (!v) return;
v.gain.gain.linearRampToValueAtTime(0, ctx.currentTime + 0.1);
v.osc.stop(ctx.currentTime + 0.1);
voci.delete(midi);
}
Il cuore è la gestione delle voci: una Map che associa ogni nota premuta alla sua coppia oscillatore/gain, così a noteOff sai quale spegnere. La formula 440 * 2^((midi-69)/12) converte il numero di nota MIDI in frequenza.
Collega tutto alla Web MIDI API e hai un synth polifonico suonabile con una tastiera vera. Da qui aggiungi filtri, detune, più oscillatori per voce: la strada verso un vero strumento software.