I have a web page which decodes wave files for certain reasons. Chrome and Safari seem to work fine. Firefox occasionally is unable to decode the file and gives the error: "The buffer passed to decodeAudioData contains invalid content which cannot be decoded successfully." I have created a jsfiddle which illustrates the issue:
var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var source;
function getData() {
source = audioCtx.createBufferSource();
request = new XMLHttpRequest();
request.open('GET', 'https://mpclubtest.s3.amazonaws.com/Malice_Bass.wav', true);
request.responseType = 'arraybuffer';
request.onload = function() {
var audioData = request.response;
audioCtx.decodeAudioData(audioData, function(buffer) {
source.buffer = buffer;
source.connect(audioCtx.destination);
},
function(e){"Error with decoding audio data" + e.err});
}
request.send();
}
getData();
source.start(0);
Can anyone tell me what the issue is and if there is any way to circumvent? Many Thanks.
EDIT Thanks to the substantial contributions of Michael Chaney I was able to implement some javascript which processes the wave so that it can be played in Firefox. The code trims any part of the "fmt" chunk over 16 bytes. Code located at: jfiddle
var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var source;
function getData() {
source = audioCtx.createBufferSource();
request = new XMLHttpRequest();
request.open('GET', 'https://mpclubtest.s3.amazonaws.com/Malice_Bass.wav', true);
request.responseType = 'arraybuffer';
request.onload = function() {
var audioData = request.response;
var dv = new DataView(audioData);
var junk = 0;
var position = 12;
do {
var header = String.fromCharCode.apply(null, Uint8Array(audioData, position, 4));
var length = dv.getUint32(position + 4, true);
if (header.trim() === 'fmt') {
junk = junk + length - 16;
}
position = position + 8 + length;
}while(position < audioData.byteLength);
var productArray = new Uint8Array(audioData.byteLength - junk);
productArray.set(new Uint8Array(audioData, 0, 12));
var newPosition = 12;
position = 12;
var fmt_length_spot;
do {
var header = String.fromCharCode.apply(null, Uint8Array(audioData, position, 4));
var length = dv.getUint32(position + 4, true);
if (header.trim() === 'fmt') {
productArray.set(new Uint8Array(audioData, position, 24), newPosition);
fmt_length_spot = newPosition + 4;
newPosition = newPosition + 24;
}
else {
productArray.set(new Uint8Array(audioData, position, length + 8), newPosition);
newPosition = newPosition + 8 + length;
}
position = position + 8 + length;
}while(position < audioData.byteLength);
audioData = productArray.buffer;
dv = new DataView(audioData);
dv.setUint32(4, audioData.byteLength - 8, true);
dv.setUint32(fmt_length_spot, 16, true);
audioCtx.decodeAudioData(audioData, function(buffer) {
source.buffer = buffer;
source.connect(audioCtx.destination);
},
function(e){"Error with decoding audio data" + e.err});
}
request.send();
}
getData();
source.start(0);
Thanks Michael.