Add ability to pan sounds

This commit is contained in:
Pavel Kabakin 2020-08-26 04:11:53 +03:00
parent 912bed5820
commit 7c74b77fc0
7 changed files with 141 additions and 6 deletions

View file

@ -128,7 +128,8 @@ var BaseSound = new Class({
detune: 0, detune: 0,
seek: 0, seek: 0,
loop: false, loop: false,
delay: 0 delay: 0,
pan: 0
}; };
@ -217,7 +218,8 @@ var BaseSound = new Class({
detune: 0, detune: 0,
seek: 0, seek: 0,
loop: false, loop: false,
delay: 0 delay: 0,
pan: 0
} }
}, marker); }, marker);
@ -418,6 +420,7 @@ var BaseSound = new Class({
this.rate = this.currentConfig.rate; this.rate = this.currentConfig.rate;
this.detune = this.currentConfig.detune; this.detune = this.currentConfig.detune;
this.loop = this.currentConfig.loop; this.loop = this.currentConfig.loop;
this.pan = this.currentConfig.pan;
}, },
/** /**

View file

@ -0,0 +1,27 @@
/**
* @author pi-kei
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* The Sound Pan Event.
*
* This event is dispatched by both Web Audio and HTML5 Audio Sound objects when their pan changes.
*
* Listen to it from a Sound instance using `Sound.on('pan', listener)`, i.e.:
*
* ```javascript
* var sound = this.sound.add('key');
* sound.on('pan', listener);
* sound.play();
* sound.setPan(0.5);
* ```
*
* @event Phaser.Sound.Events#PAN
* @since 3.0.0
*
* @param {(Phaser.Sound.WebAudioSound|Phaser.Sound.HTML5AudioSound)} sound - A reference to the Sound that emitted the event.
* @param {number} pan - The new pan of the Sound.
*/
module.exports = 'pan';

View file

@ -32,6 +32,7 @@ module.exports = {
STOP_ALL: require('./STOP_ALL_EVENT'), STOP_ALL: require('./STOP_ALL_EVENT'),
STOP: require('./STOP_EVENT'), STOP: require('./STOP_EVENT'),
UNLOCKED: require('./UNLOCKED_EVENT'), UNLOCKED: require('./UNLOCKED_EVENT'),
VOLUME: require('./VOLUME_EVENT') VOLUME: require('./VOLUME_EVENT'),
PAN: require('./PAN_EVENT')
}; };

View file

@ -916,6 +916,49 @@ var HTML5AudioSound = new Class({
{ {
this.loop = value; this.loop = value;
return this;
},
/**
* Gets or sets the pan of this sound, a value between -1 (full left pan) and 1 (full right pan).
* Has no effect on HTML5 Audio Sound.
*
* @name Phaser.Sound.HTML5AudioSound#pan
* @type {number}
* @default 0
* @fires Phaser.Sound.Events#PAN
* @since 3.0.0
*/
pan: {
get: function ()
{
return this.currentConfig.pan;
},
set: function (value)
{
this.currentConfig.pan = value;
this.emit(Events.PAN, this, value);
}
},
/**
* Sets the pan of this Sound. Has no effect on HTML5 Audio Sound.
*
* @method Phaser.Sound.HTML5AudioSound#setPan
* @fires Phaser.Sound.Events#PAN
* @since 3.4.0
*
* @param {number} value - The pan of the sound.
*
* @return {Phaser.Sound.HTML5AudioSound} This Sound instance.
*/
setPan: function (value)
{
this.pan = value;
return this; return this;
} }

View file

@ -70,7 +70,8 @@ var NoAudioSound = new Class({
detune: 0, detune: 0,
seek: 0, seek: 0,
loop: false, loop: false,
delay: 0 delay: 0,
pan: 0
}, config); }, config);
this.currentConfig = this.config; this.currentConfig = this.config;
@ -80,6 +81,7 @@ var NoAudioSound = new Class({
this.detune = 0; this.detune = 0;
this.seek = 0; this.seek = 0;
this.loop = false; this.loop = false;
this.pan = 0;
this.markers = {}; this.markers = {};
this.currentMarker = null; this.currentMarker = null;
this.pendingRemove = false; this.pendingRemove = false;
@ -178,7 +180,9 @@ var NoAudioSound = new Class({
setSeek: returnThis, setSeek: returnThis,
setLoop: returnThis setLoop: returnThis,
setPan: returnThis
}); });

View file

@ -11,4 +11,5 @@
* @property {number} [seek=0] - Position of playback for this sound, in seconds. * @property {number} [seek=0] - Position of playback for this sound, in seconds.
* @property {boolean} [loop=false] - Whether or not the sound or current sound marker should loop. * @property {boolean} [loop=false] - Whether or not the sound or current sound marker should loop.
* @property {number} [delay=0] - Time, in seconds, that should elapse before the sound actually starts its playback. * @property {number} [delay=0] - Time, in seconds, that should elapse before the sound actually starts its playback.
* @property {number} [pan=0] - A value between -1 (full left pan) and 1 (full right pan). 0 means no pan.
*/ */

View file

@ -91,6 +91,15 @@ var WebAudioSound = new Class({
*/ */
this.volumeNode = manager.context.createGain(); this.volumeNode = manager.context.createGain();
/**
* Panner node responsible for controlling this sound's pan.
*
* @name Phaser.Sound.WebAudioSound#pannerNode
* @type {StereoPannerNode}
* @private
*/
this.pannerNode = manager.context.createStereoPanner();
/** /**
* The time at which the sound should have started playback from the beginning. * The time at which the sound should have started playback from the beginning.
* Based on BaseAudioContext.currentTime value. * Based on BaseAudioContext.currentTime value.
@ -165,7 +174,9 @@ var WebAudioSound = new Class({
this.muteNode.connect(this.volumeNode); this.muteNode.connect(this.volumeNode);
this.volumeNode.connect(manager.destination); this.volumeNode.connect(this.pannerNode);
this.pannerNode.connect(manager.destination);
this.duration = this.audioBuffer.duration; this.duration = this.audioBuffer.duration;
@ -493,6 +504,8 @@ var WebAudioSound = new Class({
this.muteNode = null; this.muteNode = null;
this.volumeNode.disconnect(); this.volumeNode.disconnect();
this.volumeNode = null; this.volumeNode = null;
this.pannerNode.disconnect();
this.pannerNode = null;
this.rateUpdates.length = 0; this.rateUpdates.length = 0;
this.rateUpdates = null; this.rateUpdates = null;
}, },
@ -892,6 +905,49 @@ var WebAudioSound = new Class({
{ {
this.loop = value; this.loop = value;
return this;
},
/**
* Gets or sets the pan of this sound, a value between -1 (full left pan) and 1 (full right pan).
*
* @name Phaser.Sound.WebAudioSound#pan
* @type {number}
* @default 0
* @fires Phaser.Sound.Events#PAN
* @since 3.0.0
*/
pan: {
get: function ()
{
return this.pannerNode.pan.value;
},
set: function (value)
{
this.currentConfig.pan = value;
this.pannerNode.pan.setValueAtTime(value, this.manager.context.currentTime);
this.emit(Events.PAN, this, value);
}
},
/**
* Sets the pan of this Sound.
*
* @method Phaser.Sound.WebAudioSound#setPan
* @fires Phaser.Sound.Events#PAN
* @since 3.4.0
*
* @param {number} value - The pan of the sound.
*
* @return {Phaser.Sound.WebAudioSound} This Sound instance.
*/
setPan: function (value)
{
this.pan = value;
return this; return this;
} }