Skip to main content
Lightning Jar - Web Studio Lightning Jar Wordmark

Findings No. 1

iOS starts an AudioContext suspended, and the promise from resume() may never settle

Schedule nothing until the context state reads running: poll state alongside onstatechange, give the wake a deadline, and replace a context that never wakes.

Stem Shovel Web Audio verified iOS Safari

On iOS, an AudioContext is born suspended, wakes slowly, and the promise returned by resume() is not a reliable signal that it ever woke: one test phone sat on a loading state for minutes while awaiting it. Meanwhile, notes scheduled against currentTime pile up at time zero, so every key pressed during the wake sounds at once, a second or two later.

The shape that works: warm the context on the first touch, hold notes until ctx.state reads running, and watch the wake by polling state alongside the onstatechange event rather than trusting the promise. Play a silent one-sample buffer as the old-style unlock. Give the wake a deadline (three seconds in our piano), and if the context never comes up, throw it away so the next touch gets a fresh one.

Receipt: Stem Shovel's piano (piano.svelte.ts, commits 58232b7, 37067c1, a410a8d; docs/piano.md, "iOS and the first note").

Ask Eljay

Ask about the studio's work, research, packages, or writing. A few starters:

Answers come from this site's own content and link their sources. For anything that matters, email hello@lightningjar.com.