If sound clicks or stutters

Sound should be smooth however busy your drawing is. If it clicks, crackles or stutters, or a key feels late, the page is most likely making its sound the slow way. This page says what that is, why a page gets it, and what to do.

The short answer

Open the page from an https address (or from localhost). Then the sound is made on the browser's audio thread, and the clicks go.

Circuitry itself is served over https, so a scene in its preview has the audio thread. So has a scene run with pictures run or pyctures run on the same computer, which is localhost.

What is happening

The sound is made by an engine that runs on the browser's audio thread, away from your program. So sound does not slow a frame, and a slow frame does not break the sound.

A browser only gives a page an audio thread when the page is secure: served over https, or from localhost. A page that is not has none. The usual way to meet one is a page on your own computer, opened on a phone or an iPad by the computer's address (http://192.168…).

There the same engine runs on the page's own thread. This is the fallback. It is the same sound, with two costs:

  • It is later. Sound is made 2048 frames at a time (about 43 thousandths of a second), and everything is scheduled two of those ahead. A key is heard about 95 thousandths of a second after it is pressed, where the audio thread takes 40. The times between notes stay exact, so a tune is still in time.
  • It clicks when the page is busy. The page's thread is also drawing your scene. When it is busy for longer than one buffer lasts, the next piece of sound arrives late, and that is heard as a click.

The browser's console says once that the fallback is in use, and why.

What to do

  1. Use an https address. It has neither cost. This is the real cure.
  2. Do less in a frame. A click is the page being busy. Fewer things drawn, or a smaller picture, gives the sound its turn.
  3. Make the buffer bigger, with one line. A bigger buffer rides over a busier page, and is heard later:
BufferA key is heard afterRides over a page busy for
1024 frames ("small")about 50 ms10 ms
2048 frames ("medium")about 95 ms30 ms
4096 frames ("large")about 180 ms60 ms

Left alone, the buffer starts at 2048 and is doubled once, by itself, if the page keeps being too busy (four times in ten seconds). It is never made smaller again. So a page that clicked at first often settles.

So for music played from the keys, where a late note matters, go smaller; for a busy game on a slow device, go larger.

Setting the buffer

setSoundBuffer("large")        // "small" (1024 frames), "medium" (2048), "large" (4096), "auto", or a number of frames

function draw() {
  background("midnightblue")
  const now = soundBuffer()    // { frames, delay, thread, underruns, setting }
  text(now.delay + " ms late, " + now.underruns + " clicks", width / 2, height / 2, "white", 24, "centre")
}

It may be called before the first sound, and at any time after. "auto" lets the library choose again.

soundBuffer() says how things are now:

It givesWhat it is
framesHow much sound is made at a time
delayThe thousandths of a second from a key to its note
thread"page" on the slow way, "audio" on the audio thread, and nothing before the first sound
underrunsHow many times a piece of sound came too late. Each is a click
settingWhat you asked for: a number of frames, or "auto"

On the audio thread there is nothing to fix. The engine there always makes 128 frames at a time, which nothing can change, so the same call sets how far ahead everything is scheduled instead, and the console says once that this is what it did. That is what happens in Circuitry, which is served over https.

In the iPad and iPhone app

In Circuitry's iPad and iPhone app the sound of a scene is made by the app itself, on the device's own audio thread, and not by the page the scene is drawn in. So a busy scene cannot make the sound click or stutter there, and a tune or a song is kept in time by the sound engine, whatever the page is doing.

  • No first tap is needed. Sound is on from the start, so nothing waits for a touch.
  • It is the same engine. A scene sounds the same as it does in a browser.
  • It is sound out only. The microphone and MIDI are not connected in a scene there, as they are not in Circuitry's preview anywhere yet.

If sound misbehaves on your device, turn it off: Settings, General, Native sound engine. Sound is then made in the page, as in a browser. It applies the next time a preview starts. The setting is only there in the iPad and iPhone app.

It applies to the app only. A browser on an iPad or an iPhone, and a page made with Export as Web Page, make their sound in the page as everywhere else.

Other things that sound like this

  • Nothing at all until you click. A browser keeps a page silent until its first click, tap or key press. See The first click.
  • Notes cut off. There are 64 voices. With more notes than that sounding at once, the oldest makes way. Long release times and big chords use them up.