Skip to content

Commit dde5b25

Browse files
authored
Merge pull request phaserjs#5274 from pi-kei/sound-panning
Add ability to pan sounds
2 parents 1d58620 + 7f2874c commit dde5b25

8 files changed

Lines changed: 182 additions & 5 deletions

File tree

src/sound/BaseSound.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,8 @@ var BaseSound = new Class({
128128
detune: 0,
129129
seek: 0,
130130
loop: false,
131-
delay: 0
131+
delay: 0,
132+
pan: 0
132133

133134
};
134135

@@ -217,7 +218,8 @@ var BaseSound = new Class({
217218
detune: 0,
218219
seek: 0,
219220
loop: false,
220-
delay: 0
221+
delay: 0,
222+
pan: 0
221223
}
222224
}, marker);
223225

@@ -418,6 +420,7 @@ var BaseSound = new Class({
418420
this.rate = this.currentConfig.rate;
419421
this.detune = this.currentConfig.detune;
420422
this.loop = this.currentConfig.loop;
423+
this.pan = this.currentConfig.pan;
421424
},
422425

423426
/**

src/sound/events/PAN_EVENT.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* @author pi-kei
3+
* @copyright 2020 Photon Storm Ltd.
4+
* @license {@link https://opensource.org/licenses/MIT|MIT License}
5+
*/
6+
7+
/**
8+
* The Sound Pan Event.
9+
*
10+
* This event is dispatched by both Web Audio and HTML5 Audio Sound objects when their pan changes.
11+
*
12+
* Listen to it from a Sound instance using `Sound.on('pan', listener)`, i.e.:
13+
*
14+
* ```javascript
15+
* var sound = this.sound.add('key');
16+
* sound.on('pan', listener);
17+
* sound.play();
18+
* sound.setPan(0.5);
19+
* ```
20+
*
21+
* @event Phaser.Sound.Events#PAN
22+
* @since 3.0.0
23+
*
24+
* @param {(Phaser.Sound.WebAudioSound|Phaser.Sound.HTML5AudioSound)} sound - A reference to the Sound that emitted the event.
25+
* @param {number} pan - The new pan of the Sound.
26+
*/
27+
module.exports = 'pan';

src/sound/events/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ module.exports = {
2222
LOOP: require('./LOOP_EVENT'),
2323
LOOPED: require('./LOOPED_EVENT'),
2424
MUTE: require('./MUTE_EVENT'),
25+
PAN: require('./PAN_EVENT'),
2526
PAUSE_ALL: require('./PAUSE_ALL_EVENT'),
2627
PAUSE: require('./PAUSE_EVENT'),
2728
PLAY: require('./PLAY_EVENT'),

src/sound/html5/HTML5AudioSound.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -916,6 +916,49 @@ var HTML5AudioSound = new Class({
916916
{
917917
this.loop = value;
918918

919+
return this;
920+
},
921+
922+
/**
923+
* Gets or sets the pan of this sound, a value between -1 (full left pan) and 1 (full right pan).
924+
* Has no effect on HTML5 Audio Sound.
925+
*
926+
* @name Phaser.Sound.HTML5AudioSound#pan
927+
* @type {number}
928+
* @default 0
929+
* @fires Phaser.Sound.Events#PAN
930+
* @since 3.0.0
931+
*/
932+
pan: {
933+
934+
get: function ()
935+
{
936+
return this.currentConfig.pan;
937+
},
938+
939+
set: function (value)
940+
{
941+
this.currentConfig.pan = value;
942+
943+
this.emit(Events.PAN, this, value);
944+
}
945+
},
946+
947+
/**
948+
* Sets the pan of this Sound. Has no effect on HTML5 Audio Sound.
949+
*
950+
* @method Phaser.Sound.HTML5AudioSound#setPan
951+
* @fires Phaser.Sound.Events#PAN
952+
* @since 3.4.0
953+
*
954+
* @param {number} value - The pan of the sound.
955+
*
956+
* @return {Phaser.Sound.HTML5AudioSound} This Sound instance.
957+
*/
958+
setPan: function (value)
959+
{
960+
this.pan = value;
961+
919962
return this;
920963
}
921964

src/sound/noaudio/NoAudioSound.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ var NoAudioSound = new Class({
7070
detune: 0,
7171
seek: 0,
7272
loop: false,
73-
delay: 0
73+
delay: 0,
74+
pan: 0
7475
}, config);
7576

7677
this.currentConfig = this.config;
@@ -80,6 +81,7 @@ var NoAudioSound = new Class({
8081
this.detune = 0;
8182
this.seek = 0;
8283
this.loop = false;
84+
this.pan = 0;
8385
this.markers = {};
8486
this.currentMarker = null;
8587
this.pendingRemove = false;
@@ -178,7 +180,9 @@ var NoAudioSound = new Class({
178180

179181
setSeek: returnThis,
180182

181-
setLoop: returnThis
183+
setLoop: returnThis,
184+
185+
setPan: returnThis
182186

183187
});
184188

src/sound/typedefs/SoundConfig.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@
1111
* @property {number} [seek=0] - Position of playback for this sound, in seconds.
1212
* @property {boolean} [loop=false] - Whether or not the sound or current sound marker should loop.
1313
* @property {number} [delay=0] - Time, in seconds, that should elapse before the sound actually starts its playback.
14+
* @property {number} [pan=0] - A value between -1 (full left pan) and 1 (full right pan). 0 means no pan.
1415
*/

src/sound/webaudio/WebAudioSound.js

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,15 @@ var WebAudioSound = new Class({
9191
*/
9292
this.volumeNode = manager.context.createGain();
9393

94+
/**
95+
* Panner node responsible for controlling this sound's pan.
96+
*
97+
* @name Phaser.Sound.WebAudioSound#pannerNode
98+
* @type {StereoPannerNode}
99+
* @private
100+
*/
101+
this.pannerNode = manager.context.createStereoPanner();
102+
94103
/**
95104
* The time at which the sound should have started playback from the beginning.
96105
* Based on BaseAudioContext.currentTime value.
@@ -165,7 +174,9 @@ var WebAudioSound = new Class({
165174

166175
this.muteNode.connect(this.volumeNode);
167176

168-
this.volumeNode.connect(manager.destination);
177+
this.volumeNode.connect(this.pannerNode);
178+
179+
this.pannerNode.connect(manager.destination);
169180

170181
this.duration = this.audioBuffer.duration;
171182

@@ -493,6 +504,8 @@ var WebAudioSound = new Class({
493504
this.muteNode = null;
494505
this.volumeNode.disconnect();
495506
this.volumeNode = null;
507+
this.pannerNode.disconnect();
508+
this.pannerNode = null;
496509
this.rateUpdates.length = 0;
497510
this.rateUpdates = null;
498511
},
@@ -892,6 +905,49 @@ var WebAudioSound = new Class({
892905
{
893906
this.loop = value;
894907

908+
return this;
909+
},
910+
911+
/**
912+
* Gets or sets the pan of this sound, a value between -1 (full left pan) and 1 (full right pan).
913+
*
914+
* @name Phaser.Sound.WebAudioSound#pan
915+
* @type {number}
916+
* @default 0
917+
* @fires Phaser.Sound.Events#PAN
918+
* @since 3.0.0
919+
*/
920+
pan: {
921+
922+
get: function ()
923+
{
924+
return this.pannerNode.pan.value;
925+
},
926+
927+
set: function (value)
928+
{
929+
this.currentConfig.pan = value;
930+
this.pannerNode.pan.setValueAtTime(value, this.manager.context.currentTime);
931+
932+
this.emit(Events.PAN, this, value);
933+
}
934+
},
935+
936+
/**
937+
* Sets the pan of this Sound.
938+
*
939+
* @method Phaser.Sound.WebAudioSound#setPan
940+
* @fires Phaser.Sound.Events#PAN
941+
* @since 3.4.0
942+
*
943+
* @param {number} value - The pan of the sound.
944+
*
945+
* @return {Phaser.Sound.WebAudioSound} This Sound instance.
946+
*/
947+
setPan: function (value)
948+
{
949+
this.pan = value;
950+
895951
return this;
896952
}
897953

types/phaser.d.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65371,6 +65371,10 @@ declare namespace Phaser {
6537165371
* Time, in seconds, that should elapse before the sound actually starts its playback.
6537265372
*/
6537365373
delay?: number;
65374+
/**
65375+
* A value between -1 (full left pan) and 1 (full right pan). 0 means no pan.
65376+
*/
65377+
pan?: number;
6537465378
};
6537565379

6537665380
/**
@@ -85691,6 +85695,22 @@ declare namespace Phaser {
8569185695
*/
8569285696
const MUTE: any;
8569385697

85698+
/**
85699+
* The Sound Pan Event.
85700+
*
85701+
* This event is dispatched by both Web Audio and HTML5 Audio Sound objects when their pan changes.
85702+
*
85703+
* Listen to it from a Sound instance using `Sound.on('pan', listener)`, i.e.:
85704+
*
85705+
* ```javascript
85706+
* var sound = this.sound.add('key');
85707+
* sound.on('pan', listener);
85708+
* sound.play();
85709+
* sound.setPan(0.5);
85710+
* ```
85711+
*/
85712+
const PAN: any;
85713+
8569485714
/**
8569585715
* The Pause All Sounds Event.
8569685716
*
@@ -85980,6 +86000,18 @@ declare namespace Phaser {
8598086000
*/
8598186001
setLoop(value: boolean): Phaser.Sound.HTML5AudioSound;
8598286002

86003+
/**
86004+
* Gets or sets the pan of this sound, a value between -1 (full left pan) and 1 (full right pan).
86005+
* Has no effect on HTML5 Audio Sound.
86006+
*/
86007+
pan: number;
86008+
86009+
/**
86010+
* Sets the pan of this Sound. Has no effect on HTML5 Audio Sound.
86011+
* @param value The pan of the sound.
86012+
*/
86013+
setPan(value: number): Phaser.Sound.HTML5AudioSound;
86014+
8598386015
}
8598486016

8598586017
/**
@@ -86302,6 +86334,16 @@ declare namespace Phaser {
8630286334
*/
8630386335
setLoop(value: boolean): Phaser.Sound.WebAudioSound;
8630486336

86337+
/**
86338+
* Gets or sets the pan of this sound, a value between -1 (full left pan) and 1 (full right pan).
86339+
*/
86340+
pan: number;
86341+
86342+
/**
86343+
* Sets the pan of this Sound.
86344+
* @param value The pan of the sound.
86345+
*/
86346+
setPan(value: number): Phaser.Sound.WebAudioSound;
8630586347
}
8630686348

8630786349
/**

0 commit comments

Comments
 (0)