I am working on an Ionic / Cordova app which involves loading three minute audio clips (mp3) from a remote server and playing them.
I have followed this tutorial - http://www.html5rocks.com/en/tutorials/webaudio/intro/ - and the loading and playing works fine.
However I want to store / cache the loaded mp3 locally so that the user only has to download it once and the app can work offline. The files are approx 750 KB. In the example below the file is only 74 KB.
Elsewhere in the app I am using Mozilla's localForage (via [ngular-localForage) which specifically states it can be used to store ArrayBuffers - http://mozilla.github.io/localForage/#setitem
However I can't seem to retrieve the audio in a format I can play... I suspect I'm storing the wrong thing - I don't really understand what an ArrayBuffer is!
Anyway here is my basic code (at the moment I'm using a local file). First load the audio plays correctly, second load I get an error (see below):
window.AudioContext = window.AudioContext || window.webkitAudioContext;
var context = new AudioContext();
function loadDingSound() {
// attempt to retrieve stored file
$localForage.getItem('ding').then(function (response) {
if (response) {
console.log('playing audio from localForage');
console.log(response);
context.decodeAudioData(response, function(buffer) {
playSound(buffer);
});
} else {
var request = new XMLHttpRequest();
request.open('GET', 'audio/ding.mp3', true); // loading local file for now
request.responseType = 'arraybuffer';
// Decode asynchronously
request.onload = function() {
$localForage.setItem('ding', request.response).then(function () {
context.decodeAudioData(request.response, function(buffer) {
playSound(buffer);
});
});
};
request.send();
}
});
}
function playSound(buffer) {
var source = context.createBufferSource(); // creates a sound source
source.buffer = buffer; // tell the source which sound to play
source.connect(context.destination); // connect the source to the context's destination (the speakers)
source.start(0); // play the source now
}
// init
loadDingSound();
And the response I get in the console is as follows:
Object {} // line 13
Error: Failed to execute 'decodeAudioData' on 'AudioContext': invalid ArrayBuffer for audioData. // line 15
At the moment I've only been testing this in Chrome, not the Cordova app.
What am I doing wrong? Or is there is a better way to do this? Perhaps I could save the MP3 to the file system instead...?