Web Audio API

I've developed a TypeScript based sound effect generator using the Web Audio API called SFXWeb. I've learned a lot developing this API, so I've decided to write a tutorial explaining how you can generate sounds using the Web Audio API in your HTML5 games and apps.

AudioContext

The AudioContext is the interface through which you will use the web audio api. I will show you how you can use a series of AudioNode objects that you string together using calls to their "connect" methods to generate sounds that you will eventually connect to the AudioContext.destination. We use our AudioContext to create the nodes, and to access the current time for the nodes to use while creating or modifying our sounds.

AudioNode

The AudioNode is an interface we use to either generate our sounds (using an Oscillator) or to manipulate it in some way by creating a filter or a gain. The Web Audio API has several types of these AudioNodes. We usually AudioBufferSourceNode the output of one node to the input of a second node using the "connect" method in the following way:

starting_audio_node.connect( output_to_audio_node );

The previous code sends the output of the "starting_audio_node" to the "output_to_audio_node". The starting_audio_node might be something like an OscillatorNode that generates a tone, and the output_to_audio_node might be a GainNode, which is used to change the volume. Or it could be a BiquadFilterNode which can be used to create a low pass or a high pass filter.

OscillatorNode

An OscillatorNode can be used to generate a wave form that you can then process with other AudioNodes. You tell an OscillatorNode what type of wave it is (e.g. sin, square, sawtooth) and give it a frequency and it will output a very unpleasant sound. However, with a little processing you can turn those nasty sounds into the bleeps, boops, and laser blasts you remember from your 8bit childhoodA games. Square waves and triangle waves are able to produce many of the sounds you might remember from the NES days because the NES was only able to generate square waves, triangle waves and noise. We'll cover noise later because you don't use an oscillator to generate it.

GainNode

A GainNode is used to adjust the volume on a node that connects to it. Gain does't have to strictly be like a volume knob though. You can create what is called an Envelope of gain which tells the sound how to fade in, and how to fade out.

BiquadFilterNode

BiquadFilterNodes are used to filter out frequencies from your sound. Two of the most common forms of this filter are the low pass filter, which is used to remove high pitch sounds and the high pass filter which is used to remove low pitch sounds. At first that felt a little backwards to me, but you have to remember, the low pass filter is allowing low frequncies to pass, and the high pass filter is allowing high frequencies to pass.

Creating Noise using AudioBufferSourceNode

Using the AudioContext, create an AudioBufferSourceNode. A Float32Array array buffer is used for random data to be thrown into the audio buffer. Loop over every float32 and randomly generate data to put into this buffer.

Duty Cycle

A Duty Cycle is a gain node use to turn the volume completely on and off through a period of time. It is used frequently in a lot of 8 bit sound effects.

High Pass Filter

A High Pass filter is created using a BiquadFilterNode. This will allow only the frequencies above a certain level pass, and filters out all the frequencies below that. It gives the sound a tinny tweeter only sort of sound.

Low Pass Filter

A low pass filter is the opposite of a high pass filter. It filters out all of the higher pitched frequncies, usually giving the sound a sort of muffled feel.

Frequency Slide

A lot of old school sound effects use a frequency slide. Think of a slide whistle and the effect it creates. Creating a OscillatorNode with a constant frequency creates an ear bleeding effect that makes you want to turn it off immediately. Many laser sound effects in old games slide the frequency of an oscillator from high to low which gives a sense of speed because in real life we are used to the doppler effect for fast approaching objects.

Vibrato

Vibrato is a volume effect that typically adjusts the volume based on an oscillator. It is similar to a duty cycle, but the duty cycle turns the sound completely off or on, and the vibrato effect ramps the volume up and down usually based on a sine wave.

Volume Envelope

To have a sound begin at full volume then abruptly end doesn't sound good. In the real world sounds fade in, and then out. Many sounds in games use a ADSR envelope, which stands for Attack, Decay, Sustain, and Release. Attack is the initial time the envelope takes to fade in. There may be a "punch" associated with the attack where the volume goes above the sustaining volume. The Decay is the amount of time it takes for the volume to be reduced from the Attack volume level down to the Sustaining volume level. The Sustain time is how long the volume will remain without changing. The Release time is how long it takes for the sound to then fade out.

Flange Effect

The Flange Effect is a feedback effect where we combine two identical wave forms with a delay. It's frequently used to create swoosh, jet or drain effects.

OscillatorTone method


public OscillatorTone = (frequency: number, wave: OscillatorType): OscillatorNode => {
var context: AudioContext = SFXWeb.ACTX;
var tone: OscillatorNode = context.createOscillator();
tone.type = wave;
tone.frequency.setValueAtTime(frequency, context.currentTime); // value in hertz

return tone;
}

Embed Games

 
To suggest an improvement, or just say hi, please contact me on twitter :-)

Follow @battagline or  Tweet to @battagline

Thanks,
Rick