I have a web page that for some reason decodes wave files. Chrome and Safari seem to be working fine. Firefox sometimes cannot decode the file and gives an error: "The buffer passed to decodeAudioData contains invalid content that cannot be decoded successfully." I created jsfiddle which illustrates the problem:
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 someone tell me what the problem is, and is there any way around it? Thank you very much.
EDIT Thanks to the significant contribution of Michael Cheney, I was able to implement some javascript that processes the wave so that it can be played in Firefox. The code truncates any part of the "fmt" fragment to 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.