Web Audio API Audio Buffer

Web Audio API Audio Buffer

UPDATED ON: December 16, 2014

Web Audio API Audio Buffer is a tutorial that will give you an understanding of how to buffer and play audio with the Web Audio API. After all, playing an audio file is probably the first thing most people want to do. Simple, right? Nope. We have to load the audio into a buffer first. Web Audio API Audio Buffer builds on what we’ve covered in Web Audio API Basics, the first tutorial in the series so make sure to read it. After covering the process of buffering and playing audio in this tutorial, we’ll finish by applying what we’ve learned to create a working example.

Web Audio API Audio Buffer

Web Audio API Audio Buffer

Although we can generate oscillating wave forms quite easily with the Web Audio API, working with prerecorded sounds is a bit trickier. Audio files of various formats (wav, mp3, aac, ogg, etc.) can be played, but the audio source must first be loaded into a buffer. What’s a buffer? In generic terms, a buffer is a region of physical memory used to temporarily store data while it is being moved from one place to another. In this case, the data is the audio from the source file.

Load the Sound with an XMLHttpRequest

An XMLHttpRequest is used to load data into a buffer from the audio file. We give it the path to our audio file. Specifying true makes it load asynchronously. We want the audio to be read in as binary data, so we need to specify a response type of ‘arraybuffer’. Next, we create an onload function, decode the audio data and store it in the variable electro. Finally, the actual request to load is sent.

var getSound = new XMLHttpRequest();
getSound.open("GET", "sounds/electro2.wav", true);
getSound.responseType = "arraybuffer";
getSound.onload = function() {
context.decodeAudioData(getSound.response, function(buffer){
electro = buffer;
});
}
getSound.send();

Play the Sound

Once a sound has been buffered and decoded, it can be played instantly. Each time it is triggered, a different instance of the buffered sound is created. The Web Audio API allows multiple instances of a buffered sound to be played simultaneously. There are many ways to trigger sounds, but that’s a topic that’s probably definitely better suited for it’s own tutorial.

To play the sound we’ve loaded into our buffer, we’ll keep it simple and add a keydown EventListener for the [X] key. Then we declare a new sound and attach our audio data as it’s buffer. Finally, we link the sound to the output, and have it play immediately upon being triggered.

window.addEventListener("keydown",onKeyDown);
	
function onKeyDown(e){
switch (e.keyCode) {
// X
case 88:
var playSound = context.createBufferSource();
playSound.buffer = electro;
playSound.connect(context.destination);
playSound.start(0);
break;
}
}

Full Code to Load and Play Buffered Audio

Here’s the full code to load and play buffered audio with the Web Audio API. Change the path and filename of the audio file to match yours and you’ve got it!

// Create Annonomuos Self Executing Function
(function(){
	
	var context = new AudioContext(); // Create and Initialize the Audio Context
	var electro; // Create the Sound 
	var getSound = new XMLHttpRequest(); // Load the Sound with XMLHttpRequest
	getSound.open("GET", "sounds/electro2.wav", true); // Path to Audio File
	getSound.responseType = "arraybuffer"; // Read as Binary Data
	getSound.onload = function() {
		context.decodeAudioData(getSound.response, function(buffer){
			electro = buffer; // Decode the Audio Data and Store it in a Variable
		});
	}
	getSound.send(); // Send the Request and Load the File
	
	window.addEventListener("keydown",onKeyDown); // Create Event Listener for KeyDown
	
	function onKeyDown(e){
		switch (e.keyCode) {
			// X
			case 88:
				var playSound = context.createBufferSource(); // Declare a New Sound
				playSound.buffer = electro; // Attatch our Audio Data as it's Buffer
				playSound.connect(context.destination);  // Link the Sound to the Output
				playSound.start(0); // Play the Sound Immediately
			break;
		}
 	}
}());

Well, that’s the low down on using the Web Audio API Audio Buffer to load and play sounds in the browser. As you can see, loading and playing even one audio file requires quite a bit of code. Fortunately, much of this can be abstracted into a BufferLoader class that will make your life easier. I’m ready to explore the outer limits of imagination. Are you? The possibilities are endless. How are you going to use the Web Audio API to make the web awesome?

Other tutorials in this series

More examples of the Web Audio API in action


Comments

13 responses to “Web Audio API Audio Buffer”

  1. wolfie Avatar
    wolfie

    Nice demo Obadiah! I’m curious of how you create an AudioBuffer, you do it like this: buffer = context.createBuffer(incomingData, true);

    I can’t get this to work, is the API changed since you created your demo, or am I missing something?

    1. Wolfie, I’m not sure about API changes, but my method for creating an AudioBuffer should still work fine.

      What do you mean when you say you can’t get this to work? Could you be more specific? I’ll try to help if I can. You can always send a message from my contact page as well.

      Good luck!

      1. Rodrigo Avatar
        Rodrigo

        So Wolfie didn’t respond, but I’ll try to continue where he left off. I too have an issue with create a buffer using the method you describe. Currently, the api state that you must pass the following arguments: createBuffer(numberOfChannels,length,sampleRate),
        where as you pass the raw file itself (and I wish the process had stayed like that). Any suggestions?

        1. Thanks Rodrigo and Wolfie for pointing this out! Apparently, the spec has changed since I wrote this. I’ll look into it and update the tutorial when I figure it out.

  2. Hi,
    Thank’s for your demo !
    I have a question, I would like to do streaming with the javascript API and the problem is that onLoad is called when the file is completely loaded. Do you think that it would be possible to play sound using onProgress ? (Knowing that the response type has to be text to get it in the onProgress)

    Thank’s
    Lukas

    1. You’re welcome Lukas! I’m not sure about using onProgress, but it sounds interesting. Please let me know if it does. Thanks!

  3. I had a problem loading an mp3 on my system (MacOSX 10.9), but I resolved it by first running a small python command in Terminal.

    First cd into the directory that contains both your .html file and your audio file. Then run

    python -m SimpleHTTPServer

    Change your load command to

    request.open(“GET”, “myfile.mp3”, true); // Path to Audio File

    Then it should work.

    1. Thanks for sharing Mike!

  4. Thanks for your great tutorial.

    I have tested this code it works very well in firefox but when I use chrome after the page is loaded it gives this error:

    GET http://localhost/audio/kick.wav net::ERR_EMPTY_RESPONSE

    I have kick.wav in my audio folder

    What is the solution? Why chrome could not get the file?

    1. You’re welcome Ehsan!

      What Operating System are you using? I get no errors in Chrome on Windows. Note the audio source path “sounds/electro2.wav” in the code. Could be a problem with your installation of Chrome…

      1. Thanks a lot.
        I use Windows and the problem is solved right now.
        Your articles are really great and easy to understand I am reading them one by one.

  5. Hi! I love this is great!! I have an issue. I made it work with chrome, but it doesn’t work in firefox, and I have the latest version. The oscilator works fine, so I think it has something to do with the XMLhttp request, but I don’t know. Could somebody help me?

    Thanks!

  6. Morten Skogly Avatar
    Morten Skogly

    Is there a way to stop the sound on key up?

Leave a Reply

Your email address will not be published. Required fields are marked *