I'm trying to use the HTML5 Web Audio API to create an equalizer type graphic, but for some reason the data is never brought into the MediaElementSource
.
$('.table').on('click', 'tr', function() {
if ($(this) != $('.table tr:first-child')) {
var src = $(this).children().first().attr('data-src');
var audio = new Audio();
audio.src = src;
audio.controls = true;
$('.file-playlist').append(audio);
console.log(audio);
audio.load();
audio.play();
context = new webkitAudioContext();
console.log(context);
analyser = context.createAnalyser();
console.log(analyser);
source = context.createMediaElementSource(audio);
console.log(source);
source.connect(analyser);
console.log(source);
analyser.connect(context.destination);
console.log(analyser);
rafCallback();
}
});
In the function above I have created an audio element and used that as the source for the context's MediaElementSource
however there is some issue that I cannot find because in the console, the activeSourceCount
attribute of the AudioContext is always 0, which means that it never received the audio element that I gave it as a parameter.
EDIT:
I modified my code according to what idbehold said; however, now I have 2 errors, an InvalidStateError: DOM Exception 11
on the source = context.createMediaElementSource(audio);
line, and a TypeError: Cannot read property 'frequencyBinCount' of undefined
at the line var freqByteData = new Uint8Array(analyser.frequencyBinCount);
Additionally, the MediaElementSource still has 0 activeSourceCounts.
$(document).ready(function() {
var context = new webkitAudioContext();
console.log(context);
var audio;
var source;
$('.table').on('click', 'tr', function() {
if ($(this) != $('.table tr:first-child')) {
var src = $(this).children().first().attr('data-src');
if (audio) {
audio.remove();
audio = new Audio();
audio.src = src;
audio.controls = true;
$('.file-playlist').append(audio);
console.log(audio);
audio.addEventListener("canplay", function(e) {
analyser = context.createAnalyser();
console.log(analyser);
source.disconnect();
source = context.createMediaElementSource(audio);
console.log(source);
source.connect(analyser);
console.log(source);
analyser.connect(context.destination);
console.log(analyser);
audio.load();
audio.play();
}, false);
}
else {
audio = new Audio();
audio.src = src;
audio.controls = true;
$('.file-playlist').append(audio);
console.log(audio);
audio.addEventListener("canplay", function(e) {
analyser = (analyser || context.createAnalyser());
console.log(analyser);
source = context.createMediaElementSource(audio);
console.log(source);
source.connect(analyser);
console.log(source);
analyser.connect(context.destination);
console.log(analyser);
audio.load();
audio.play();
}, false);
}
}
rafCallback();
});
});
EDIT 2:
in my rafCallback() function, I noticed that the data from the Uint8Array was never being processed, so I added the getByteFrequencyData(analyser.frequencyBinCount);
which fixed everything.
I'm trying to use the HTML5 Web Audio API to create an equalizer type graphic, but for some reason the data is never brought into the MediaElementSource
.
$('.table').on('click', 'tr', function() {
if ($(this) != $('.table tr:first-child')) {
var src = $(this).children().first().attr('data-src');
var audio = new Audio();
audio.src = src;
audio.controls = true;
$('.file-playlist').append(audio);
console.log(audio);
audio.load();
audio.play();
context = new webkitAudioContext();
console.log(context);
analyser = context.createAnalyser();
console.log(analyser);
source = context.createMediaElementSource(audio);
console.log(source);
source.connect(analyser);
console.log(source);
analyser.connect(context.destination);
console.log(analyser);
rafCallback();
}
});
In the function above I have created an audio element and used that as the source for the context's MediaElementSource
however there is some issue that I cannot find because in the console, the activeSourceCount
attribute of the AudioContext is always 0, which means that it never received the audio element that I gave it as a parameter.
EDIT:
I modified my code according to what idbehold said; however, now I have 2 errors, an InvalidStateError: DOM Exception 11
on the source = context.createMediaElementSource(audio);
line, and a TypeError: Cannot read property 'frequencyBinCount' of undefined
at the line var freqByteData = new Uint8Array(analyser.frequencyBinCount);
Additionally, the MediaElementSource still has 0 activeSourceCounts.
$(document).ready(function() {
var context = new webkitAudioContext();
console.log(context);
var audio;
var source;
$('.table').on('click', 'tr', function() {
if ($(this) != $('.table tr:first-child')) {
var src = $(this).children().first().attr('data-src');
if (audio) {
audio.remove();
audio = new Audio();
audio.src = src;
audio.controls = true;
$('.file-playlist').append(audio);
console.log(audio);
audio.addEventListener("canplay", function(e) {
analyser = context.createAnalyser();
console.log(analyser);
source.disconnect();
source = context.createMediaElementSource(audio);
console.log(source);
source.connect(analyser);
console.log(source);
analyser.connect(context.destination);
console.log(analyser);
audio.load();
audio.play();
}, false);
}
else {
audio = new Audio();
audio.src = src;
audio.controls = true;
$('.file-playlist').append(audio);
console.log(audio);
audio.addEventListener("canplay", function(e) {
analyser = (analyser || context.createAnalyser());
console.log(analyser);
source = context.createMediaElementSource(audio);
console.log(source);
source.connect(analyser);
console.log(source);
analyser.connect(context.destination);
console.log(analyser);
audio.load();
audio.play();
}, false);
}
}
rafCallback();
});
});
EDIT 2:
in my rafCallback() function, I noticed that the data from the Uint8Array was never being processed, so I added the getByteFrequencyData(analyser.frequencyBinCount);
which fixed everything.
1 Answer
Reset to default 6You can only create a single AudioContext
per window and you should be waiting until the audio's canplay
event fires before setting up your MediaElementSource
. You should also be disconnecting the MediaElementSource
when you're finished using it.
Here's an example that I used to answer a similar question: http://jsbin./acolet/1/