Making Sound with the Web Audio API

The Web Audio API makes sound from nothing, no audio files needed. An AudioContext is the sound engine. An oscillator produces a tone at a frequency measured in hertz (440 is the A that orchestras tune to), and a gain node sets its volume. You connect them in a chain, oscillator to gain to audioCtx.destination, the speakers, then start and stop the oscillator at times measured by audioCtx.currentTime, in seconds.

✦ Sound needs a click first

Browsers won't let a page make sound until the person has interacted with it, so a page can't suddenly blare at you. Create or resume the AudioContext inside a click handler. Once it has been unlocked, code that plays later, such as a timer reaching zero, is allowed to make sound.

A tone that starts and stops instantly makes a click. An envelope fixes that: the gain starts near silence, rises over a few hundredths of a second, then fades away slowly. Exponential ramps sound natural to the ear, and they can't ramp to exactly 0, which is why the quiet end is 0.0001.

EXAMPLE · WEB PAGE
loading editor…
WHAT THIS DOES

The click unlocks the sound engine, then tone builds a short chain for each note: an oscillator at a frequency, through a gain that fades in and out, to the speakers. Two tones at once, 440 and 660 hertz, blend into one bell-like sound.

YOUR TURN · WEB PAGE
Your turn → Add a second button for a deep gong: three tones at low frequencies such as 82, 110 and 165 hertz, lasting about five seconds. Then try osc.type = "triangle" on one of them and listen to the difference.
loading editor…

Syntax has to be exact. Every quote, bracket, brace and parenthesis needs its partner, and every HTML tag you open needs closing. One slip and the script won't run; the message under the page will say where.

Stopping a sound early means keeping hold of what you started. Push each oscillator and gain into an array as you create them; a stop function then calls stop() and disconnect() on each one and empties the array. Repeating a sound, as an alarm does until someone answers it, is a setInterval that plays it again, cleared by the same stop function.

◈ Graded Build

Finish the sound board. playBowl() and playGong() each play a different sound using tone(). Every node tone() creates goes into the activeNodes array, and stopAudio() stops and disconnects them all and empties the array. The three buttons call unlockAudio() and then their function.

Checked by using your page: clicking, typing and waiting, then reading what changed. 3 visible and 1 hidden checks.

loading editor…

Mark this lesson complete

Signed in, your progress follows you to every device.

Next: Practice Test →
← Back