Visualising <audio> elements with the Web Audio API

18 September 2012

3 comments

A Blue Perspective: Visualising <audio> elements with the Web Audio API

For a new project I'm working on I'd like to create an audio-reactive visualisation using analysis of the music that's playing. The new Web Audio API lets you do this pretty easily in the browser (Webkit-only at the moment).

I'm posting my documented code here with an explanation for anyone else who would like an easy snippet to get them started down the music visualisation path. You can view a demo here and download the source code here.

The main concept in the Web Audio API is that you wire up a bunch of modules together. The output from one module going into the input of another module. To this with an <audio> element, you have to create a Web Audio source with it, wire that up to an analyser, and then wire the analyser up to your speakers (so that you can hear the original <audio> again).

The code for all that looks something like this:

var audio = document.getElementById('music');
var audioContext = new webkitAudioContext();
analyser = audioContext.createAnalyser();
var source = audioContext.createMediaElementSource(audio);
source.connect(analyser);
analyser.connect(audioContext.destination);

Once you've done that, the analyser is now listening for any output from the <audio> and will have data waiting for you whenever you ask it.

Once you set the audio.play()ing you can query the analyser at any time and check what the current frequency data of the sound is. If we put that analysis into a simple draw() loop then we can graph out what the sound looks like:

function draw() {
	// Setup the next frame of the drawing
	webkitRequestAnimationFrame(draw);
	
	// Create a new array that we can copy the frequency data into
	var freqByteData = new Uint8Array(analyser.frequencyBinCount);
	// Copy the frequency data into our new array
	analyser.getByteFrequencyData(freqByteData);

	// Clear the drawing display
	canvasContext.clearRect(0, 0, canvas.width, canvas.height);

	// For each "bucket" in the frequency data, draw a line corresponding to its magnitude
	for (var i = 0; i < freqByteData.length; i++) {
		canvasContext.fillRect(i, canvas.height - freqByteData[i], 1, canvas.height);
	}
}

You can see a demo of this running in my experiments section. I've just done a very simple line rendering of the frequency data but your imagination is the limit. Download the source code and see what you can do with it!

Stay tuned for the prettiness that I've actually got planned for this code.

Update (2013-04-22): This article has kindly been translated into Serbo-Croatian by Anja Skrba. You can read it here: http://science.webhostinggeeks.com/vizualizovanje-elemenata-sa-web

Categories

, , , , , , ,

Comments

  1. 1/3

    Joseph Gillson commented on 19 September 2012 @ 20:17

    Thanks. I shall try to use.

  2. 2/3

    Ann Martinez commented on 19 September 2012 @ 21:39

    This is interesting. We use it in the future.
    Thank you for work with the music.

  3. 3/3

    Aaron Savy commented on 20 September 2012 @ 05:26

    Good Works. Thanks.

  4. Leave your own comment

    Comments have been turned off on this entry to foil the demons from the lower pits of Spamzalot.

    If you've got some vitriol that just has to be spat, then contact me.

Follow me on Twitter

To hear smaller but more regular stuff from me, follow @themaninblue.

Monthly Archives

Popular Entries

My Book: Simply JavaScript

Simply JavaScript

Simply JavaScript is an enjoyable and easy-to-follow guide for beginners as they begin their journey into JavaScript. Separated into 9 logical chapters, it will take you all the way from the basics of the JavaScript language through to DOM manipulation and Ajax.

Step-by-step examples, rich illustrations and humourous commentary will teach you the right way to code JavaScript in both an unobtrusive and an accessible manner.

RSS feed