Web Audio API

The Basics

Imagine

A web-based game without audio.

Picture from HexGL by Thibaut Despoulain

It's just... terrible.

Web Audio API come in rescue!

Understanding the structure first

This is very important!

Accurate timing

Consist of different nodes

Fire-and-forget

Summary

  • Accurate Timing
    All sounds can be fired at specific time in per-sample precision. This makes it suitable for music applications such as drum machines that require precise timing.
  • Consist of different nodes
    Web Audio API have various nodes that can connect to each other with a function call. This make it suitable for doing sound FX in a logical way.
  • Fire-and-forget
    Sound in web audio API can only be fired once. However, multiple sounds can be played at the same time. This makes it good for doing game audio.

Time for some real stuff

Start it up!

// All methods of the web audio API are inside
// an object called AudioContext. All sounds are
// fired inside this context, and only one context
// per page is allowed. If you call this repeatedly,
// you'll get back the same AudioContext object.

var audioContext = new AudioContext();

// In the above example, we only take care of the
// latest browsers. To make older browsers that supports
// the web audio API to work, we should do the following

var audioContext = new (window.AudioContext || window.webkitAudioContext)();

Load an audio file

// Preparing things up!
// Create the audio nodes for our first work!
var sound = null; // Store the sound globally

// Load an audio file using XMLHttpRequest2
var xhr = new XMLHttpRequest();
xhr.responseType = 'arraybuffer';
xhr.onload = function(){
    // Decode the audio file to raw audio samples
    audioContext.decodeAudioData(xhr.response, function(buffer){
        // Save the buffer for later use
        sound = buffer;
        // Play it once it's loaded. You'll meet this again in the next slide.
        play();
    });
};

xhr.open('GET', '/some/audio/files.mp3', true);
xhr.send(null);

Play the sound

// Here's our function for playing a sound.
function play(){
    // Here's our node for playing sounds.
    var soundNode = audioContext.createBufferSource();
    
    // Add the audio in for playing
    soundNode.buffer = sound;

    // Connect the sound node to the speakers
    soundNode.connect(audioContext.destination);

    // Fire it up!
    // The first argument is the time offset to play the file
    // 0 means to play it immediately, otherwise it stands for
    // the time in seconds to play since the AudioContext object
    // has created.
    soundNode.start(0);
};

It's that simple

Now add something to it!

Loop it

// Here's our function for playing a sound.
function play(){
    // Here's our node for playing sounds.
    var soundNode = audioContext.createBufferSource();
    
    // Add the audio in for playing
    soundNode.buffer = sound;

    // *Loop it*
    soundNode.loop = true;

    // Connect the sound node to the speakers
    soundNode.connect(audioContext.destination);

    // And play it
    soundNode.start(0);
};

Playback Speed

// Here's our function for playing a sound.
function play(){
    // Here's our node for playing sounds.
    var soundNode = audioContext.createBufferSource();
    
    // Add the audio in for playing
    soundNode.buffer = sound;

    // *Speed it up by 50%*
    soundNode.playbackRate.value = 1.5;

    // Connect the sound node to the speakers
    soundNode.connect(audioContext.destination);

    // And play it
    soundNode.start(0);
};

How about the volume?

Introducing the gain node

Create gain node

// Here's our function for playing a sound.
function play(){
    // Here's our node for playing sounds.
    var soundNode = audioContext.createBufferSource();
    var gainNode = audioContext.createGain(); // THE GAIN NODE
    
    // Add the audio in for playing
    soundNode.buffer = sound;

    // Set the gain to be 50% louder
    gainNode.gain.value = 1.5;

    // Connect the sound node to the speakers
    soundNode.connect(gainNode); // GAIN NODE FIRST
    gainNode.connect(audioContext.destination);

    // And play it
    soundNode.start(0);
};

Fade in

// Here's our function for playing a sound.
function play(){
    // Here's our node for playing sounds.
    var soundNode = audioContext.createBufferSource();
    var gainNode = audioContext.createGain(); // THE GAIN NODE
    
    soundNode.buffer = sound;

    // Set gain to 0
    gainNode.gain.value = 0;

    // Connect the sound node to the speakers
    soundNode.connect(gainNode); // GAIN NODE FIRST
    gainNode.connect(audioContext.destination);

    soundNode.start(0);
    
    // Fade in after 2 seconds
    gainNode.gain.linearRampToValueAtTime(1, audioContesxt.currentTime + 2);
};

Fade out

// Here's our function for playing a sound.
function play(){
    // Here's our node for playing sounds.
    var soundNode = audioContext.createBufferSource();
    var gainNode = audioContext.createGain(); // THE GAIN NODE
    
    soundNode.buffer = sound;

    gainNode.gain.value = 1;

    // Connect the sound node to the speakers
    soundNode.connect(gainNode); // GAIN NODE FIRST
    gainNode.connect(audioContext.destination);

    soundNode.start(0);

    // Calculate the time to fade out
    var fadeOutPosition = audioContext.currentTime + sound.duration - 2;
    
    // Fade out after 2 seconds
    gainNode.gain.linearRampToValueAtTime(1, fadeOutPosition);
};

Exercise

Make an audio player that fades in and out during start and end

Q & A

The End.

Thanks for attending!

Web Audio API: The Basics

By Licson

Web Audio API: The Basics

This shows you the basic elements of Web Audio API and how to start using it right away!

  • 832