audio-manager
Advanced tools
Comparing version 0.1.13 to 0.1.14
@@ -111,3 +111,10 @@ //▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | ||
sound.fade = defaultFade; | ||
sound.play(volume * self.volume, pan, pitch); // load and play | ||
sound.load(function onSoundLoad(error) { | ||
if (error) { | ||
sound.unload(); | ||
self.loopSound = null; | ||
return; | ||
} | ||
sound.play(volume * self.volume, pan, pitch); | ||
}); | ||
} | ||
@@ -127,5 +134,9 @@ | ||
} | ||
this.nextLoop = audioManager.createSound(soundId); | ||
this.nextLoop = audioManager.createSound(soundId, this.id); | ||
this.nextLoop.load(function onSoundLoad(error) { | ||
if (error) return; | ||
if (error) { | ||
self.nextLoop.unload(); | ||
self.nextLoop = null; | ||
return; | ||
} | ||
stopCurrentLoop(this.loopSound); | ||
@@ -136,5 +147,5 @@ playNextSound(); | ||
} else { | ||
this.nextLoop = audioManager.createSound(soundId); | ||
this.nextLoop = audioManager.createSound(soundId, this.id); | ||
stopCurrentLoop(this.loopSound, playNextSound); | ||
} | ||
}; |
45
index.js
@@ -6,2 +6,3 @@ var AudioContext = window.AudioContext || window.webkitAudioContext; | ||
var AudioChannel = require('./AudioChannel.js'); | ||
var ISound = require('./ISound.js'); | ||
@@ -13,3 +14,3 @@ if (!AudioContext) { | ||
console.warn('HTML5 <Audio> is not supported on this platform. Sound features are unavailable.'); | ||
SoundObject = require('./ISound.js'); | ||
SoundObject = ISound; | ||
} | ||
@@ -47,3 +48,4 @@ } | ||
crossFading: false, | ||
getFileUri: function getFileUri(audioPath, id) { return audioPath + id + '.mp3'; } | ||
getFileUri: function getFileUri(audioPath, id) { return audioPath + id + '.mp3'; }, | ||
getSoundConstructor: function getSoundConstructor(channelId, soundId) { return null; } | ||
}; | ||
@@ -58,3 +60,3 @@ | ||
// register self | ||
SoundObject.prototype.audioManager = this; | ||
ISound.prototype.audioManager = this; | ||
SoundGroup.prototype.audioManager = this; | ||
@@ -66,3 +68,6 @@ AudioChannel.prototype.audioManager = this; | ||
// expose ISound for custom sound constructors | ||
module.exports.ISound = ISound; | ||
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | ||
@@ -86,5 +91,19 @@ /** Initialise audio. | ||
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | ||
/** Get a unused sound object (or a new one if no more empty sounds are available in pool) */ | ||
AudioManager.prototype.getEmptySound = function () { | ||
/** Get a unused sound object (or a new one if no more empty sounds are available in pool) | ||
* | ||
* @param {string} channelId - channel id where the sound will be used | ||
* @param {string} soundId - sound id | ||
* | ||
* @return {Object} sound object | ||
*/ | ||
AudioManager.prototype.getEmptySound = function (channelId, soundId) { | ||
var sound; | ||
// custom sound constructor | ||
var constructor = this.settings.getSoundConstructor(channelId, soundId); | ||
if (constructor) { | ||
sound = new constructor(); | ||
return sound; | ||
} | ||
if (this.freeSoundPool.length > 0) { | ||
@@ -152,6 +171,6 @@ sound = this.freeSoundPool.pop(); | ||
*/ | ||
AudioManager.prototype.createSound = function (id) { | ||
AudioManager.prototype.createSound = function (id, channelId) { | ||
var sound = this.getSound(id); | ||
if (sound) return sound; | ||
sound = this.soundsById[id] = this.getEmptySound(); | ||
sound = this.soundsById[id] = this.getEmptySound(channelId, id); | ||
sound.setId(id); | ||
@@ -166,3 +185,3 @@ return sound; | ||
*/ | ||
AudioManager.prototype.createSoundPermanent = function (id) { | ||
AudioManager.prototype.createSoundPermanent = function (id, channelId) { | ||
var sound = this.getSound(id); | ||
@@ -172,3 +191,5 @@ // TODO: Check if sound is permanent and move it to permanents list if it's not the case. | ||
if (sound) return sound; | ||
sound = this.permanentSounds[id] = new SoundObject(); | ||
var constructor = this.settings.getSoundConstructor(channelId, id) || SoundObject; | ||
sound = this.permanentSounds[id] = new constructor(); | ||
sound.setId(id); | ||
@@ -248,3 +269,5 @@ return sound; | ||
sound.unload(); | ||
this.freeSoundPool.push(sound); | ||
// don't add freed sound in pool if it's created from a custom constructor | ||
if (sound instanceof SoundObject) this.freeSoundPool.push(sound); | ||
}; | ||
@@ -361,3 +384,3 @@ | ||
var sound = this.getSound(soundId); | ||
if (!sound) { sound = this.createSound(soundId); } | ||
if (!sound) { sound = this.createSound(soundId, channelId); } | ||
volume = volume || 1.0; | ||
@@ -364,0 +387,0 @@ sound.play(channel.volume * volume, pan, pitch); |
113
ISound.js
@@ -36,5 +36,2 @@ //▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | ||
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | ||
ISound.prototype.init = function () { /* virtual function */ }; | ||
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | ||
ISound.prototype.setId = function (value) { | ||
@@ -46,31 +43,2 @@ this.id = value; | ||
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | ||
ISound.prototype.setVolume = function (value) { | ||
this.volume = value; | ||
}; | ||
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | ||
ISound.prototype.setPan = function (value) { | ||
this.pan = value; | ||
}; | ||
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | ||
ISound.prototype.setLoop = function (value) { | ||
this.loop = value; | ||
}; | ||
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | ||
ISound.prototype.setPitch = function (pitch) { | ||
this.pitch = pitch; | ||
}; | ||
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | ||
/** Load sound. Abstract method to be overwritten | ||
* @private | ||
*/ | ||
ISound.prototype._load = function () { | ||
console.log('ISound load call: ' + this.id); | ||
return this._finalizeLoad(null); | ||
}; | ||
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | ||
/** Load sound | ||
@@ -120,26 +88,2 @@ * | ||
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | ||
/** Unload sound from memory */ | ||
ISound.prototype.unload = function () { | ||
this._playTriggered = 0; | ||
this.setLoop(false); | ||
this.fade = 0; | ||
this.pitch = 0; | ||
this.stop(); | ||
if (this._loading) { | ||
this._unloading = true; | ||
return false; | ||
} | ||
this.audioManager.usedMemory -= this.usedMemory; | ||
this.setVolume(1.0); | ||
this.setPan(0.0); | ||
this.id = null; | ||
this._loaded = false; | ||
this.usedMemory = 0; | ||
return true; | ||
}; | ||
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | ||
/** Remove callback set on load */ | ||
@@ -168,8 +112,30 @@ ISound.prototype.cancelOnLoadCallbacks = function () { | ||
// prevent a looped sound to play twice | ||
// TODO: add a flag to allow force restart | ||
if (this.loop && this.playing) { | ||
// update pitch if needed | ||
this._updatePlayPitch(pitch); | ||
return; | ||
} | ||
this._play(pitch); | ||
}; | ||
//█████████████████████████████████████████████████████████████████████████████████ | ||
//████████████████████████████████████████▄███████▄░██████████▄░███████▄░██████████ | ||
//█▀▄▄▄▄▀█▄░▄██▄░▄█▀▄▄▄▄▀█▄░▀▄▄▄█▄░▀▄▄▄█▄▄░███▀▄▄▄▀░██▀▄▄▄▄▀███░▀▄▄▄▀███░███▀▄▄▄▄▀█ | ||
//█░████░███░██░███░▄▄▄▄▄██░██████░███████░███░████░██▀▄▄▄▄░███░████░███░███░▄▄▄▄▄█ | ||
//█▄▀▀▀▀▄████░░████▄▀▀▀▀▀█▀░▀▀▀██▀░▀▀▀██▀▀░▀▀█▄▀▀▀▄░▀█▄▀▀▀▄░▀█▀░▄▀▀▀▄█▀▀░▀▀█▄▀▀▀▀▀█ | ||
//█████████████████████████████████████████████████████████████████████████████████ | ||
ISound.prototype.init = function () { /* virtual function */ }; | ||
ISound.prototype.setVolume = function (value) { this.volume = value; }; | ||
ISound.prototype.setPan = function (value) { this.pan = value; }; | ||
ISound.prototype.setLoop = function (value) { this.loop = value; }; | ||
ISound.prototype.setPitch = function (pitch) { this.pitch = pitch; }; | ||
ISound.prototype._updatePlayPitch = function (pitch) { /* virtual */ }; | ||
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | ||
/** Play sound. Abstract method to be overwritten */ | ||
ISound.prototype._play = function () { | ||
ISound.prototype._play = function (pitch) { | ||
this.playing = true; | ||
@@ -188,1 +154,34 @@ console.log('ISound play call: "' + this.id + '"'); | ||
}; | ||
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | ||
/** Load sound. Abstract method to be overwritten | ||
* @private | ||
*/ | ||
ISound.prototype._load = function () { | ||
console.log('ISound load call: ' + this.id); | ||
return this._finalizeLoad(null); | ||
}; | ||
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | ||
/** Unload sound from memory */ | ||
ISound.prototype.unload = function () { | ||
this._playTriggered = 0; | ||
this.setLoop(false); | ||
this.fade = 0; | ||
this.pitch = 0; | ||
this.stop(); | ||
if (this._loading) { | ||
this._unloading = true; | ||
return false; | ||
} | ||
this.audioManager.usedMemory -= this.usedMemory; | ||
this.setVolume(1.0); | ||
this.setPan(0.0); | ||
this.id = null; | ||
this._loaded = false; | ||
this.usedMemory = 0; | ||
return true; | ||
}; |
{ | ||
"name": "audio-manager", | ||
"version": "0.1.13", | ||
"version": "0.1.14", | ||
"description": "Play sounds using Web Audio, fallback to HTML5 Audio", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -108,3 +108,3 @@ var inherits = require('util').inherits; | ||
*/ | ||
Sound.prototype._play = function () { | ||
Sound.prototype._play = function (pitch) { | ||
// TODO: sound pan | ||
@@ -111,0 +111,0 @@ // TODO: fade-in |
@@ -27,3 +27,3 @@ var inherits = require('util').inherits; | ||
this._playPitch = 0.0; | ||
this._playPitch = 0.0; // pitch for each independent play | ||
this._fadeTimeout = null; | ||
@@ -173,2 +173,10 @@ this._onStopCallback = null; | ||
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | ||
SoundBuffered.prototype._updatePlayPitch = function (pitch) { | ||
if ((pitch || pitch === 0) && pitch !== this._playPitch) { | ||
this._playPitch = pitch; | ||
this._setPlaybackRate(0); | ||
} | ||
}; | ||
//▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ | ||
SoundBuffered.prototype._setPlaybackRate = function (portamento) { | ||
@@ -279,13 +287,2 @@ if (!this.source) return; | ||
// prevent a looped sound to play twice | ||
// TODO: add a flag to allow force restart | ||
if (this.loop && this.playing) { | ||
// update pitch if needed | ||
if ((pitch || pitch === 0) && pitch !== this._playPitch) { | ||
this._playPitch = pitch; | ||
this._setPlaybackRate(0); | ||
} | ||
return; | ||
} | ||
this.playing = true; | ||
@@ -292,0 +289,0 @@ |
73421
1490