/* SoundEffectManager Loads and plays sound effects useing HTML5 Web Audio API (as only available in webkit, at the moment). By @HenrikJoreteg from &yet */ /*global webkitAudioContext define*/ (function () { var root = this; function SoundEffectManager() { this.support = !!window.webkitAudioContext; if (this.support) { this.context = new webkitAudioContext(); } this.sounds = {}; } // async load a file at a given URL, store it as 'name'. SoundEffectManager.prototype.loadFile = function (url, name, delay) { if (this.support) { this._loadWebAudioFile(url, name, delay); } else { this._loadWaveFile(url.replace('.mp3', '.wav'), name, delay); } }; // async load a file at a given URL, store it as 'name'. SoundEffectManager.prototype._loadWebAudioFile = function (url, name, delay) { if (!this.support) return; var self = this, request = new XMLHttpRequest(); request.open("GET", url, true); request.responseType = "arraybuffer"; request.onload = function () { self.sounds[name] = self.context.createBuffer(request.response, true); }; setTimeout(function () { request.send(); }, delay || 0); }; SoundEffectManager.prototype._loadWaveFile = function (url, name, delay, multiplexLimit) { var self = this, limit = multiplexLimit || 3; setTimeout(function () { var a, i = 0; self.sounds[name] = []; while (i < limit) { a = new Audio(); a.src = url; a.load(); self.sounds[name][i++] = a; } }, delay || 0); }; SoundEffectManager.prototype._playWebAudio = function (soundName) { var buffer = this.sounds[soundName], source; if (!buffer) return; // creates a sound source source = this.context.createBufferSource(); // tell the source which sound to play source.buffer = buffer; // connect the source to the context's destination (the speakers) source.connect(this.context.destination); // play it source.noteOn(0); }; SoundEffectManager.prototype._playWavAudio = function (soundName, loop) { var self = this, audio = this.sounds[soundName], howMany = audio && audio.length || 0, i = 0, currSound; if (!audio) return; while (i < howMany) { currSound = audio[i++]; // this covers case where we loaded an unplayable file type if (currSound.error) return; if (currSound.currentTime === 0 || currSound.currentTime === currSound.duration) { currSound.currentTime = 0; currSound.loop = !!loop; i = howMany; return currSound.play(); } } }; SoundEffectManager.prototype.play = function (soundName, loop) { if (this.support) { this._playWebAudio(soundName, loop); } else { return this._playWavAudio(soundName, loop); } }; SoundEffectManager.prototype.stop = function (soundName) { if (this.support) { // TODO: this } else { var soundArray = this.sounds[soundName], howMany = soundArray && soundArray.length || 0, i = 0, currSound; while (i < howMany) { currSound = soundArray[i++]; currSound.pause(); currSound.currentTime = 0; } } }; // attach to window or export with commonJS if (typeof module !== "undefined") { module.exports = SoundEffectManager; } else if (typeof root.define === "function" && define.amd) { root.define(SoundEffectManager); } else { root.SoundEffectManager = SoundEffectManager; } })();