JMM’s notes on

Web Audio API

Oh cool, I don’t have to use Csound anymore.

Audio scheduling

These are basically my notes of Chris Wilson’s excellent web.dev article on audio scheduling (also see his demo metronome). I asked Kagi’s FastGPT to make a simple periodic beep, but it used setInterval, which you don’t want to do.

What you do want to do is have a periodic setTimeout that schedules upcoming events with overlaps. Like, make a setTimeout call for 25ms, but have it schedule sounds up to the next 100ms.

In the article, there are 3 different functions. One that’s called by setInterval, one that schedules the next note, and one that calculates the time of the next note. They all work by modifying global variables. I actually think you could use a generator here (and it’s one of the few places I’ve ever actually used a generator). Something like:

function* noteGenerator(start, scheduleahead) {
    const { audioCtx, finish } = getAudioCtx();
    const notelength = 0.05;
    var nextnotetime = start;
    var currentbeat = 0;
    while (true) {
	let addednotes = 0;
	while (nextnotetime < audioCtx.currentTime + scheduleahead) {
	    // Add a note
	    const oscillatorNode = new OscillatorNode(audioCtx);
	    oscillatorNode.connect(finish);

	    oscillatorNode.frequency.value =
		( currentbeat % timetop ) === 0 ? 220.0
		: ( currentbeat % 4) === 0 ? 880.0
		: 440.0;
	    oscillatorNode.start(nextnotetime);
	    oscillatorNode.stop(nextnotetime + notelength);

	    addednotes++;

	    // Find next time for note
	    var secondsperbeat = 60.0 / tempo;

	    nextnotetime += (4.0 / timebottom) * secondsperbeat;

	    currentbeat++;
	    currentbeat %= timetop;
	}
	if (addednotes) {
	    // console.log(`${addednotes} notes were added`);
	}
	yield;
    };
}