Skip to content

Commit 15562a7

Browse files
Updated override property docs
1 parent ef60c16 commit 15562a7

1 file changed

Lines changed: 299 additions & 1 deletion

File tree

src/sound/html5/HTML5AudioSound.js

Lines changed: 299 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,316 @@
11
var Class = require('../../utils/Class');
22
var BaseSound = require('../BaseSound');
3+
var SoundEvent = require('../SoundEvent');
4+
var SoundValueEvent = require('../SoundValueEvent');
35
var HTML5AudioSound = new Class({
46
Extends: BaseSound,
57
initialize: function HTML5AudioSound(manager, key, config) {
68
if (config === void 0) { config = {}; }
79
/**
8-
* Reference to HTML5 Audio tag used for playing sound.
10+
* An array containing all HTML5 Audio tags that could be used for individual
11+
* sound's playback. Number of instances depends on the config value passed
12+
* to the Loader#audio method call, default is 1.
13+
*
14+
* @private
15+
* @property {HTMLAudioElement[]} tags
16+
*/
17+
this.tags = manager.game.cache.audio.get(key);
18+
if (!this.tags) {
19+
console.error('No audio loaded in cache with key: \'' + key + '\'!');
20+
return;
21+
}
22+
/**
23+
* Reference to an HTML5 Audio tag used for playing sound.
924
*
1025
* @private
1126
* @property {HTMLAudioElement} audio
1227
* @default null
1328
*/
1429
this.audio = null;
30+
/**
31+
* Audio tag's playback position recorded on previous
32+
* update method call. Set to 0 if sound is not playing.
33+
*
34+
* @private
35+
* @property {number} previousTime
36+
* @default 0
37+
*/
38+
this.previousTime = 0;
39+
/**
40+
* Timestamp as generated by the Request Animation Frame or SetTimeout
41+
* representing the time at which the delayed sound playback should start.
42+
* Set to 0 if sound playback is not delayed.
43+
*
44+
* @private
45+
* @property {number} startTime
46+
* @default 0
47+
*/
48+
this.startTime = 0;
49+
this.duration = this.tags[0].duration;
50+
this.totalDuration = this.tags[0].duration;
1551
BaseSound.call(this, manager, key, config);
52+
},
53+
play: function (markerName, config) {
54+
if (!BaseSound.prototype.play.call(this, markerName, config)) {
55+
return false;
56+
}
57+
// \/\/\/ isPlaying = true, isPaused = false \/\/\/
58+
if (!this.pickAndPlayAudioTag()) {
59+
return false;
60+
}
61+
this.events.dispatch(new SoundEvent(this, 'SOUND_PLAY'));
62+
return true;
63+
},
64+
pause: function () {
65+
if (this.startTime > 0) {
66+
return false;
67+
}
68+
if (!BaseSound.prototype.pause.call(this)) {
69+
return false;
70+
}
71+
// \/\/\/ isPlaying = false, isPaused = true \/\/\/
72+
this.currentConfig.seek = this.audio.currentTime
73+
- (this.currentMarker ? this.currentMarker.start : 0);
74+
this.stopAndReleaseAudioTag();
75+
this.events.dispatch(new SoundEvent(this, 'SOUND_PAUSE'));
76+
return true;
77+
},
78+
resume: function () {
79+
if (this.startTime > 0) {
80+
return false;
81+
}
82+
if (!BaseSound.prototype.resume.call(this)) {
83+
return false;
84+
}
85+
// \/\/\/ isPlaying = true, isPaused = false \/\/\/
86+
if (!this.pickAndPlayAudioTag()) {
87+
return false;
88+
}
89+
this.events.dispatch(new SoundEvent(this, 'SOUND_RESUME'));
90+
return true;
91+
},
92+
stop: function () {
93+
if (!BaseSound.prototype.stop.call(this)) {
94+
return false;
95+
}
96+
// \/\/\/ isPlaying = false, isPaused = false \/\/\/
97+
this.stopAndReleaseAudioTag();
98+
this.events.dispatch(new SoundEvent(this, 'SOUND_STOP'));
99+
return true;
100+
},
101+
pickAndPlayAudioTag: function () {
102+
if (!this.pickAudioTag()) {
103+
this.reset();
104+
return false;
105+
}
106+
var seek = this.currentConfig.seek;
107+
var delay = this.currentConfig.delay;
108+
var offset = (this.currentMarker ? this.currentMarker.start : 0) + seek;
109+
this.previousTime =
110+
this.audio.currentTime = offset;
111+
this.applyConfig();
112+
if (delay === 0) {
113+
this.startTime = 0;
114+
if (this.audio.paused) {
115+
this.audio.play();
116+
}
117+
}
118+
else {
119+
this.startTime = window.performance.now() + delay;
120+
if (!this.audio.paused) {
121+
this.audio.pause();
122+
}
123+
}
124+
this.resetConfig();
125+
return true;
126+
},
127+
pickAudioTag: function () {
128+
if (!this.audio) {
129+
for (var i = 0; i < this.tags.length; i++) {
130+
var audio = this.tags[i];
131+
if (audio.dataset.used === 'false') {
132+
audio.dataset.used = 'true';
133+
this.audio = audio;
134+
return true;
135+
}
136+
}
137+
if (!this.manager.override) {
138+
return false;
139+
}
140+
var otherSounds_1 = [];
141+
this.manager.forEachActiveSound(function (sound) {
142+
if (sound.key === this.key && sound.isPlaying) {
143+
otherSounds_1.push(sound);
144+
}
145+
});
146+
otherSounds_1.sort(function (a1, a2) {
147+
if (a1.loop === a2.loop) {
148+
return a2.seek - a1.seek;
149+
}
150+
return a1.loop ? 1 : -1;
151+
});
152+
var selectedSound = otherSounds_1[0];
153+
this.audio = selectedSound.audio;
154+
selectedSound.reset();
155+
selectedSound.audio = null;
156+
selectedSound.previousTime = 0;
157+
selectedSound.startTime = 0;
158+
}
159+
return true;
160+
},
161+
stopAndReleaseAudioTag: function () {
162+
this.audio.pause();
163+
this.audio.dataset.used = 'false';
164+
this.audio = null;
165+
this.previousTime = 0;
166+
this.startTime = 0;
167+
},
168+
reset: function () {
169+
BaseSound.prototype.stop.call(this);
170+
},
171+
update: function (time, delta) {
172+
// TODO include play method call delay
173+
if (this.isPlaying) {
174+
// handling delayed playback
175+
if (this.startTime > 0) {
176+
if (this.startTime < time) {
177+
this.previousTime =
178+
this.audio.currentTime += (time - this.startTime) / 1000;
179+
this.startTime = 0;
180+
this.audio.play();
181+
}
182+
return;
183+
}
184+
// handle looping and ending
185+
var startTime = (this.currentMarker ? this.currentMarker.start : 0);
186+
var endTime = startTime + this.duration;
187+
var currentTime = this.audio.currentTime;
188+
if (currentTime >= endTime) {
189+
if (this.currentConfig.loop) {
190+
currentTime =
191+
this.audio.currentTime = startTime + (currentTime - endTime);
192+
}
193+
else {
194+
this.reset();
195+
this.stopAndReleaseAudioTag();
196+
this.events.dispatch(new SoundEvent(this, 'SOUND_ENDED'));
197+
return;
198+
}
199+
}
200+
else if (currentTime < startTime) {
201+
currentTime =
202+
this.audio.currentTime += startTime;
203+
}
204+
if (currentTime < this.previousTime) {
205+
this.events.dispatch(new SoundEvent(this, 'SOUND_LOOP'));
206+
}
207+
this.previousTime = currentTime;
208+
}
209+
},
210+
destroy: function () {
211+
BaseSound.prototype.destroy.call(this);
212+
// TODO release all HTML5 Audio tag related stuff
213+
},
214+
setMute: function () {
215+
if (this.audio) {
216+
this.audio.muted = this.currentConfig.mute || this.manager.mute;
217+
}
218+
},
219+
setVolume: function () {
220+
if (this.audio) {
221+
this.audio.volume = this.currentConfig.volume * this.manager.volume;
222+
}
223+
},
224+
setRate: function () {
225+
BaseSound.prototype.setRate.call(this);
226+
if (this.audio) {
227+
this.audio.playbackRate = this.totalRate;
228+
}
229+
}
230+
});
231+
/**
232+
* Mute setting.
233+
*
234+
* @name Phaser.Sound.HTML5AudioSound#mute
235+
* @property {boolean} mute
236+
*/
237+
Object.defineProperty(HTML5AudioSound.prototype, 'mute', {
238+
get: function () {
239+
return this.currentConfig.mute;
240+
},
241+
set: function (value) {
242+
this.currentConfig.mute = value;
243+
this.setMute();
244+
this.events.dispatch(new SoundValueEvent(this, 'SOUND_MUTE', value));
245+
}
246+
});
247+
/**
248+
* Volume setting.
249+
*
250+
* @name Phaser.Sound.HTML5AudioSound#volume
251+
* @property {number} volume
252+
*/
253+
Object.defineProperty(HTML5AudioSound.prototype, 'volume', {
254+
get: function () {
255+
return this.currentConfig.volume;
256+
},
257+
set: function (value) {
258+
this.currentConfig.volume = value;
259+
this.setVolume();
260+
this.events.dispatch(new SoundValueEvent(this, 'SOUND_VOLUME', value));
261+
}
262+
});
263+
/**
264+
* Current position of playing sound.
265+
*
266+
* @name Phaser.Sound.HTML5AudioSound#seek
267+
* @property {number} seek
268+
*/
269+
Object.defineProperty(HTML5AudioSound.prototype, 'seek', {
270+
get: function () {
271+
if (this.isPlaying) {
272+
return this.audio.currentTime;
273+
}
274+
else if (this.isPaused) {
275+
return this.currentConfig.seek;
276+
}
277+
else {
278+
return 0;
279+
}
280+
},
281+
set: function (value) {
282+
if (this.startTime > 0) {
283+
return;
284+
}
285+
if (this.isPlaying || this.isPaused) {
286+
value = Math.min(Math.max(0, value), this.duration);
287+
if (this.isPlaying) {
288+
this.previousTime =
289+
this.audio.currentTime = value;
290+
}
291+
else if (this.isPaused) {
292+
this.currentConfig.seek = value;
293+
}
294+
this.events.dispatch(new SoundValueEvent(this, 'SOUND_SEEK', value));
295+
}
296+
}
297+
});
298+
/**
299+
* Property indicating whether or not
300+
* the sound or current sound marker will loop.
301+
*
302+
* @name Phaser.Sound.HTML5AudioSound#loop
303+
* @property {boolean} loop
304+
*/
305+
Object.defineProperty(HTML5AudioSound.prototype, 'loop', {
306+
get: function () {
307+
return this.currentConfig.loop;
308+
},
309+
set: function (value) {
310+
this.currentConfig.loop = value;
311+
if (this.audio) {
312+
this.audio.loop = value;
313+
}
16314
}
17315
});
18316
module.exports = HTML5AudioSound;

0 commit comments

Comments
 (0)