I’m trying to create a graphic equalizer type visualization for HTML5 audio – Chrome only at this point, using webkitAudioContext.
I’m finding unusual and unpredictable behaviour when I try to change the source of the audio i.e. to play a different song. I read somewhere I should wait until the “canplay” event on the audio is triggered before connecting it to the context / analyser:
var context, sourceNode, analyser, javascriptNode, audio;
var ctx = $("#songcanvas").get()[0].getContext("2d");
function loadSong(url) {
if (audio!=undefined) { audio.pause(); }
audio = new Audio();
audio.src = url;
audio.addEventListener("canplay", function(e) {
setupAudioNodes();
}, false);
}
function setupAudioNodes() {
context = new webkitAudioContext();
javascriptNode = context.createJavaScriptNode(2048, 1, 1);
javascriptNode.connect(context.destination);
analyser = context.createAnalyser();
analyser.smoothingTimeConstant = 0.3;
analyser.fftSize = 512;
sourceNode = context.createMediaElementSource(audio);
sourceNode.connect(analyser);
analyser.connect(javascriptNode);
sourceNode.connect(context.destination);
javascriptNode.onaudioprocess = function() {
var array = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(array);
ctx.clearRect(0, 0, 1000, 325);
ctx.fillStyle="rgba(32, 45, 21,1)";
drawSpectrum(array);
}
audio.play();
}
function drawSpectrum(array) {
for ( var i = 0; i < (array.length); i++ ){
var value = array[i];
ctx.fillRect(i*5,325-value,3,325);
}
};
The first three or four times I change the source, it works, then eventually fails with “Uncaught SyntaxError: audio resources unavailable for AudioContext construction”
Full demo here http://jsfiddle.net/eAgQN/
I’d recommend staying away from creating a
JavaScriptNodeif you’re simply going to be drawing the spectrum. Instead try utilizing therequestAnimationFramemethod as it will save CPU cycles and will get you closer to a constant 60fps (is especially useful if your window/tab is in the background as any function wrapped in arequestAnimationFramewill wait until the window is in focus again before firing).The reason you’re probably getting that error is because A) you can only create a single
AudioContextper window, B) you should be disconnecting theMediaElementSourcewhen you’re finished using it, and C) you should also be removing the actualAudioelement too.Here’s a your demo with the changes I outlined above: http://jsbin.com/acolet/1/