/// /** * Phaser - Sound * * A Sound file, used by the Game.SoundManager for playback. */ var Phaser; (function (Phaser) { var Sound = (function () { /** * Sound constructor * @param [volume] {number} volume of this sound when playing. * @param [loop] {bool} loop this sound when playing? (Default to false) */ function Sound(game, key, volume, loop) { if (typeof volume === "undefined") { volume = 1; } if (typeof loop === "undefined") { loop = false; } /** * Reference to AudioContext instance. */ this.context = null; /** * Decoded data buffer / Audio tag. */ this._buffer = null; this._muted = false; this.usingWebAudio = false; this.usingAudioTag = false; this.name = ''; this.autoplay = false; this.totalDuration = 0; this.startTime = 0; this.currentTime = 0; this.duration = 0; this.stopTime = 0; this.paused = false; this.loop = false; this.isPlaying = false; this.currentMarker = ''; this.pendingPlayback = false; this.override = false; this.game = game; this.usingWebAudio = this.game.sound.usingWebAudio; this.usingAudioTag = this.game.sound.usingAudioTag; this.key = key; if(this.usingWebAudio) { this.context = this.game.sound.context; this.masterGainNode = this.game.sound.masterGain; if(typeof this.context.createGain === 'undefined') { this.gainNode = this.context.createGainNode(); } else { this.gainNode = this.context.createGain(); } this.gainNode.gain.value = volume * this.game.sound.volume; this.gainNode.connect(this.masterGainNode); } else { if(this.game.cache.getSound(key) && this.game.cache.getSound(key).locked == false) { this._sound = this.game.cache.getSoundData(key); this.totalDuration = this._sound.duration; } else { this.game.cache.onSoundUnlock.add(this.soundHasUnlocked, this); } } this._volume = volume; this.loop = loop; this.markers = { }; this.onDecoded = new Phaser.Signal(); this.onPlay = new Phaser.Signal(); this.onPause = new Phaser.Signal(); this.onResume = new Phaser.Signal(); this.onLoop = new Phaser.Signal(); this.onStop = new Phaser.Signal(); this.onMute = new Phaser.Signal(); this.onMarkerComplete = new Phaser.Signal(); } Sound.prototype.soundHasUnlocked = function (key) { if(key == this.key) { this._sound = this.game.cache.getSoundData(this.key); this.totalDuration = this._sound.duration; //console.log('sound has unlocked', this._sound); } }; Object.defineProperty(Sound.prototype, "isDecoding", { get: function () { return this.game.cache.getSound(this.key).isDecoding; }, enumerable: true, configurable: true }); Object.defineProperty(Sound.prototype, "isDecoded", { get: function () { return this.game.cache.isSoundDecoded(this.key); }, enumerable: true, configurable: true }); Sound.prototype.addMarker = function (name, start, stop, volume, loop) { if (typeof volume === "undefined") { volume = 1; } if (typeof loop === "undefined") { loop = false; } this.markers[name] = { name: name, start: start, stop: stop, volume: volume, duration: stop - start, loop: loop }; }; Sound.prototype.removeMarker = function (name) { delete this.markers[name]; }; Sound.prototype.update = function () { if(this.pendingPlayback && this.game.cache.isSoundReady(this.key)) { this.pendingPlayback = false; this.play(this._tempMarker, this._tempPosition, this._tempVolume, this._tempLoop); } if(this.isPlaying) { this.currentTime = this.game.time.now - this.startTime; if(this.currentTime >= this.duration) { //console.log(this.currentMarker, 'has hit duration'); if(this.usingWebAudio) { if(this.loop) { //console.log('loop1'); // won't work with markers, needs to reset the position this.onLoop.dispatch(this); if(this.currentMarker == '') { //console.log('loop2'); this.currentTime = 0; this.startTime = this.game.time.now; } else { //console.log('loop3'); this.play(this.currentMarker, 0, this.volume, true, true); } } else { //console.log('stopping, no loop for marker'); this.stop(); } } else { if(this.loop) { this.onLoop.dispatch(this); this.play(this.currentMarker, 0, this.volume, true, true); } else { this.stop(); } } } } }; Sound.prototype.play = /** * Play this sound, or a marked section of it. * @param marker {string} Assets key of the sound you want to play. * @param [volume] {number} volume of the sound you want to play. * @param [loop] {bool} loop when it finished playing? (Default to false) * @return {Sound} The playing sound object. */ function (marker, position, volume, loop, forceRestart) { if (typeof marker === "undefined") { marker = ''; } if (typeof position === "undefined") { position = 0; } if (typeof volume === "undefined") { volume = 1; } if (typeof loop === "undefined") { loop = false; } if (typeof forceRestart === "undefined") { forceRestart = false; } //console.log('play', marker, 'current is', this.currentMarker); if(this.isPlaying == true && forceRestart == false && this.override == false) { // Use Restart instead return; } if(this.isPlaying && this.override) { //console.log('asked to play', marker, 'but already playing', this.currentMarker); if(this.usingWebAudio) { if(typeof this._sound.stop === 'undefined') { this._sound.noteOff(0); } else { this._sound.stop(0); } } else if(this.usingAudioTag) { this._sound.pause(); this._sound.currentTime = 0; } } this.currentMarker = marker; if(marker !== '' && this.markers[marker]) { this.position = this.markers[marker].start; this.volume = this.markers[marker].volume; this.loop = this.markers[marker].loop; this.duration = this.markers[marker].duration * 1000; //console.log('marker info loaded', this.loop, this.duration); this._tempMarker = marker; this._tempPosition = this.position; this._tempVolume = this.volume; this._tempLoop = this.loop; } else { this.position = position; this.volume = volume; this.loop = loop; this.duration = 0; this._tempMarker = marker; this._tempPosition = position; this._tempVolume = volume; this._tempLoop = loop; } if(this.usingWebAudio) { // Does the sound need decoding? if(this.game.cache.isSoundDecoded(this.key)) { // Do we need to do this every time we play? How about just if the buffer is empty? if(this._buffer == null) { this._buffer = this.game.cache.getSoundData(this.key); } //if (this._sound == null) //{ this._sound = this.context.createBufferSource(); this._sound.buffer = this._buffer; this._sound.connect(this.gainNode); this.totalDuration = this._sound.buffer.duration; //} if(this.duration == 0) { this.duration = this.totalDuration * 1000; } if(this.loop && marker == '') { this._sound.loop = true; } // Useful to cache this somewhere perhaps? if(typeof this._sound.start === 'undefined') { this._sound.noteGrainOn(0, this.position, this.duration / 1000); //this._sound.noteOn(0); // the zero is vitally important, crashes iOS6 without it } else { this._sound.start(0, this.position, this.duration / 1000); } this.isPlaying = true; this.startTime = this.game.time.now; this.currentTime = 0; this.stopTime = this.startTime + this.duration; this.onPlay.dispatch(this); //console.log('playing, start', this.startTime, 'stop'); } else { this.pendingPlayback = true; if(this.game.cache.getSound(this.key) && this.game.cache.getSound(this.key).isDecoding == false) { this.game.sound.decode(this.key, this); } } } else { //console.log('Sound play Audio'); if(this.game.cache.getSound(this.key) && this.game.cache.getSound(this.key).locked) { //console.log('tried playing locked sound, pending set, reload started'); this.game.cache.reloadSound(this.key); this.pendingPlayback = true; } else { //console.log('sound not locked, state?', this._sound.readyState); if(this._sound && this._sound.readyState == 4) { if(this.duration == 0) { this.duration = this.totalDuration * 1000; } //console.log('playing', this._sound); this._sound.currentTime = this.position; this._sound.muted = this._muted; if(this._muted) { this._sound.volume = 0; } else { this._sound.volume = this._volume; } this._sound.play(); this.isPlaying = true; this.startTime = this.game.time.now; this.currentTime = 0; this.stopTime = this.startTime + this.duration; this.onPlay.dispatch(this); } else { this.pendingPlayback = true; } } } }; Sound.prototype.restart = function (marker, position, volume, loop) { if (typeof marker === "undefined") { marker = ''; } if (typeof position === "undefined") { position = 0; } if (typeof volume === "undefined") { volume = 1; } if (typeof loop === "undefined") { loop = false; } this.play(marker, position, volume, loop, true); }; Sound.prototype.pause = function () { if(this.isPlaying && this._sound) { this.stop(); this.isPlaying = false; this.paused = true; this.onPause.dispatch(this); } }; Sound.prototype.resume = function () { if(this.paused && this._sound) { if(this.usingWebAudio) { if(typeof this._sound.start === 'undefined') { this._sound.noteGrainOn(0, this.position, this.duration); //this._sound.noteOn(0); // the zero is vitally important, crashes iOS6 without it } else { this._sound.start(0, this.position, this.duration); } } else { this._sound.play(); } this.isPlaying = true; this.paused = false; this.onResume.dispatch(this); } }; Sound.prototype.stop = /** * Stop playing this sound. */ function () { if(this.isPlaying && this._sound) { if(this.usingWebAudio) { if(typeof this._sound.stop === 'undefined') { this._sound.noteOff(0); } else { this._sound.stop(0); } } else if(this.usingAudioTag) { this._sound.pause(); this._sound.currentTime = 0; } } this.isPlaying = false; var prevMarker = this.currentMarker; this.currentMarker = ''; this.onStop.dispatch(this, prevMarker); }; Object.defineProperty(Sound.prototype, "mute", { get: /** * Mute sounds. */ function () { return this._muted; }, set: function (value) { if(value) { this._muted = true; if(this.usingWebAudio) { this._muteVolume = this.gainNode.gain.value; this.gainNode.gain.value = 0; } else if(this.usingAudioTag && this._sound) { this._muteVolume = this._sound.volume; this._sound.volume = 0; } } else { this._muted = false; if(this.usingWebAudio) { this.gainNode.gain.value = this._muteVolume; } else if(this.usingAudioTag && this._sound) { this._sound.volume = this._muteVolume; } } this.onMute.dispatch(this); }, enumerable: true, configurable: true }); Object.defineProperty(Sound.prototype, "volume", { get: function () { return this._volume; }, set: function (value) { this._volume = value; if(this.usingWebAudio) { this.gainNode.gain.value = value; } else if(this.usingAudioTag && this._sound) { this._sound.volume = value; } }, enumerable: true, configurable: true }); return Sound; })(); Phaser.Sound = Sound; })(Phaser || (Phaser = {}));