@roomrtc/mediaserver
Version:
A simple media server for RoomRTC
156 lines (133 loc) • 5.24 kB
JavaScript
angular.module('videoconference').factory('SoundEffectManager', function () {
return (function () {
function SoundEffectManager() {
this.AudioContext = window.AudioContext || window.webkitAudioContext;
this.support = !!this.AudioContext;
if (this.support) {
this.context = new this.AudioContext();
}
this.sounds = {};
this.sources = {};
}
// async load a file at a given URL, store it as 'name'.
SoundEffectManager.prototype.loadFile = function (url, name, delay, cb) {
if (this.support) {
this._loadWebAudioFile(url, name, delay, cb);
} else {
this._loadWaveFile(url.replace('.mp3', '.wav'), name, delay, 3, cb);
}
};
// async load a file at a given URL, store it as 'name'.
SoundEffectManager.prototype._loadWebAudioFile = function (url, name, delay, cb) {
if (!this.support) {
return;
}
var self = this;
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
request.onload = function () {
self.context.decodeAudioData(request.response,
function (data) { // Success
self.sounds[name] = data;
if (cb) {
cb(null, data);
}
},
function (err) { // Error
if (cb) {
cb(err);
}
}
);
};
setTimeout(function () {
request.send();
}, delay || 0);
};
SoundEffectManager.prototype._loadWaveFile = function (url, name, delay, multiplexLimit, cb) {
var self = this;
var limit = multiplexLimit || 3;
setTimeout(function () {
var a, i = 0;
self.sounds[name] = [];
while (i < limit) {
a = new Audio();
a.src = url;
// for our callback
if (i === 0 && cb) {
a.addEventListener('canplaythrough', cb, false);
}
a.load();
self.sounds[name][i++] = a;
}
}, delay || 0);
};
SoundEffectManager.prototype._playWebAudio = function (soundName, loop) {
var buffer = this.sounds[soundName];
if (!buffer) {
return;
}
if (loop && this.sources[soundName]) {
// Only start the sound once if it's looping
return;
}
var source = this.context.createBufferSource();
source.buffer = buffer;
source.loop = loop;
source.connect(this.context.destination);
if (loop) {
this.sources[soundName] = source;
}
source.start(0);
};
SoundEffectManager.prototype._playWavAudio = function (soundName, loop) {
var audio = this.sounds[soundName];
var howMany = audio && audio.length || 0;
var i = 0;
var 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) {
if (this.sources[soundName]) {
this.sources[soundName].stop(0);
delete this.sources[soundName];
}
} else {
var soundArray = this.sounds[soundName];
var howMany = soundArray && soundArray.length || 0;
var i = 0;
var currSound;
while (i < howMany) {
currSound = soundArray[i++];
currSound.pause();
currSound.currentTime = 0;
}
}
};
return SoundEffectManager;
})();
});