Your First Steps with the Web Audio API

Aaron Ervin

The Web Audio API is an abstraction layer which aims to simplify audio programming for the web.

In this short introduction, you’ll learn about the Web Audio API’s AudioContext, and the ability of AudioContext instances to create simple oscillators which can be used to transform your browser into a retro synthesizer! This tutorial’s code snippets have been tested in Chrome, but you can probably follow along using the console of your favorite browser’s developer tools.

Prep work

As mentioned, support for the Web Audio API is not universal, so it’s best to verify that the API is available in the user’s browser:

let audioContext;

try {
  audioContext =
    new (window.AudioContext || window.webkitAudioContext)();
} catch (error) {
  window.alert(
    `Sorry, but your browser doesn't support the Web Audio API!`
  );
}

if (audioContext !== undefined) {
  /* Our code goes here */
}

After this simple check, we’re safe to use the Web Audio API’s functionality.

About AudioContext

It might be helpful to imagine audioContext–our instance of the AudioContext–as a sort of DJ: it coordinates a collection of audio sources and ensures that the sources play through the user’s speakers at the right time and with the right “sound.” And like a DJ, we can think of audioContext as a mediator between sources of sound and a “sound system,” the host machine’s audio hardware. Here are some more things to keep in mind when working with the AudioContext:

  • The AudioContext is a master “time-keeper.” All signals should be scheduled relative to audioContext.currentTime.
  • Instances of the AudioContext can create audio sources from scratch.

A simple oscillator

To see what sorts of sounds it can generate on its own, let’s use audioContext to create an OscillatorNode:

const oscillator = audioContext.createOscillator();

This is all we need to make sound with the browser–an AudioContext and an OscillatorNode. But first, we need to “wire” the oscillator to our audioContext:

oscillator.connect(audioContext.destination);

The Web Audio API attempts to mimic an analog signal chain. We pipe our input signal (the oscillator) into a digital power amp (the audioContext), which then passes the signal to the speakers (the destination).

Let’s make some noise:

oscillator.start();

You should hear a sound comparable to a dial tone. Congratulations, you’re making music with the Web Audio API! Of course, no one wants to hear the same pitch forever and ever. You can stop our oscillator this way:

oscillator.stop();

Once an AudioNode has been stopped, it cannot be started again! A new AudioNode will need to be created to resume playback.

The start and stop methods both accept a single parameter of type number. The parameter value is used to schedule the start/stop events:

/* Emit a signal 10 seconds from now */
oscillator.start(audioContext.currentTime + 10);

/* Cancel the signal 10 seconds after that */
oscillator.stop(audioContext.currentTime + 20);

Let’s conclude by manipulating our oscillator to make different sounds.

Manipulating sound with AudioParams

Logging the oscillator object, we get something like this (specific property values are omitted as they may be different depending on the device/browser):

console.log(oscillator);
/*
  {
    channelCount: number,
    context: AudioContext,
    detune: AudioParam,
    type: 'sine' | 'sawtooth' | 'triangle' | 'square'
    frequency: AudioParam,
    numberOfInputs: number,
    numberOfOutputs: number,
    onended: function
    ...
  }
*/

The property that matters most for our purposes is oscillator.frequency:

console.log(oscillator.frequency);
/*
  {
    defaultValue: number,
    maxValue: number,
    minValue: number,
    value: number // Probably 440 (A4)
  }
*/

The frequency value of our oscillator implements the AudioParam interface. The sound of an AudioNode such as oscillator can be manipulated via its AudioParam properties. However, direct reassignment to the AudioParam value property has been deprecated in favor of helper methods.

/* Don't do this */
oscillator.frequency.value = 500;

If we want our oscillator to emit a “Bb” instead of an “A”, we should do something like this:

/* The frequency (in Hz) of Bb4 is 466.16 */
oscillator
  .frequency
  .setValueAtTime(466.16, audioContext.currentTime);

or

/* Slowly transition to Bb4 over the span of 10 seconds */
oscillator
  .frequency
  .exponentialRampToValueAtTime(
      466.16,
      audioContext.currentTime + 10
  );

Bonus: adjusting the periodic waveform

Our oscillator uses a periodic waveform to emit its tone. The waveform is represented by the type property of the OscillatorNode interface. By default, the type is 'sine'. Most browsers support at least three other options: 'sawtooth', 'triangle', and 'square'. So, changing the “tone” of our oscillator is as simple as:

oscillator.type = 'triangle';

Conclusion

Generating and manipulating audio in the browser is easier than ever thanks to the Web Audio API. With its help, web developers can recreate retro synth tones with 3-5 lines of code.

🎶 CHALLENGE: Use the Web Audio API to program the riff from Funkytown!

  Tweet It

🕵 Search Results

🔎 Searching...

Sponsored by #native_company# — Learn More
#native_title# #native_desc#
#native_cta#