|
1 | 1 | var Class = require('../../utils/Class'); |
2 | 2 | var BaseSound = require('../BaseSound'); |
3 | | -var SoundEvent = require('../SoundEvent'); |
4 | | -var SoundValueEvent = require('../SoundValueEvent'); |
5 | 3 | var HTML5AudioSound = new Class({ |
6 | 4 | Extends: BaseSound, |
7 | 5 | initialize: function HTML5AudioSound(manager, key, config) { |
8 | 6 | if (config === void 0) { config = {}; } |
9 | 7 | /** |
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. |
| 8 | + * Reference to HTML5 Audio tag used for playing sound. |
24 | 9 | * |
25 | 10 | * @private |
26 | 11 | * @property {HTMLAudioElement} audio |
27 | 12 | * @default null |
28 | 13 | */ |
29 | 14 | 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; |
51 | 15 | 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 | | - } |
314 | 16 | } |
315 | 17 | }); |
316 | 18 | module.exports = HTML5AudioSound; |
0 commit comments