@eva/plugin-sound 2.0.0-beta.2 → 2.0.0-beta.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/EVA.plugin.sound.js +1656 -223
- package/dist/EVA.plugin.sound.min.js +1 -1
- package/dist/plugin-sound.cjs.js +54 -227
- package/dist/plugin-sound.cjs.prod.js +3 -2
- package/dist/plugin-sound.d.ts +9 -28
- package/dist/plugin-sound.esm.js +54 -227
- package/package.json +5 -3
package/dist/EVA.plugin.sound.js
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
2
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
3
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
4
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
5
|
+
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
1
6
|
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
var _EVA_IIFE_sound = function (exports, eva_js) {
|
|
7
|
+
globalThis.EVA = globalThis.EVA || {};
|
|
8
|
+
globalThis.EVA.plugin = globalThis.EVA.plugin || {};
|
|
9
|
+
var _EVA_IIFE_sound = function (exports, eva_js, pixi_js) {
|
|
5
10
|
'use strict';
|
|
6
11
|
function __decorate(decorators, target, key, desc) {
|
|
7
12
|
var c = arguments.length,
|
|
@@ -37,69 +42,1637 @@ var _EVA_IIFE_sound = function (exports, eva_js) {
|
|
|
37
42
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
38
43
|
});
|
|
39
44
|
}
|
|
40
|
-
let
|
|
41
|
-
|
|
45
|
+
let instance;
|
|
46
|
+
function setInstance(sound) {
|
|
47
|
+
instance = sound;
|
|
48
|
+
return sound;
|
|
49
|
+
}
|
|
50
|
+
function getInstance() {
|
|
51
|
+
return instance;
|
|
52
|
+
}
|
|
53
|
+
class WebAudioUtils {
|
|
54
|
+
static setParamValue(param, value) {
|
|
55
|
+
if (param.setValueAtTime) {
|
|
56
|
+
const context = getInstance().context;
|
|
57
|
+
param.setValueAtTime(value, context.audioContext.currentTime);
|
|
58
|
+
} else {
|
|
59
|
+
param.value = value;
|
|
60
|
+
}
|
|
61
|
+
return value;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
class HTMLAudioContext extends pixi_js.EventEmitter {
|
|
65
|
+
constructor() {
|
|
66
|
+
super(...arguments);
|
|
67
|
+
this.speed = 1;
|
|
68
|
+
this.muted = false;
|
|
69
|
+
this.volume = 1;
|
|
70
|
+
this.paused = false;
|
|
71
|
+
}
|
|
72
|
+
refresh() {
|
|
73
|
+
this.emit("refresh");
|
|
74
|
+
}
|
|
75
|
+
refreshPaused() {
|
|
76
|
+
this.emit("refreshPaused");
|
|
77
|
+
}
|
|
78
|
+
get filters() {
|
|
79
|
+
console.warn("HTML Audio does not support filters");
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
set filters(_filters) {
|
|
83
|
+
console.warn("HTML Audio does not support filters");
|
|
84
|
+
}
|
|
85
|
+
get audioContext() {
|
|
86
|
+
console.warn("HTML Audio does not support audioContext");
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
toggleMute() {
|
|
90
|
+
this.muted = !this.muted;
|
|
91
|
+
this.refresh();
|
|
92
|
+
return this.muted;
|
|
93
|
+
}
|
|
94
|
+
togglePause() {
|
|
95
|
+
this.paused = !this.paused;
|
|
96
|
+
this.refreshPaused();
|
|
97
|
+
return this.paused;
|
|
98
|
+
}
|
|
99
|
+
destroy() {
|
|
100
|
+
this.removeAllListeners();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
let id$1 = 0;
|
|
104
|
+
const _HTMLAudioInstance = class extends pixi_js.EventEmitter {
|
|
105
|
+
constructor(parent) {
|
|
42
106
|
super();
|
|
43
|
-
this.
|
|
44
|
-
this.
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
this
|
|
48
|
-
|
|
107
|
+
this.id = id$1++;
|
|
108
|
+
this.init(parent);
|
|
109
|
+
}
|
|
110
|
+
set(name, value) {
|
|
111
|
+
if (this[name] === void 0) {
|
|
112
|
+
throw new Error(`Property with name ${name} does not exist.`);
|
|
113
|
+
} else {
|
|
114
|
+
switch (name) {
|
|
115
|
+
case "speed":
|
|
116
|
+
this.speed = value;
|
|
117
|
+
break;
|
|
118
|
+
case "volume":
|
|
119
|
+
this.volume = value;
|
|
120
|
+
break;
|
|
121
|
+
case "paused":
|
|
122
|
+
this.paused = value;
|
|
123
|
+
break;
|
|
124
|
+
case "loop":
|
|
125
|
+
this.loop = value;
|
|
126
|
+
break;
|
|
127
|
+
case "muted":
|
|
128
|
+
this.muted = value;
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return this;
|
|
133
|
+
}
|
|
134
|
+
get progress() {
|
|
135
|
+
const {
|
|
136
|
+
currentTime
|
|
137
|
+
} = this._source;
|
|
138
|
+
return currentTime / this._duration;
|
|
139
|
+
}
|
|
140
|
+
get paused() {
|
|
141
|
+
return this._paused;
|
|
142
|
+
}
|
|
143
|
+
set paused(paused) {
|
|
144
|
+
this._paused = paused;
|
|
145
|
+
this.refreshPaused();
|
|
146
|
+
}
|
|
147
|
+
_onPlay() {
|
|
148
|
+
this._playing = true;
|
|
149
|
+
}
|
|
150
|
+
_onPause() {
|
|
151
|
+
this._playing = false;
|
|
152
|
+
}
|
|
153
|
+
init(media) {
|
|
154
|
+
this._playing = false;
|
|
155
|
+
this._duration = media.source.duration;
|
|
156
|
+
const source = this._source = media.source.cloneNode(false);
|
|
157
|
+
source.src = media.parent.url;
|
|
158
|
+
source.onplay = this._onPlay.bind(this);
|
|
159
|
+
source.onpause = this._onPause.bind(this);
|
|
160
|
+
media.context.on("refresh", this.refresh, this);
|
|
161
|
+
media.context.on("refreshPaused", this.refreshPaused, this);
|
|
162
|
+
this._media = media;
|
|
163
|
+
}
|
|
164
|
+
_internalStop() {
|
|
165
|
+
if (this._source && this._playing) {
|
|
166
|
+
this._source.onended = null;
|
|
167
|
+
this._source.pause();
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
stop() {
|
|
171
|
+
this._internalStop();
|
|
172
|
+
if (this._source) {
|
|
173
|
+
this.emit("stop");
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
get speed() {
|
|
177
|
+
return this._speed;
|
|
178
|
+
}
|
|
179
|
+
set speed(speed) {
|
|
180
|
+
this._speed = speed;
|
|
181
|
+
this.refresh();
|
|
182
|
+
}
|
|
183
|
+
get volume() {
|
|
184
|
+
return this._volume;
|
|
185
|
+
}
|
|
186
|
+
set volume(volume) {
|
|
187
|
+
this._volume = volume;
|
|
188
|
+
this.refresh();
|
|
189
|
+
}
|
|
190
|
+
get loop() {
|
|
191
|
+
return this._loop;
|
|
192
|
+
}
|
|
193
|
+
set loop(loop) {
|
|
194
|
+
this._loop = loop;
|
|
195
|
+
this.refresh();
|
|
49
196
|
}
|
|
50
197
|
get muted() {
|
|
51
|
-
return this.
|
|
198
|
+
return this._muted;
|
|
52
199
|
}
|
|
53
|
-
set muted(
|
|
54
|
-
|
|
200
|
+
set muted(muted) {
|
|
201
|
+
this._muted = muted;
|
|
202
|
+
this.refresh();
|
|
203
|
+
}
|
|
204
|
+
get filters() {
|
|
205
|
+
console.warn("HTML Audio does not support filters");
|
|
206
|
+
return null;
|
|
207
|
+
}
|
|
208
|
+
set filters(_filters) {
|
|
209
|
+
console.warn("HTML Audio does not support filters");
|
|
210
|
+
}
|
|
211
|
+
refresh() {
|
|
212
|
+
const global = this._media.context;
|
|
213
|
+
const sound = this._media.parent;
|
|
214
|
+
this._source.loop = this._loop || sound.loop;
|
|
215
|
+
const globalVolume = global.volume * (global.muted ? 0 : 1);
|
|
216
|
+
const soundVolume = sound.volume * (sound.muted ? 0 : 1);
|
|
217
|
+
const instanceVolume = this._volume * (this._muted ? 0 : 1);
|
|
218
|
+
this._source.volume = instanceVolume * globalVolume * soundVolume;
|
|
219
|
+
this._source.playbackRate = this._speed * global.speed * sound.speed;
|
|
220
|
+
}
|
|
221
|
+
refreshPaused() {
|
|
222
|
+
const global = this._media.context;
|
|
223
|
+
const sound = this._media.parent;
|
|
224
|
+
const pausedReal = this._paused || sound.paused || global.paused;
|
|
225
|
+
if (pausedReal !== this._pausedReal) {
|
|
226
|
+
this._pausedReal = pausedReal;
|
|
227
|
+
if (pausedReal) {
|
|
228
|
+
this._internalStop();
|
|
229
|
+
this.emit("paused");
|
|
230
|
+
} else {
|
|
231
|
+
this.emit("resumed");
|
|
232
|
+
this.play({
|
|
233
|
+
start: this._source.currentTime,
|
|
234
|
+
end: this._end,
|
|
235
|
+
volume: this._volume,
|
|
236
|
+
speed: this._speed,
|
|
237
|
+
loop: this._loop
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
this.emit("pause", pausedReal);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
play(options) {
|
|
244
|
+
const {
|
|
245
|
+
start,
|
|
246
|
+
end,
|
|
247
|
+
speed,
|
|
248
|
+
loop,
|
|
249
|
+
volume,
|
|
250
|
+
muted
|
|
251
|
+
} = options;
|
|
252
|
+
if (end) {
|
|
253
|
+
console.assert(end > start, "End time is before start time");
|
|
254
|
+
}
|
|
255
|
+
this._speed = speed;
|
|
256
|
+
this._volume = volume;
|
|
257
|
+
this._loop = !!loop;
|
|
258
|
+
this._muted = muted;
|
|
259
|
+
this.refresh();
|
|
260
|
+
if (this.loop && end !== null) {
|
|
261
|
+
console.warn('Looping not support when specifying an "end" time');
|
|
262
|
+
this.loop = false;
|
|
263
|
+
}
|
|
264
|
+
this._start = start;
|
|
265
|
+
this._end = end || this._duration;
|
|
266
|
+
this._start = Math.max(0, this._start - _HTMLAudioInstance.PADDING);
|
|
267
|
+
this._end = Math.min(this._end + _HTMLAudioInstance.PADDING, this._duration);
|
|
268
|
+
this._source.onloadedmetadata = () => {
|
|
269
|
+
if (this._source) {
|
|
270
|
+
this._source.currentTime = start;
|
|
271
|
+
this._source.onloadedmetadata = null;
|
|
272
|
+
this.emit("progress", start / this._duration, this._duration);
|
|
273
|
+
pixi_js.Ticker.shared.add(this._onUpdate, this);
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
this._source.onended = this._onComplete.bind(this);
|
|
277
|
+
this._source.play();
|
|
278
|
+
this.emit("start");
|
|
279
|
+
}
|
|
280
|
+
_onUpdate() {
|
|
281
|
+
this.emit("progress", this.progress, this._duration);
|
|
282
|
+
if (this._source.currentTime >= this._end && !this._source.loop) {
|
|
283
|
+
this._onComplete();
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
_onComplete() {
|
|
287
|
+
pixi_js.Ticker.shared.remove(this._onUpdate, this);
|
|
288
|
+
this._internalStop();
|
|
289
|
+
this.emit("progress", 1, this._duration);
|
|
290
|
+
this.emit("end", this);
|
|
291
|
+
}
|
|
292
|
+
destroy() {
|
|
293
|
+
pixi_js.Ticker.shared.remove(this._onUpdate, this);
|
|
294
|
+
this.removeAllListeners();
|
|
295
|
+
const source = this._source;
|
|
296
|
+
if (source) {
|
|
297
|
+
source.onended = null;
|
|
298
|
+
source.onplay = null;
|
|
299
|
+
source.onpause = null;
|
|
300
|
+
this._internalStop();
|
|
301
|
+
}
|
|
302
|
+
this._source = null;
|
|
303
|
+
this._speed = 1;
|
|
304
|
+
this._volume = 1;
|
|
305
|
+
this._loop = false;
|
|
306
|
+
this._end = null;
|
|
307
|
+
this._start = 0;
|
|
308
|
+
this._duration = 0;
|
|
309
|
+
this._playing = false;
|
|
310
|
+
this._pausedReal = false;
|
|
311
|
+
this._paused = false;
|
|
312
|
+
this._muted = false;
|
|
313
|
+
if (this._media) {
|
|
314
|
+
this._media.context.off("refresh", this.refresh, this);
|
|
315
|
+
this._media.context.off("refreshPaused", this.refreshPaused, this);
|
|
316
|
+
this._media = null;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
toString() {
|
|
320
|
+
return `[HTMLAudioInstance id=${this.id}]`;
|
|
321
|
+
}
|
|
322
|
+
};
|
|
323
|
+
let HTMLAudioInstance = _HTMLAudioInstance;
|
|
324
|
+
HTMLAudioInstance.PADDING = 0.1;
|
|
325
|
+
class HTMLAudioMedia extends pixi_js.EventEmitter {
|
|
326
|
+
init(parent) {
|
|
327
|
+
this.parent = parent;
|
|
328
|
+
this._source = parent.options.source || new Audio();
|
|
329
|
+
if (parent.url) {
|
|
330
|
+
this._source.src = parent.url;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
create() {
|
|
334
|
+
return new HTMLAudioInstance(this);
|
|
335
|
+
}
|
|
336
|
+
get isPlayable() {
|
|
337
|
+
return !!this._source && this._source.readyState === 4;
|
|
338
|
+
}
|
|
339
|
+
get duration() {
|
|
340
|
+
return this._source.duration;
|
|
341
|
+
}
|
|
342
|
+
get context() {
|
|
343
|
+
return this.parent.context;
|
|
344
|
+
}
|
|
345
|
+
get filters() {
|
|
346
|
+
return null;
|
|
347
|
+
}
|
|
348
|
+
set filters(_filters) {
|
|
349
|
+
console.warn("HTML Audio does not support filters");
|
|
350
|
+
}
|
|
351
|
+
destroy() {
|
|
352
|
+
this.removeAllListeners();
|
|
353
|
+
this.parent = null;
|
|
354
|
+
if (this._source) {
|
|
355
|
+
this._source.src = "";
|
|
356
|
+
this._source.load();
|
|
357
|
+
this._source = null;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
get source() {
|
|
361
|
+
return this._source;
|
|
362
|
+
}
|
|
363
|
+
load(callback) {
|
|
364
|
+
const source = this._source;
|
|
365
|
+
const sound = this.parent;
|
|
366
|
+
if (source.readyState === 4) {
|
|
367
|
+
sound.isLoaded = true;
|
|
368
|
+
const instance = sound.autoPlayStart();
|
|
369
|
+
if (callback) {
|
|
370
|
+
setTimeout(() => {
|
|
371
|
+
callback(null, sound, instance);
|
|
372
|
+
}, 0);
|
|
373
|
+
}
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
if (!sound.url) {
|
|
377
|
+
callback(new Error("sound.url or sound.source must be set"));
|
|
55
378
|
return;
|
|
56
379
|
}
|
|
57
|
-
|
|
380
|
+
source.src = sound.url;
|
|
381
|
+
const onLoad = () => {
|
|
382
|
+
removeListeners();
|
|
383
|
+
sound.isLoaded = true;
|
|
384
|
+
const instance = sound.autoPlayStart();
|
|
385
|
+
if (callback) {
|
|
386
|
+
callback(null, sound, instance);
|
|
387
|
+
}
|
|
388
|
+
};
|
|
389
|
+
const onAbort = () => {
|
|
390
|
+
removeListeners();
|
|
391
|
+
if (callback) {
|
|
392
|
+
callback(new Error("Sound loading has been aborted"));
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
const onError = () => {
|
|
396
|
+
removeListeners();
|
|
397
|
+
const message = `Failed to load audio element (code: ${source.error.code})`;
|
|
398
|
+
if (callback) {
|
|
399
|
+
callback(new Error(message));
|
|
400
|
+
} else {
|
|
401
|
+
console.error(message);
|
|
402
|
+
}
|
|
403
|
+
};
|
|
404
|
+
const removeListeners = () => {
|
|
405
|
+
source.removeEventListener("canplaythrough", onLoad);
|
|
406
|
+
source.removeEventListener("load", onLoad);
|
|
407
|
+
source.removeEventListener("abort", onAbort);
|
|
408
|
+
source.removeEventListener("error", onError);
|
|
409
|
+
};
|
|
410
|
+
source.addEventListener("canplaythrough", onLoad, false);
|
|
411
|
+
source.addEventListener("load", onLoad, false);
|
|
412
|
+
source.addEventListener("abort", onAbort, false);
|
|
413
|
+
source.addEventListener("error", onError, false);
|
|
414
|
+
source.load();
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
class SoundSprite {
|
|
418
|
+
constructor(parent, options) {
|
|
419
|
+
this.parent = parent;
|
|
420
|
+
_extends(this, options);
|
|
421
|
+
this.duration = this.end - this.start;
|
|
422
|
+
console.assert(this.duration > 0, "End time must be after start time");
|
|
423
|
+
}
|
|
424
|
+
play(complete) {
|
|
425
|
+
return this.parent.play({
|
|
426
|
+
complete,
|
|
427
|
+
speed: this.speed || this.parent.speed,
|
|
428
|
+
end: this.end,
|
|
429
|
+
start: this.start,
|
|
430
|
+
loop: this.loop
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
destroy() {
|
|
434
|
+
this.parent = null;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
const extensions = ["ogg", "oga", "opus", "m4a", "mp3", "mpeg", "wav", "aiff", "wma", "mid", "caf"];
|
|
438
|
+
const mimes = ["audio/mpeg", "audio/ogg"];
|
|
439
|
+
const supported = {};
|
|
440
|
+
function validateFormats(typeOverrides) {
|
|
441
|
+
const overrides = _objectSpread({
|
|
442
|
+
m4a: "audio/mp4",
|
|
443
|
+
oga: "audio/ogg",
|
|
444
|
+
opus: 'audio/ogg; codecs="opus"',
|
|
445
|
+
caf: 'audio/x-caf; codecs="opus"'
|
|
446
|
+
}, typeOverrides || {});
|
|
447
|
+
const audio = document.createElement("audio");
|
|
448
|
+
const formats = {};
|
|
449
|
+
const no = /^no$/;
|
|
450
|
+
extensions.forEach(ext => {
|
|
451
|
+
const canByExt = audio.canPlayType(`audio/${ext}`).replace(no, "");
|
|
452
|
+
const canByType = overrides[ext] ? audio.canPlayType(overrides[ext]).replace(no, "") : "";
|
|
453
|
+
formats[ext] = !!canByExt || !!canByType;
|
|
454
|
+
});
|
|
455
|
+
_extends(supported, formats);
|
|
456
|
+
}
|
|
457
|
+
validateFormats();
|
|
458
|
+
let id = 0;
|
|
459
|
+
class WebAudioInstance extends pixi_js.EventEmitter {
|
|
460
|
+
constructor(media) {
|
|
461
|
+
super();
|
|
462
|
+
this.id = id++;
|
|
463
|
+
this._media = null;
|
|
464
|
+
this._paused = false;
|
|
465
|
+
this._muted = false;
|
|
466
|
+
this._elapsed = 0;
|
|
467
|
+
this.init(media);
|
|
468
|
+
}
|
|
469
|
+
set(name, value) {
|
|
470
|
+
if (this[name] === void 0) {
|
|
471
|
+
throw new Error(`Property with name ${name} does not exist.`);
|
|
472
|
+
} else {
|
|
473
|
+
switch (name) {
|
|
474
|
+
case "speed":
|
|
475
|
+
this.speed = value;
|
|
476
|
+
break;
|
|
477
|
+
case "volume":
|
|
478
|
+
this.volume = value;
|
|
479
|
+
break;
|
|
480
|
+
case "muted":
|
|
481
|
+
this.muted = value;
|
|
482
|
+
break;
|
|
483
|
+
case "loop":
|
|
484
|
+
this.loop = value;
|
|
485
|
+
break;
|
|
486
|
+
case "paused":
|
|
487
|
+
this.paused = value;
|
|
488
|
+
break;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
return this;
|
|
492
|
+
}
|
|
493
|
+
stop() {
|
|
494
|
+
if (this._source) {
|
|
495
|
+
this._internalStop();
|
|
496
|
+
this.emit("stop");
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
get speed() {
|
|
500
|
+
return this._speed;
|
|
501
|
+
}
|
|
502
|
+
set speed(speed) {
|
|
503
|
+
this._speed = speed;
|
|
504
|
+
this.refresh();
|
|
505
|
+
this._update(true);
|
|
58
506
|
}
|
|
59
507
|
get volume() {
|
|
60
|
-
return this.
|
|
508
|
+
return this._volume;
|
|
61
509
|
}
|
|
62
|
-
set volume(
|
|
63
|
-
|
|
510
|
+
set volume(volume) {
|
|
511
|
+
this._volume = volume;
|
|
512
|
+
this.refresh();
|
|
513
|
+
}
|
|
514
|
+
get muted() {
|
|
515
|
+
return this._muted;
|
|
516
|
+
}
|
|
517
|
+
set muted(muted) {
|
|
518
|
+
this._muted = muted;
|
|
519
|
+
this.refresh();
|
|
520
|
+
}
|
|
521
|
+
get loop() {
|
|
522
|
+
return this._loop;
|
|
523
|
+
}
|
|
524
|
+
set loop(loop) {
|
|
525
|
+
this._loop = loop;
|
|
526
|
+
this.refresh();
|
|
527
|
+
}
|
|
528
|
+
get filters() {
|
|
529
|
+
return this._filters;
|
|
530
|
+
}
|
|
531
|
+
set filters(filters) {
|
|
532
|
+
if (this._filters) {
|
|
533
|
+
var _this$_filters;
|
|
534
|
+
(_this$_filters = this._filters) === null || _this$_filters === void 0 ? void 0 : _this$_filters.filter(filter => filter).forEach(filter => filter.disconnect());
|
|
535
|
+
this._filters = null;
|
|
536
|
+
this._source.connect(this._gain);
|
|
537
|
+
}
|
|
538
|
+
this._filters = filters !== null && filters !== void 0 && filters.length ? filters.slice(0) : null;
|
|
539
|
+
this.refresh();
|
|
540
|
+
}
|
|
541
|
+
refresh() {
|
|
542
|
+
if (!this._source) {
|
|
64
543
|
return;
|
|
65
544
|
}
|
|
66
|
-
this.
|
|
545
|
+
const global = this._media.context;
|
|
546
|
+
const sound = this._media.parent;
|
|
547
|
+
this._source.loop = this._loop || sound.loop;
|
|
548
|
+
const globalVolume = global.volume * (global.muted ? 0 : 1);
|
|
549
|
+
const soundVolume = sound.volume * (sound.muted ? 0 : 1);
|
|
550
|
+
const instanceVolume = this._volume * (this._muted ? 0 : 1);
|
|
551
|
+
WebAudioUtils.setParamValue(this._gain.gain, instanceVolume * soundVolume * globalVolume);
|
|
552
|
+
WebAudioUtils.setParamValue(this._source.playbackRate, this._speed * sound.speed * global.speed);
|
|
553
|
+
this.applyFilters();
|
|
67
554
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
555
|
+
applyFilters() {
|
|
556
|
+
var _this$_filters2;
|
|
557
|
+
if ((_this$_filters2 = this._filters) !== null && _this$_filters2 !== void 0 && _this$_filters2.length) {
|
|
558
|
+
this._source.disconnect();
|
|
559
|
+
let source = this._source;
|
|
560
|
+
this._filters.forEach(filter => {
|
|
561
|
+
source.connect(filter.destination);
|
|
562
|
+
source = filter;
|
|
563
|
+
});
|
|
564
|
+
source.connect(this._gain);
|
|
71
565
|
}
|
|
72
|
-
return this.ctx.state !== 'running';
|
|
73
566
|
}
|
|
74
|
-
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
567
|
+
refreshPaused() {
|
|
568
|
+
const global = this._media.context;
|
|
569
|
+
const sound = this._media.parent;
|
|
570
|
+
const pausedReal = this._paused || sound.paused || global.paused;
|
|
571
|
+
if (pausedReal !== this._pausedReal) {
|
|
572
|
+
this._pausedReal = pausedReal;
|
|
573
|
+
if (pausedReal) {
|
|
574
|
+
this._internalStop();
|
|
575
|
+
this.emit("paused");
|
|
576
|
+
} else {
|
|
577
|
+
this.emit("resumed");
|
|
578
|
+
this.play({
|
|
579
|
+
start: this._elapsed % this._duration,
|
|
580
|
+
end: this._end,
|
|
581
|
+
speed: this._speed,
|
|
582
|
+
loop: this._loop,
|
|
583
|
+
volume: this._volume
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
this.emit("pause", pausedReal);
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
play(options) {
|
|
590
|
+
const {
|
|
591
|
+
start,
|
|
592
|
+
end,
|
|
593
|
+
speed,
|
|
594
|
+
loop,
|
|
595
|
+
volume,
|
|
596
|
+
muted,
|
|
597
|
+
filters
|
|
598
|
+
} = options;
|
|
599
|
+
if (end) {
|
|
600
|
+
console.assert(end > start, "End time is before start time");
|
|
601
|
+
}
|
|
602
|
+
this._paused = false;
|
|
603
|
+
const {
|
|
604
|
+
source,
|
|
605
|
+
gain
|
|
606
|
+
} = this._media.nodes.cloneBufferSource();
|
|
607
|
+
this._source = source;
|
|
608
|
+
this._gain = gain;
|
|
609
|
+
this._speed = speed;
|
|
610
|
+
this._volume = volume;
|
|
611
|
+
this._loop = !!loop;
|
|
612
|
+
this._muted = muted;
|
|
613
|
+
this._filters = filters;
|
|
614
|
+
this.refresh();
|
|
615
|
+
const duration = this._source.buffer.duration;
|
|
616
|
+
this._duration = duration;
|
|
617
|
+
this._end = end;
|
|
618
|
+
this._lastUpdate = this._now();
|
|
619
|
+
this._elapsed = start;
|
|
620
|
+
this._source.onended = this._onComplete.bind(this);
|
|
621
|
+
if (this._loop) {
|
|
622
|
+
this._source.loopEnd = end;
|
|
623
|
+
this._source.loopStart = start;
|
|
624
|
+
this._source.start(0, start);
|
|
625
|
+
} else if (end) {
|
|
626
|
+
this._source.start(0, start, end - start);
|
|
627
|
+
} else {
|
|
628
|
+
this._source.start(0, start);
|
|
629
|
+
}
|
|
630
|
+
this.emit("start");
|
|
631
|
+
this._update(true);
|
|
632
|
+
this.enableTicker(true);
|
|
633
|
+
}
|
|
634
|
+
enableTicker(enabled) {
|
|
635
|
+
pixi_js.Ticker.shared.remove(this._updateListener, this);
|
|
636
|
+
if (enabled) {
|
|
637
|
+
pixi_js.Ticker.shared.add(this._updateListener, this);
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
get progress() {
|
|
641
|
+
return this._progress;
|
|
642
|
+
}
|
|
643
|
+
get paused() {
|
|
644
|
+
return this._paused;
|
|
645
|
+
}
|
|
646
|
+
set paused(paused) {
|
|
647
|
+
this._paused = paused;
|
|
648
|
+
this.refreshPaused();
|
|
649
|
+
}
|
|
650
|
+
destroy() {
|
|
651
|
+
var _this$_filters3;
|
|
652
|
+
this.removeAllListeners();
|
|
653
|
+
this._internalStop();
|
|
654
|
+
if (this._gain) {
|
|
655
|
+
this._gain.disconnect();
|
|
656
|
+
this._gain = null;
|
|
657
|
+
}
|
|
658
|
+
if (this._media) {
|
|
659
|
+
this._media.context.events.off("refresh", this.refresh, this);
|
|
660
|
+
this._media.context.events.off("refreshPaused", this.refreshPaused, this);
|
|
661
|
+
this._media = null;
|
|
662
|
+
}
|
|
663
|
+
(_this$_filters3 = this._filters) === null || _this$_filters3 === void 0 ? void 0 : _this$_filters3.forEach(filter => filter.disconnect());
|
|
664
|
+
this._filters = null;
|
|
665
|
+
this._end = null;
|
|
666
|
+
this._speed = 1;
|
|
667
|
+
this._volume = 1;
|
|
668
|
+
this._loop = false;
|
|
669
|
+
this._elapsed = 0;
|
|
670
|
+
this._duration = 0;
|
|
671
|
+
this._paused = false;
|
|
672
|
+
this._muted = false;
|
|
673
|
+
this._pausedReal = false;
|
|
674
|
+
}
|
|
675
|
+
toString() {
|
|
676
|
+
return `[WebAudioInstance id=${this.id}]`;
|
|
677
|
+
}
|
|
678
|
+
_now() {
|
|
679
|
+
return this._media.context.audioContext.currentTime;
|
|
680
|
+
}
|
|
681
|
+
_updateListener() {
|
|
682
|
+
this._update();
|
|
683
|
+
}
|
|
684
|
+
_update(force = false) {
|
|
685
|
+
if (this._source) {
|
|
686
|
+
const now = this._now();
|
|
687
|
+
const delta = now - this._lastUpdate;
|
|
688
|
+
if (delta > 0 || force) {
|
|
689
|
+
const speed = this._source.playbackRate.value;
|
|
690
|
+
this._elapsed += delta * speed;
|
|
691
|
+
this._lastUpdate = now;
|
|
692
|
+
const duration = this._duration;
|
|
693
|
+
let progress;
|
|
694
|
+
if (this._source.loopStart) {
|
|
695
|
+
const soundLength = this._source.loopEnd - this._source.loopStart;
|
|
696
|
+
progress = (this._source.loopStart + this._elapsed % soundLength) / duration;
|
|
697
|
+
} else {
|
|
698
|
+
progress = this._elapsed % duration / duration;
|
|
699
|
+
}
|
|
700
|
+
this._progress = progress;
|
|
701
|
+
this.emit("progress", this._progress, duration);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
init(media) {
|
|
706
|
+
this._media = media;
|
|
707
|
+
media.context.events.on("refresh", this.refresh, this);
|
|
708
|
+
media.context.events.on("refreshPaused", this.refreshPaused, this);
|
|
709
|
+
}
|
|
710
|
+
_internalStop() {
|
|
711
|
+
if (this._source) {
|
|
712
|
+
this.enableTicker(false);
|
|
713
|
+
this._source.onended = null;
|
|
714
|
+
this._source.stop(0);
|
|
715
|
+
this._source.disconnect();
|
|
716
|
+
try {
|
|
717
|
+
this._source.buffer = null;
|
|
718
|
+
} catch (err) {
|
|
719
|
+
console.warn("Failed to set AudioBufferSourceNode.buffer to null:", err);
|
|
720
|
+
}
|
|
721
|
+
this._source = null;
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
_onComplete() {
|
|
725
|
+
if (this._source) {
|
|
726
|
+
this.enableTicker(false);
|
|
727
|
+
this._source.onended = null;
|
|
728
|
+
this._source.disconnect();
|
|
729
|
+
try {
|
|
730
|
+
this._source.buffer = null;
|
|
731
|
+
} catch (err) {
|
|
732
|
+
console.warn("Failed to set AudioBufferSourceNode.buffer to null:", err);
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
this._source = null;
|
|
736
|
+
this._progress = 1;
|
|
737
|
+
this.emit("progress", 1, this._duration);
|
|
738
|
+
this.emit("end", this);
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
class Filterable {
|
|
742
|
+
constructor(input, output) {
|
|
743
|
+
this._output = output;
|
|
744
|
+
this._input = input;
|
|
745
|
+
}
|
|
746
|
+
get destination() {
|
|
747
|
+
return this._input;
|
|
748
|
+
}
|
|
749
|
+
get filters() {
|
|
750
|
+
return this._filters;
|
|
751
|
+
}
|
|
752
|
+
set filters(filters) {
|
|
753
|
+
if (this._filters) {
|
|
754
|
+
this._filters.forEach(filter => {
|
|
755
|
+
if (filter) {
|
|
756
|
+
filter.disconnect();
|
|
757
|
+
}
|
|
758
|
+
});
|
|
759
|
+
this._filters = null;
|
|
760
|
+
this._input.connect(this._output);
|
|
761
|
+
}
|
|
762
|
+
if (filters && filters.length) {
|
|
763
|
+
this._filters = filters.slice(0);
|
|
764
|
+
this._input.disconnect();
|
|
765
|
+
let prevFilter = null;
|
|
766
|
+
filters.forEach(filter => {
|
|
767
|
+
if (prevFilter === null) {
|
|
768
|
+
this._input.connect(filter.destination);
|
|
769
|
+
} else {
|
|
770
|
+
prevFilter.connect(filter.destination);
|
|
771
|
+
}
|
|
772
|
+
prevFilter = filter;
|
|
78
773
|
});
|
|
79
|
-
this.
|
|
774
|
+
prevFilter.connect(this._output);
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
destroy() {
|
|
778
|
+
this.filters = null;
|
|
779
|
+
this._input = null;
|
|
780
|
+
this._output = null;
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
const _WebAudioNodes = class extends Filterable {
|
|
784
|
+
constructor(context) {
|
|
785
|
+
const audioContext = context.audioContext;
|
|
786
|
+
const bufferSource = audioContext.createBufferSource();
|
|
787
|
+
const gain = audioContext.createGain();
|
|
788
|
+
const analyser = audioContext.createAnalyser();
|
|
789
|
+
bufferSource.connect(analyser);
|
|
790
|
+
analyser.connect(gain);
|
|
791
|
+
gain.connect(context.destination);
|
|
792
|
+
super(analyser, gain);
|
|
793
|
+
this.context = context;
|
|
794
|
+
this.bufferSource = bufferSource;
|
|
795
|
+
this.gain = gain;
|
|
796
|
+
this.analyser = analyser;
|
|
797
|
+
}
|
|
798
|
+
get script() {
|
|
799
|
+
if (!this._script) {
|
|
800
|
+
this._script = this.context.audioContext.createScriptProcessor(_WebAudioNodes.BUFFER_SIZE);
|
|
801
|
+
this._script.connect(this.context.destination);
|
|
802
|
+
}
|
|
803
|
+
return this._script;
|
|
804
|
+
}
|
|
805
|
+
destroy() {
|
|
806
|
+
super.destroy();
|
|
807
|
+
this.bufferSource.disconnect();
|
|
808
|
+
if (this._script) {
|
|
809
|
+
this._script.disconnect();
|
|
810
|
+
}
|
|
811
|
+
this.gain.disconnect();
|
|
812
|
+
this.analyser.disconnect();
|
|
813
|
+
this.bufferSource = null;
|
|
814
|
+
this._script = null;
|
|
815
|
+
this.gain = null;
|
|
816
|
+
this.analyser = null;
|
|
817
|
+
this.context = null;
|
|
818
|
+
}
|
|
819
|
+
cloneBufferSource() {
|
|
820
|
+
const orig = this.bufferSource;
|
|
821
|
+
const source = this.context.audioContext.createBufferSource();
|
|
822
|
+
source.buffer = orig.buffer;
|
|
823
|
+
WebAudioUtils.setParamValue(source.playbackRate, orig.playbackRate.value);
|
|
824
|
+
source.loop = orig.loop;
|
|
825
|
+
const gain = this.context.audioContext.createGain();
|
|
826
|
+
source.connect(gain);
|
|
827
|
+
gain.connect(this.destination);
|
|
828
|
+
return {
|
|
829
|
+
source,
|
|
830
|
+
gain
|
|
80
831
|
};
|
|
81
|
-
this.ctx.resume().then(handleResume, handleResume);
|
|
82
832
|
}
|
|
83
|
-
|
|
84
|
-
this.
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
833
|
+
get bufferSize() {
|
|
834
|
+
return this.script.bufferSize;
|
|
835
|
+
}
|
|
836
|
+
};
|
|
837
|
+
let WebAudioNodes = _WebAudioNodes;
|
|
838
|
+
WebAudioNodes.BUFFER_SIZE = 0;
|
|
839
|
+
class WebAudioMedia {
|
|
840
|
+
init(parent) {
|
|
841
|
+
this.parent = parent;
|
|
842
|
+
this._nodes = new WebAudioNodes(this.context);
|
|
843
|
+
this._source = this._nodes.bufferSource;
|
|
844
|
+
this.source = parent.options.source;
|
|
845
|
+
}
|
|
846
|
+
destroy() {
|
|
847
|
+
this.parent = null;
|
|
848
|
+
this._nodes.destroy();
|
|
849
|
+
this._nodes = null;
|
|
850
|
+
try {
|
|
851
|
+
this._source.buffer = null;
|
|
852
|
+
} catch (err) {
|
|
853
|
+
console.warn("Failed to set AudioBufferSourceNode.buffer to null:", err);
|
|
854
|
+
}
|
|
855
|
+
this._source = null;
|
|
856
|
+
this.source = null;
|
|
857
|
+
}
|
|
858
|
+
create() {
|
|
859
|
+
return new WebAudioInstance(this);
|
|
860
|
+
}
|
|
861
|
+
get context() {
|
|
862
|
+
return this.parent.context;
|
|
863
|
+
}
|
|
864
|
+
get isPlayable() {
|
|
865
|
+
return !!this._source && !!this._source.buffer;
|
|
866
|
+
}
|
|
867
|
+
get filters() {
|
|
868
|
+
return this._nodes.filters;
|
|
869
|
+
}
|
|
870
|
+
set filters(filters) {
|
|
871
|
+
this._nodes.filters = filters;
|
|
872
|
+
}
|
|
873
|
+
get duration() {
|
|
874
|
+
console.assert(this.isPlayable, "Sound not yet playable, no duration");
|
|
875
|
+
return this._source.buffer.duration;
|
|
876
|
+
}
|
|
877
|
+
get buffer() {
|
|
878
|
+
return this._source.buffer;
|
|
879
|
+
}
|
|
880
|
+
set buffer(buffer) {
|
|
881
|
+
this._source.buffer = buffer;
|
|
882
|
+
}
|
|
883
|
+
get nodes() {
|
|
884
|
+
return this._nodes;
|
|
885
|
+
}
|
|
886
|
+
load(callback) {
|
|
887
|
+
if (this.source) {
|
|
888
|
+
this._decode(this.source, callback);
|
|
889
|
+
} else if (this.parent.url) {
|
|
890
|
+
this._loadUrl(callback);
|
|
891
|
+
} else if (callback) {
|
|
892
|
+
callback(new Error("sound.url or sound.source must be set"));
|
|
893
|
+
} else {
|
|
894
|
+
console.error("sound.url or sound.source must be set");
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
async _loadUrl(callback) {
|
|
898
|
+
const url = this.parent.url;
|
|
899
|
+
const response = await pixi_js.DOMAdapter.get().fetch(url);
|
|
900
|
+
this._decode(await response.arrayBuffer(), callback);
|
|
901
|
+
}
|
|
902
|
+
_decode(arrayBuffer, callback) {
|
|
903
|
+
const audioBufferReadyFn = (err, buffer) => {
|
|
904
|
+
if (err) {
|
|
905
|
+
if (callback) {
|
|
906
|
+
callback(err);
|
|
907
|
+
}
|
|
908
|
+
} else {
|
|
909
|
+
this.parent.isLoaded = true;
|
|
910
|
+
this.buffer = buffer;
|
|
911
|
+
const instance = this.parent.autoPlayStart();
|
|
912
|
+
if (callback) {
|
|
913
|
+
callback(null, this.parent, instance);
|
|
914
|
+
}
|
|
88
915
|
}
|
|
89
|
-
}
|
|
90
|
-
|
|
916
|
+
};
|
|
917
|
+
if (arrayBuffer instanceof AudioBuffer) {
|
|
918
|
+
audioBufferReadyFn(null, arrayBuffer);
|
|
919
|
+
} else {
|
|
920
|
+
const context = this.parent.context;
|
|
921
|
+
context.decode(arrayBuffer, audioBufferReadyFn);
|
|
922
|
+
}
|
|
91
923
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
924
|
+
}
|
|
925
|
+
const _Sound = class {
|
|
926
|
+
static from(source) {
|
|
927
|
+
let options = {};
|
|
928
|
+
if (typeof source === "string") {
|
|
929
|
+
options.url = source;
|
|
930
|
+
} else if (source instanceof ArrayBuffer || source instanceof AudioBuffer || source instanceof HTMLAudioElement) {
|
|
931
|
+
options.source = source;
|
|
932
|
+
} else if (Array.isArray(source)) {
|
|
933
|
+
options.url = source;
|
|
934
|
+
} else {
|
|
935
|
+
options = source;
|
|
936
|
+
}
|
|
937
|
+
options = _objectSpread({
|
|
938
|
+
autoPlay: false,
|
|
939
|
+
singleInstance: false,
|
|
940
|
+
url: null,
|
|
941
|
+
source: null,
|
|
942
|
+
preload: false,
|
|
943
|
+
volume: 1,
|
|
944
|
+
speed: 1,
|
|
945
|
+
complete: null,
|
|
946
|
+
loaded: null,
|
|
947
|
+
loop: false
|
|
948
|
+
}, options);
|
|
949
|
+
Object.freeze(options);
|
|
950
|
+
const media = getInstance().useLegacy ? new HTMLAudioMedia() : new WebAudioMedia();
|
|
951
|
+
return new _Sound(media, options);
|
|
952
|
+
}
|
|
953
|
+
constructor(media, options) {
|
|
954
|
+
this.media = media;
|
|
955
|
+
this.options = options;
|
|
956
|
+
this._instances = [];
|
|
957
|
+
this._sprites = {};
|
|
958
|
+
this.media.init(this);
|
|
959
|
+
const complete = options.complete;
|
|
960
|
+
this._autoPlayOptions = complete ? {
|
|
961
|
+
complete
|
|
962
|
+
} : null;
|
|
963
|
+
this.isLoaded = false;
|
|
964
|
+
this._preloadQueue = null;
|
|
965
|
+
this.isPlaying = false;
|
|
966
|
+
this.autoPlay = options.autoPlay;
|
|
967
|
+
this.singleInstance = options.singleInstance;
|
|
968
|
+
this.preload = options.preload || this.autoPlay;
|
|
969
|
+
this.url = Array.isArray(options.url) ? this.preferUrl(options.url) : options.url;
|
|
970
|
+
this.speed = options.speed;
|
|
971
|
+
this.volume = options.volume;
|
|
972
|
+
this.loop = options.loop;
|
|
973
|
+
if (options.sprites) {
|
|
974
|
+
this.addSprites(options.sprites);
|
|
975
|
+
}
|
|
976
|
+
if (this.preload) {
|
|
977
|
+
this._preload(options.loaded);
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
preferUrl(urls) {
|
|
981
|
+
const [file] = urls.map(url => ({
|
|
982
|
+
url,
|
|
983
|
+
ext: pixi_js.path.extname(url).slice(1)
|
|
984
|
+
})).filter(({
|
|
985
|
+
ext
|
|
986
|
+
}) => supported[ext]).sort((a, b) => extensions.indexOf(a.ext) - extensions.indexOf(b.ext));
|
|
987
|
+
if (!file) {
|
|
988
|
+
throw new Error("No supported file type found");
|
|
989
|
+
}
|
|
990
|
+
return file.url;
|
|
991
|
+
}
|
|
992
|
+
get context() {
|
|
993
|
+
return getInstance().context;
|
|
994
|
+
}
|
|
995
|
+
pause() {
|
|
996
|
+
this.isPlaying = false;
|
|
997
|
+
this.paused = true;
|
|
998
|
+
return this;
|
|
999
|
+
}
|
|
1000
|
+
resume() {
|
|
1001
|
+
this.isPlaying = this._instances.length > 0;
|
|
1002
|
+
this.paused = false;
|
|
1003
|
+
return this;
|
|
1004
|
+
}
|
|
1005
|
+
get paused() {
|
|
1006
|
+
return this._paused;
|
|
1007
|
+
}
|
|
1008
|
+
set paused(paused) {
|
|
1009
|
+
this._paused = paused;
|
|
1010
|
+
this.refreshPaused();
|
|
1011
|
+
}
|
|
1012
|
+
get speed() {
|
|
1013
|
+
return this._speed;
|
|
1014
|
+
}
|
|
1015
|
+
set speed(speed) {
|
|
1016
|
+
this._speed = speed;
|
|
1017
|
+
this.refresh();
|
|
1018
|
+
}
|
|
1019
|
+
get filters() {
|
|
1020
|
+
return this.media.filters;
|
|
1021
|
+
}
|
|
1022
|
+
set filters(filters) {
|
|
1023
|
+
this.media.filters = filters;
|
|
1024
|
+
}
|
|
1025
|
+
addSprites(source, data) {
|
|
1026
|
+
if (typeof source === "object") {
|
|
1027
|
+
const results = {};
|
|
1028
|
+
for (const alias in source) {
|
|
1029
|
+
results[alias] = this.addSprites(alias, source[alias]);
|
|
1030
|
+
}
|
|
1031
|
+
return results;
|
|
1032
|
+
}
|
|
1033
|
+
console.assert(!this._sprites[source], `Alias ${source} is already taken`);
|
|
1034
|
+
const sprite = new SoundSprite(this, data);
|
|
1035
|
+
this._sprites[source] = sprite;
|
|
1036
|
+
return sprite;
|
|
1037
|
+
}
|
|
1038
|
+
destroy() {
|
|
1039
|
+
this._removeInstances();
|
|
1040
|
+
this.removeSprites();
|
|
1041
|
+
this.media.destroy();
|
|
1042
|
+
this.media = null;
|
|
1043
|
+
this._sprites = null;
|
|
1044
|
+
this._instances = null;
|
|
1045
|
+
}
|
|
1046
|
+
removeSprites(alias) {
|
|
1047
|
+
if (!alias) {
|
|
1048
|
+
for (const name in this._sprites) {
|
|
1049
|
+
this.removeSprites(name);
|
|
1050
|
+
}
|
|
1051
|
+
} else {
|
|
1052
|
+
const sprite = this._sprites[alias];
|
|
1053
|
+
if (sprite !== void 0) {
|
|
1054
|
+
sprite.destroy();
|
|
1055
|
+
delete this._sprites[alias];
|
|
96
1056
|
}
|
|
1057
|
+
}
|
|
1058
|
+
return this;
|
|
1059
|
+
}
|
|
1060
|
+
get isPlayable() {
|
|
1061
|
+
return this.isLoaded && this.media && this.media.isPlayable;
|
|
1062
|
+
}
|
|
1063
|
+
stop() {
|
|
1064
|
+
if (!this.isPlayable) {
|
|
1065
|
+
this.autoPlay = false;
|
|
1066
|
+
this._autoPlayOptions = null;
|
|
1067
|
+
return this;
|
|
1068
|
+
}
|
|
1069
|
+
this.isPlaying = false;
|
|
1070
|
+
for (let i = this._instances.length - 1; i >= 0; i--) {
|
|
1071
|
+
this._instances[i].stop();
|
|
1072
|
+
}
|
|
1073
|
+
return this;
|
|
1074
|
+
}
|
|
1075
|
+
play(source, complete) {
|
|
1076
|
+
let options;
|
|
1077
|
+
if (typeof source === "string") {
|
|
1078
|
+
const sprite = source;
|
|
1079
|
+
options = {
|
|
1080
|
+
sprite,
|
|
1081
|
+
loop: this.loop,
|
|
1082
|
+
complete
|
|
1083
|
+
};
|
|
1084
|
+
} else if (typeof source === "function") {
|
|
1085
|
+
options = {};
|
|
1086
|
+
options.complete = source;
|
|
1087
|
+
} else {
|
|
1088
|
+
options = source;
|
|
1089
|
+
}
|
|
1090
|
+
options = _objectSpread({
|
|
1091
|
+
complete: null,
|
|
1092
|
+
loaded: null,
|
|
1093
|
+
sprite: null,
|
|
1094
|
+
end: null,
|
|
1095
|
+
start: 0,
|
|
1096
|
+
volume: 1,
|
|
1097
|
+
speed: 1,
|
|
1098
|
+
muted: false,
|
|
1099
|
+
loop: false
|
|
1100
|
+
}, options || {});
|
|
1101
|
+
if (options.sprite) {
|
|
1102
|
+
const alias = options.sprite;
|
|
1103
|
+
console.assert(!!this._sprites[alias], `Alias ${alias} is not available`);
|
|
1104
|
+
const sprite = this._sprites[alias];
|
|
1105
|
+
options.start = sprite.start + (options.start || 0);
|
|
1106
|
+
options.end = sprite.end;
|
|
1107
|
+
options.speed = sprite.speed || 1;
|
|
1108
|
+
options.loop = sprite.loop || options.loop;
|
|
1109
|
+
delete options.sprite;
|
|
1110
|
+
}
|
|
1111
|
+
if (options.offset) {
|
|
1112
|
+
options.start = options.offset;
|
|
1113
|
+
}
|
|
1114
|
+
if (!this.isLoaded) {
|
|
1115
|
+
if (this._preloadQueue) {
|
|
1116
|
+
return new Promise(resolve => {
|
|
1117
|
+
this._preloadQueue.push(() => {
|
|
1118
|
+
resolve(this.play(options));
|
|
1119
|
+
});
|
|
1120
|
+
});
|
|
1121
|
+
}
|
|
1122
|
+
this._preloadQueue = [];
|
|
1123
|
+
this.autoPlay = true;
|
|
1124
|
+
this._autoPlayOptions = options;
|
|
1125
|
+
return new Promise((resolve, reject) => {
|
|
1126
|
+
this._preload((err, sound, media) => {
|
|
1127
|
+
this._preloadQueue.forEach(resolve2 => resolve2());
|
|
1128
|
+
this._preloadQueue = null;
|
|
1129
|
+
if (err) {
|
|
1130
|
+
reject(err);
|
|
1131
|
+
} else {
|
|
1132
|
+
if (options.loaded) {
|
|
1133
|
+
options.loaded(err, sound, media);
|
|
1134
|
+
}
|
|
1135
|
+
resolve(media);
|
|
1136
|
+
}
|
|
1137
|
+
});
|
|
1138
|
+
});
|
|
1139
|
+
}
|
|
1140
|
+
if (this.singleInstance || options.singleInstance) {
|
|
1141
|
+
this._removeInstances();
|
|
1142
|
+
}
|
|
1143
|
+
const instance = this._createInstance();
|
|
1144
|
+
this._instances.push(instance);
|
|
1145
|
+
this.isPlaying = true;
|
|
1146
|
+
instance.once("end", () => {
|
|
1147
|
+
if (options.complete) {
|
|
1148
|
+
options.complete(this);
|
|
1149
|
+
}
|
|
1150
|
+
this._onComplete(instance);
|
|
97
1151
|
});
|
|
98
|
-
|
|
99
|
-
|
|
1152
|
+
instance.once("stop", () => {
|
|
1153
|
+
this._onComplete(instance);
|
|
1154
|
+
});
|
|
1155
|
+
instance.play(options);
|
|
1156
|
+
return instance;
|
|
1157
|
+
}
|
|
1158
|
+
refresh() {
|
|
1159
|
+
const len = this._instances.length;
|
|
1160
|
+
for (let i = 0; i < len; i++) {
|
|
1161
|
+
this._instances[i].refresh();
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
refreshPaused() {
|
|
1165
|
+
const len = this._instances.length;
|
|
1166
|
+
for (let i = 0; i < len; i++) {
|
|
1167
|
+
this._instances[i].refreshPaused();
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
get volume() {
|
|
1171
|
+
return this._volume;
|
|
1172
|
+
}
|
|
1173
|
+
set volume(volume) {
|
|
1174
|
+
this._volume = volume;
|
|
1175
|
+
this.refresh();
|
|
1176
|
+
}
|
|
1177
|
+
get muted() {
|
|
1178
|
+
return this._muted;
|
|
1179
|
+
}
|
|
1180
|
+
set muted(muted) {
|
|
1181
|
+
this._muted = muted;
|
|
1182
|
+
this.refresh();
|
|
1183
|
+
}
|
|
1184
|
+
get loop() {
|
|
1185
|
+
return this._loop;
|
|
1186
|
+
}
|
|
1187
|
+
set loop(loop) {
|
|
1188
|
+
this._loop = loop;
|
|
1189
|
+
this.refresh();
|
|
1190
|
+
}
|
|
1191
|
+
_preload(callback) {
|
|
1192
|
+
this.media.load(callback);
|
|
1193
|
+
}
|
|
1194
|
+
get instances() {
|
|
1195
|
+
return this._instances;
|
|
1196
|
+
}
|
|
1197
|
+
get sprites() {
|
|
1198
|
+
return this._sprites;
|
|
1199
|
+
}
|
|
1200
|
+
get duration() {
|
|
1201
|
+
return this.media.duration;
|
|
1202
|
+
}
|
|
1203
|
+
autoPlayStart() {
|
|
1204
|
+
let instance;
|
|
1205
|
+
if (this.autoPlay) {
|
|
1206
|
+
instance = this.play(this._autoPlayOptions);
|
|
1207
|
+
}
|
|
1208
|
+
return instance;
|
|
1209
|
+
}
|
|
1210
|
+
_removeInstances() {
|
|
1211
|
+
for (let i = this._instances.length - 1; i >= 0; i--) {
|
|
1212
|
+
this._poolInstance(this._instances[i]);
|
|
1213
|
+
}
|
|
1214
|
+
this._instances.length = 0;
|
|
1215
|
+
}
|
|
1216
|
+
_onComplete(instance) {
|
|
1217
|
+
if (this._instances) {
|
|
1218
|
+
const index = this._instances.indexOf(instance);
|
|
1219
|
+
if (index > -1) {
|
|
1220
|
+
this._instances.splice(index, 1);
|
|
1221
|
+
}
|
|
1222
|
+
this.isPlaying = this._instances.length > 0;
|
|
1223
|
+
}
|
|
1224
|
+
this._poolInstance(instance);
|
|
1225
|
+
}
|
|
1226
|
+
_createInstance() {
|
|
1227
|
+
if (_Sound._pool.length > 0) {
|
|
1228
|
+
const instance = _Sound._pool.pop();
|
|
1229
|
+
instance.init(this.media);
|
|
1230
|
+
return instance;
|
|
1231
|
+
}
|
|
1232
|
+
return this.media.create();
|
|
1233
|
+
}
|
|
1234
|
+
_poolInstance(instance) {
|
|
1235
|
+
instance.destroy();
|
|
1236
|
+
if (_Sound._pool.indexOf(instance) < 0) {
|
|
1237
|
+
_Sound._pool.push(instance);
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
};
|
|
1241
|
+
let Sound$2 = _Sound;
|
|
1242
|
+
Sound$2._pool = [];
|
|
1243
|
+
class WebAudioContext extends Filterable {
|
|
1244
|
+
constructor() {
|
|
1245
|
+
const win = window;
|
|
1246
|
+
const ctx = new WebAudioContext.AudioContext();
|
|
1247
|
+
const compressor = ctx.createDynamicsCompressor();
|
|
1248
|
+
const analyser = ctx.createAnalyser();
|
|
1249
|
+
analyser.connect(compressor);
|
|
1250
|
+
compressor.connect(ctx.destination);
|
|
1251
|
+
super(analyser, compressor);
|
|
1252
|
+
this.autoPause = true;
|
|
1253
|
+
this._ctx = ctx;
|
|
1254
|
+
this._offlineCtx = new WebAudioContext.OfflineAudioContext(1, 2, win.OfflineAudioContext ? Math.max(8e3, Math.min(96e3, ctx.sampleRate)) : 44100);
|
|
1255
|
+
this.compressor = compressor;
|
|
1256
|
+
this.analyser = analyser;
|
|
1257
|
+
this.events = new pixi_js.EventEmitter();
|
|
1258
|
+
this.volume = 1;
|
|
1259
|
+
this.speed = 1;
|
|
1260
|
+
this.muted = false;
|
|
1261
|
+
this.paused = false;
|
|
1262
|
+
this._locked = ctx.state === "suspended" && ("ontouchstart" in globalThis || "onclick" in globalThis);
|
|
1263
|
+
if (this._locked) {
|
|
1264
|
+
this._unlock();
|
|
1265
|
+
this._unlock = this._unlock.bind(this);
|
|
1266
|
+
document.addEventListener("mousedown", this._unlock, true);
|
|
1267
|
+
document.addEventListener("touchstart", this._unlock, true);
|
|
1268
|
+
document.addEventListener("touchend", this._unlock, true);
|
|
1269
|
+
}
|
|
1270
|
+
this.onFocus = this.onFocus.bind(this);
|
|
1271
|
+
this.onBlur = this.onBlur.bind(this);
|
|
1272
|
+
globalThis.addEventListener("focus", this.onFocus);
|
|
1273
|
+
globalThis.addEventListener("blur", this.onBlur);
|
|
1274
|
+
}
|
|
1275
|
+
onFocus() {
|
|
1276
|
+
if (!this.autoPause) {
|
|
1277
|
+
return;
|
|
1278
|
+
}
|
|
1279
|
+
const state = this._ctx.state;
|
|
1280
|
+
if (state === "suspended" || state === "interrupted" || !this._locked) {
|
|
1281
|
+
this.paused = this._pausedOnBlur;
|
|
1282
|
+
this.refreshPaused();
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
onBlur() {
|
|
1286
|
+
if (!this.autoPause) {
|
|
1287
|
+
return;
|
|
1288
|
+
}
|
|
1289
|
+
if (!this._locked) {
|
|
1290
|
+
this._pausedOnBlur = this._paused;
|
|
1291
|
+
this.paused = true;
|
|
1292
|
+
this.refreshPaused();
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
_unlock() {
|
|
1296
|
+
if (!this._locked) {
|
|
1297
|
+
return;
|
|
1298
|
+
}
|
|
1299
|
+
this.playEmptySound();
|
|
1300
|
+
if (this._ctx.state === "running") {
|
|
1301
|
+
document.removeEventListener("mousedown", this._unlock, true);
|
|
1302
|
+
document.removeEventListener("touchend", this._unlock, true);
|
|
1303
|
+
document.removeEventListener("touchstart", this._unlock, true);
|
|
1304
|
+
this._locked = false;
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
playEmptySound() {
|
|
1308
|
+
const source = this._ctx.createBufferSource();
|
|
1309
|
+
source.buffer = this._ctx.createBuffer(1, 1, 22050);
|
|
1310
|
+
source.connect(this._ctx.destination);
|
|
1311
|
+
source.start(0, 0, 0);
|
|
1312
|
+
if (source.context.state === "suspended") {
|
|
1313
|
+
const promise = source.context.resume();
|
|
1314
|
+
if (promise.catch) {
|
|
1315
|
+
promise.catch(() => {});
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
static get AudioContext() {
|
|
1320
|
+
const win = window;
|
|
1321
|
+
return win.AudioContext || win.webkitAudioContext || null;
|
|
1322
|
+
}
|
|
1323
|
+
static get OfflineAudioContext() {
|
|
1324
|
+
const win = window;
|
|
1325
|
+
return win.OfflineAudioContext || win.webkitOfflineAudioContext || null;
|
|
1326
|
+
}
|
|
1327
|
+
destroy() {
|
|
1328
|
+
super.destroy();
|
|
1329
|
+
const ctx = this._ctx;
|
|
1330
|
+
if (typeof ctx.close !== "undefined") {
|
|
1331
|
+
ctx.close();
|
|
1332
|
+
}
|
|
1333
|
+
globalThis.removeEventListener("focus", this.onFocus);
|
|
1334
|
+
globalThis.removeEventListener("blur", this.onBlur);
|
|
1335
|
+
this.events.removeAllListeners();
|
|
1336
|
+
this.analyser.disconnect();
|
|
1337
|
+
this.compressor.disconnect();
|
|
1338
|
+
this.analyser = null;
|
|
1339
|
+
this.compressor = null;
|
|
1340
|
+
this.events = null;
|
|
1341
|
+
this._offlineCtx = null;
|
|
1342
|
+
this._ctx = null;
|
|
1343
|
+
}
|
|
1344
|
+
get audioContext() {
|
|
1345
|
+
return this._ctx;
|
|
1346
|
+
}
|
|
1347
|
+
get offlineContext() {
|
|
1348
|
+
return this._offlineCtx;
|
|
1349
|
+
}
|
|
1350
|
+
set paused(paused) {
|
|
1351
|
+
if (paused && this._ctx.state === "running") {
|
|
1352
|
+
this._ctx.suspend().catch(() => {});
|
|
1353
|
+
} else if (!paused && this._ctx.state === "suspended") {
|
|
1354
|
+
this._ctx.resume().catch(() => {});
|
|
1355
|
+
}
|
|
1356
|
+
this._paused = paused;
|
|
1357
|
+
}
|
|
1358
|
+
get paused() {
|
|
1359
|
+
return this._paused;
|
|
1360
|
+
}
|
|
1361
|
+
refresh() {
|
|
1362
|
+
this.events.emit("refresh");
|
|
1363
|
+
}
|
|
1364
|
+
refreshPaused() {
|
|
1365
|
+
this.events.emit("refreshPaused");
|
|
1366
|
+
}
|
|
1367
|
+
toggleMute() {
|
|
1368
|
+
this.muted = !this.muted;
|
|
1369
|
+
this.refresh();
|
|
1370
|
+
return this.muted;
|
|
1371
|
+
}
|
|
1372
|
+
togglePause() {
|
|
1373
|
+
this.paused = !this.paused;
|
|
1374
|
+
this.refreshPaused();
|
|
1375
|
+
return this._paused;
|
|
1376
|
+
}
|
|
1377
|
+
decode(arrayBuffer, callback) {
|
|
1378
|
+
const handleError = err => {
|
|
1379
|
+
callback(new Error((err === null || err === void 0 ? void 0 : err.message) || "Unable to decode file"));
|
|
1380
|
+
};
|
|
1381
|
+
const result = this._offlineCtx.decodeAudioData(arrayBuffer, buffer => {
|
|
1382
|
+
callback(null, buffer);
|
|
1383
|
+
}, handleError);
|
|
1384
|
+
if (result) {
|
|
1385
|
+
result.catch(handleError);
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
class SoundLibrary {
|
|
1390
|
+
constructor() {
|
|
1391
|
+
this.init();
|
|
100
1392
|
}
|
|
101
1393
|
init() {
|
|
102
|
-
this.
|
|
1394
|
+
if (this.supported) {
|
|
1395
|
+
this._webAudioContext = new WebAudioContext();
|
|
1396
|
+
}
|
|
1397
|
+
this._htmlAudioContext = new HTMLAudioContext();
|
|
1398
|
+
this._sounds = {};
|
|
1399
|
+
this.useLegacy = !this.supported;
|
|
1400
|
+
return this;
|
|
1401
|
+
}
|
|
1402
|
+
get context() {
|
|
1403
|
+
return this._context;
|
|
1404
|
+
}
|
|
1405
|
+
get filtersAll() {
|
|
1406
|
+
if (!this.useLegacy) {
|
|
1407
|
+
return this._context.filters;
|
|
1408
|
+
}
|
|
1409
|
+
return [];
|
|
1410
|
+
}
|
|
1411
|
+
set filtersAll(filtersAll) {
|
|
1412
|
+
if (!this.useLegacy) {
|
|
1413
|
+
this._context.filters = filtersAll;
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1416
|
+
get supported() {
|
|
1417
|
+
return WebAudioContext.AudioContext !== null;
|
|
1418
|
+
}
|
|
1419
|
+
add(source, sourceOptions) {
|
|
1420
|
+
if (typeof source === "object") {
|
|
1421
|
+
const results = {};
|
|
1422
|
+
for (const alias in source) {
|
|
1423
|
+
const options2 = this._getOptions(source[alias], sourceOptions);
|
|
1424
|
+
results[alias] = this.add(alias, options2);
|
|
1425
|
+
}
|
|
1426
|
+
return results;
|
|
1427
|
+
}
|
|
1428
|
+
console.assert(!this._sounds[source], `Sound with alias ${source} already exists.`);
|
|
1429
|
+
if (sourceOptions instanceof Sound$2) {
|
|
1430
|
+
this._sounds[source] = sourceOptions;
|
|
1431
|
+
return sourceOptions;
|
|
1432
|
+
}
|
|
1433
|
+
const options = this._getOptions(sourceOptions);
|
|
1434
|
+
const sound = Sound$2.from(options);
|
|
1435
|
+
this._sounds[source] = sound;
|
|
1436
|
+
return sound;
|
|
1437
|
+
}
|
|
1438
|
+
_getOptions(source, overrides) {
|
|
1439
|
+
let options;
|
|
1440
|
+
if (typeof source === "string") {
|
|
1441
|
+
options = {
|
|
1442
|
+
url: source
|
|
1443
|
+
};
|
|
1444
|
+
} else if (Array.isArray(source)) {
|
|
1445
|
+
options = {
|
|
1446
|
+
url: source
|
|
1447
|
+
};
|
|
1448
|
+
} else if (source instanceof ArrayBuffer || source instanceof AudioBuffer || source instanceof HTMLAudioElement) {
|
|
1449
|
+
options = {
|
|
1450
|
+
source
|
|
1451
|
+
};
|
|
1452
|
+
} else {
|
|
1453
|
+
options = source;
|
|
1454
|
+
}
|
|
1455
|
+
options = _objectSpread(_objectSpread({}, options), overrides || {});
|
|
1456
|
+
return options;
|
|
1457
|
+
}
|
|
1458
|
+
get useLegacy() {
|
|
1459
|
+
return this._useLegacy;
|
|
1460
|
+
}
|
|
1461
|
+
set useLegacy(legacy) {
|
|
1462
|
+
this._useLegacy = legacy;
|
|
1463
|
+
this._context = !legacy && this.supported ? this._webAudioContext : this._htmlAudioContext;
|
|
1464
|
+
}
|
|
1465
|
+
get disableAutoPause() {
|
|
1466
|
+
if (this._webAudioContext) {
|
|
1467
|
+
return !this._webAudioContext.autoPause;
|
|
1468
|
+
}
|
|
1469
|
+
console.warn("WebAudioContext is not initialized.");
|
|
1470
|
+
return false;
|
|
1471
|
+
}
|
|
1472
|
+
set disableAutoPause(autoPause) {
|
|
1473
|
+
if (this._webAudioContext) {
|
|
1474
|
+
this._webAudioContext.autoPause = !autoPause;
|
|
1475
|
+
} else {
|
|
1476
|
+
console.warn("WebAudioContext is not initialized.");
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
remove(alias) {
|
|
1480
|
+
this.exists(alias, true);
|
|
1481
|
+
this._sounds[alias].destroy();
|
|
1482
|
+
delete this._sounds[alias];
|
|
1483
|
+
return this;
|
|
1484
|
+
}
|
|
1485
|
+
get volumeAll() {
|
|
1486
|
+
return this._context.volume;
|
|
1487
|
+
}
|
|
1488
|
+
set volumeAll(volume) {
|
|
1489
|
+
this._context.volume = volume;
|
|
1490
|
+
this._context.refresh();
|
|
1491
|
+
}
|
|
1492
|
+
get speedAll() {
|
|
1493
|
+
return this._context.speed;
|
|
1494
|
+
}
|
|
1495
|
+
set speedAll(speed) {
|
|
1496
|
+
this._context.speed = speed;
|
|
1497
|
+
this._context.refresh();
|
|
1498
|
+
}
|
|
1499
|
+
togglePauseAll() {
|
|
1500
|
+
return this._context.togglePause();
|
|
1501
|
+
}
|
|
1502
|
+
pauseAll() {
|
|
1503
|
+
this._context.paused = true;
|
|
1504
|
+
this._context.refreshPaused();
|
|
1505
|
+
return this;
|
|
1506
|
+
}
|
|
1507
|
+
resumeAll() {
|
|
1508
|
+
this._context.paused = false;
|
|
1509
|
+
this._context.refreshPaused();
|
|
1510
|
+
return this;
|
|
1511
|
+
}
|
|
1512
|
+
toggleMuteAll() {
|
|
1513
|
+
return this._context.toggleMute();
|
|
1514
|
+
}
|
|
1515
|
+
muteAll() {
|
|
1516
|
+
this._context.muted = true;
|
|
1517
|
+
this._context.refresh();
|
|
1518
|
+
return this;
|
|
1519
|
+
}
|
|
1520
|
+
unmuteAll() {
|
|
1521
|
+
this._context.muted = false;
|
|
1522
|
+
this._context.refresh();
|
|
1523
|
+
return this;
|
|
1524
|
+
}
|
|
1525
|
+
removeAll() {
|
|
1526
|
+
for (const alias in this._sounds) {
|
|
1527
|
+
this._sounds[alias].destroy();
|
|
1528
|
+
delete this._sounds[alias];
|
|
1529
|
+
}
|
|
1530
|
+
return this;
|
|
1531
|
+
}
|
|
1532
|
+
stopAll() {
|
|
1533
|
+
for (const alias in this._sounds) {
|
|
1534
|
+
this._sounds[alias].stop();
|
|
1535
|
+
}
|
|
1536
|
+
return this;
|
|
1537
|
+
}
|
|
1538
|
+
exists(alias, assert = false) {
|
|
1539
|
+
const exists = !!this._sounds[alias];
|
|
1540
|
+
if (assert) {
|
|
1541
|
+
console.assert(exists, `No sound matching alias '${alias}'.`);
|
|
1542
|
+
}
|
|
1543
|
+
return exists;
|
|
1544
|
+
}
|
|
1545
|
+
isPlaying() {
|
|
1546
|
+
for (const alias in this._sounds) {
|
|
1547
|
+
if (this._sounds[alias].isPlaying) {
|
|
1548
|
+
return true;
|
|
1549
|
+
}
|
|
1550
|
+
}
|
|
1551
|
+
return false;
|
|
1552
|
+
}
|
|
1553
|
+
find(alias) {
|
|
1554
|
+
this.exists(alias, true);
|
|
1555
|
+
return this._sounds[alias];
|
|
1556
|
+
}
|
|
1557
|
+
play(alias, options) {
|
|
1558
|
+
return this.find(alias).play(options);
|
|
1559
|
+
}
|
|
1560
|
+
stop(alias) {
|
|
1561
|
+
return this.find(alias).stop();
|
|
1562
|
+
}
|
|
1563
|
+
pause(alias) {
|
|
1564
|
+
return this.find(alias).pause();
|
|
1565
|
+
}
|
|
1566
|
+
resume(alias) {
|
|
1567
|
+
return this.find(alias).resume();
|
|
1568
|
+
}
|
|
1569
|
+
volume(alias, volume) {
|
|
1570
|
+
const sound = this.find(alias);
|
|
1571
|
+
if (volume !== void 0) {
|
|
1572
|
+
sound.volume = volume;
|
|
1573
|
+
}
|
|
1574
|
+
return sound.volume;
|
|
1575
|
+
}
|
|
1576
|
+
speed(alias, speed) {
|
|
1577
|
+
const sound = this.find(alias);
|
|
1578
|
+
if (speed !== void 0) {
|
|
1579
|
+
sound.speed = speed;
|
|
1580
|
+
}
|
|
1581
|
+
return sound.speed;
|
|
1582
|
+
}
|
|
1583
|
+
duration(alias) {
|
|
1584
|
+
return this.find(alias).duration;
|
|
1585
|
+
}
|
|
1586
|
+
close() {
|
|
1587
|
+
this.removeAll();
|
|
1588
|
+
this._sounds = null;
|
|
1589
|
+
if (this._webAudioContext) {
|
|
1590
|
+
this._webAudioContext.destroy();
|
|
1591
|
+
this._webAudioContext = null;
|
|
1592
|
+
}
|
|
1593
|
+
if (this._htmlAudioContext) {
|
|
1594
|
+
this._htmlAudioContext.destroy();
|
|
1595
|
+
this._htmlAudioContext = null;
|
|
1596
|
+
}
|
|
1597
|
+
this._context = null;
|
|
1598
|
+
return this;
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
const getAlias = asset => {
|
|
1602
|
+
var _asset$alias;
|
|
1603
|
+
const src = asset.src;
|
|
1604
|
+
let alias = asset === null || asset === void 0 ? void 0 : (_asset$alias = asset.alias) === null || _asset$alias === void 0 ? void 0 : _asset$alias[0];
|
|
1605
|
+
if (!alias || asset.src === alias) {
|
|
1606
|
+
alias = pixi_js.path.basename(src, pixi_js.path.extname(src));
|
|
1607
|
+
}
|
|
1608
|
+
return alias;
|
|
1609
|
+
};
|
|
1610
|
+
const soundAsset = {
|
|
1611
|
+
extension: pixi_js.ExtensionType.Asset,
|
|
1612
|
+
detection: {
|
|
1613
|
+
test: async () => true,
|
|
1614
|
+
add: async formats => [...formats, ...extensions.filter(ext => supported[ext])],
|
|
1615
|
+
remove: async formats => formats.filter(ext => formats.includes(ext))
|
|
1616
|
+
},
|
|
1617
|
+
loader: {
|
|
1618
|
+
name: "sound",
|
|
1619
|
+
extension: {
|
|
1620
|
+
type: [pixi_js.ExtensionType.LoadParser],
|
|
1621
|
+
priority: pixi_js.LoaderParserPriority.High
|
|
1622
|
+
},
|
|
1623
|
+
test(url) {
|
|
1624
|
+
const ext = pixi_js.path.extname(url).slice(1);
|
|
1625
|
+
return !!supported[ext] || mimes.some(mime => url.startsWith(`data:${mime}`));
|
|
1626
|
+
},
|
|
1627
|
+
async load(url, asset) {
|
|
1628
|
+
const sound = await new Promise((resolve, reject) => Sound$2.from(_objectSpread(_objectSpread({}, asset.data), {}, {
|
|
1629
|
+
url,
|
|
1630
|
+
preload: true,
|
|
1631
|
+
loaded(err, sound2) {
|
|
1632
|
+
var _asset$data, _asset$data$loaded;
|
|
1633
|
+
if (err) {
|
|
1634
|
+
reject(err);
|
|
1635
|
+
} else {
|
|
1636
|
+
resolve(sound2);
|
|
1637
|
+
}
|
|
1638
|
+
(_asset$data = asset.data) === null || _asset$data === void 0 ? void 0 : (_asset$data$loaded = _asset$data.loaded) === null || _asset$data$loaded === void 0 ? void 0 : _asset$data$loaded.call(_asset$data, err, sound2);
|
|
1639
|
+
}
|
|
1640
|
+
})));
|
|
1641
|
+
getInstance().add(getAlias(asset), sound);
|
|
1642
|
+
return sound;
|
|
1643
|
+
},
|
|
1644
|
+
async unload(_sound, asset) {
|
|
1645
|
+
getInstance().remove(getAlias(asset));
|
|
1646
|
+
}
|
|
1647
|
+
}
|
|
1648
|
+
};
|
|
1649
|
+
pixi_js.extensions.add(soundAsset);
|
|
1650
|
+
const sound = setInstance(new SoundLibrary());
|
|
1651
|
+
sound.disableAutoPause = true;
|
|
1652
|
+
extensions.push('aac');
|
|
1653
|
+
validateFormats({
|
|
1654
|
+
aac: 'audio/aac'
|
|
1655
|
+
});
|
|
1656
|
+
pixi_js.extensions.add(soundAsset);
|
|
1657
|
+
let SoundSystem = class SoundSystem extends eva_js.System {
|
|
1658
|
+
constructor(obj) {
|
|
1659
|
+
super();
|
|
1660
|
+
this.autoPauseAndStart = true;
|
|
1661
|
+
this.components = [];
|
|
1662
|
+
this.audioBufferCache = {};
|
|
1663
|
+
_extends(this, obj);
|
|
1664
|
+
if (obj === null || obj === void 0 ? void 0 : obj.useLegacy) {
|
|
1665
|
+
sound.useLegacy = true;
|
|
1666
|
+
}
|
|
1667
|
+
}
|
|
1668
|
+
resumeAll() {
|
|
1669
|
+
sound.resumeAll();
|
|
1670
|
+
}
|
|
1671
|
+
pauseAll() {
|
|
1672
|
+
sound.pauseAll();
|
|
1673
|
+
}
|
|
1674
|
+
stopAll() {
|
|
1675
|
+
sound.stopAll();
|
|
103
1676
|
}
|
|
104
1677
|
update() {
|
|
105
1678
|
const changes = this.componentObserver.clear();
|
|
@@ -124,12 +1697,7 @@ var _EVA_IIFE_sound = function (exports, eva_js) {
|
|
|
124
1697
|
component.onDestroy();
|
|
125
1698
|
});
|
|
126
1699
|
this.components = [];
|
|
127
|
-
|
|
128
|
-
this.gainNode.disconnect();
|
|
129
|
-
this.gainNode = null;
|
|
130
|
-
this.ctx.close();
|
|
131
|
-
this.ctx = null;
|
|
132
|
-
}
|
|
1700
|
+
sound.removeAll();
|
|
133
1701
|
}
|
|
134
1702
|
componentChanged(changed) {
|
|
135
1703
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -139,44 +1707,8 @@ var _EVA_IIFE_sound = function (exports, eva_js) {
|
|
|
139
1707
|
}
|
|
140
1708
|
});
|
|
141
1709
|
}
|
|
142
|
-
setupAudioContext() {
|
|
143
|
-
try {
|
|
144
|
-
const AudioContext = window.AudioContext || window.webkitAudioContext;
|
|
145
|
-
this.ctx = new AudioContext();
|
|
146
|
-
} catch (error) {
|
|
147
|
-
console.error(error);
|
|
148
|
-
if (this.onError) {
|
|
149
|
-
this.onError(error);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
if (!this.ctx) {
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
this.gainNode = typeof this.ctx.createGain === 'undefined' ? this.ctx.createGainNode() : this.ctx.createGain();
|
|
156
|
-
this.gainNode.gain.setValueAtTime(this.muted ? 0 : this.volume, this.ctx.currentTime);
|
|
157
|
-
this.gainNode.connect(this.ctx.destination);
|
|
158
|
-
this.unlockAudio();
|
|
159
|
-
}
|
|
160
|
-
unlockAudio() {
|
|
161
|
-
if (!this.ctx || !this.audioLocked) {
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
const unlock = () => {
|
|
165
|
-
if (this.ctx) {
|
|
166
|
-
const removeListenerFn = () => {
|
|
167
|
-
document.body.removeEventListener('touchstart', unlock);
|
|
168
|
-
document.body.removeEventListener('touchend', unlock);
|
|
169
|
-
document.body.removeEventListener('click', unlock);
|
|
170
|
-
};
|
|
171
|
-
this.ctx.resume().then(removeListenerFn, removeListenerFn);
|
|
172
|
-
}
|
|
173
|
-
};
|
|
174
|
-
document.body.addEventListener('touchstart', unlock);
|
|
175
|
-
document.body.addEventListener('touchend', unlock);
|
|
176
|
-
document.body.addEventListener('click', unlock);
|
|
177
|
-
}
|
|
178
1710
|
add(changed) {
|
|
179
|
-
var _a;
|
|
1711
|
+
var _a, _b;
|
|
180
1712
|
return __awaiter(this, void 0, void 0, function* () {
|
|
181
1713
|
const component = changed.component;
|
|
182
1714
|
this.components.push(component);
|
|
@@ -187,11 +1719,9 @@ var _EVA_IIFE_sound = function (exports, eva_js) {
|
|
|
187
1719
|
component.state = 'loading';
|
|
188
1720
|
const audio = yield eva_js.resource.getResource(config.resource);
|
|
189
1721
|
if (!this.audioBufferCache[audio.name] && ((_a = audio === null || audio === void 0 ? void 0 : audio.data) === null || _a === void 0 ? void 0 : _a.audio)) {
|
|
190
|
-
this.audioBufferCache[audio.name] =
|
|
1722
|
+
this.audioBufferCache[audio.name] = (_b = audio === null || audio === void 0 ? void 0 : audio.data) === null || _b === void 0 ? void 0 : _b.audio;
|
|
191
1723
|
}
|
|
192
1724
|
if (this.audioBufferCache[audio.name]) {
|
|
193
|
-
component.systemContext = this.ctx;
|
|
194
|
-
component.systemDestination = this.gainNode;
|
|
195
1725
|
component.onload(this.audioBufferCache[audio.name]);
|
|
196
1726
|
}
|
|
197
1727
|
} catch (error) {
|
|
@@ -201,40 +1731,6 @@ var _EVA_IIFE_sound = function (exports, eva_js) {
|
|
|
201
1731
|
}
|
|
202
1732
|
});
|
|
203
1733
|
}
|
|
204
|
-
decodeAudioData(arraybuffer, name) {
|
|
205
|
-
if (this.decodeAudioPromiseMap[name]) {
|
|
206
|
-
return this.decodeAudioPromiseMap[name];
|
|
207
|
-
}
|
|
208
|
-
const promise = new Promise((resolve, reject) => {
|
|
209
|
-
if (!this.ctx) {
|
|
210
|
-
reject(new Error('No audio support'));
|
|
211
|
-
}
|
|
212
|
-
const success = decodedData => {
|
|
213
|
-
if (this.decodeAudioPromiseMap[name]) {
|
|
214
|
-
delete this.decodeAudioPromiseMap[name];
|
|
215
|
-
}
|
|
216
|
-
if (decodedData) {
|
|
217
|
-
resolve(decodedData);
|
|
218
|
-
} else {
|
|
219
|
-
reject(new Error(`Error decoding audio ${name}`));
|
|
220
|
-
}
|
|
221
|
-
};
|
|
222
|
-
const error = err => {
|
|
223
|
-
if (this.decodeAudioPromiseMap[name]) {
|
|
224
|
-
delete this.decodeAudioPromiseMap[name];
|
|
225
|
-
}
|
|
226
|
-
reject(new Error(`${err}. arrayBuffer byteLength: ${arraybuffer ? arraybuffer.byteLength : 0}`));
|
|
227
|
-
};
|
|
228
|
-
const promise = this.ctx.decodeAudioData(arraybuffer, success, error);
|
|
229
|
-
if (promise instanceof Promise) {
|
|
230
|
-
promise.catch(err => {
|
|
231
|
-
reject(new Error(`catch ${err}, arrayBuffer byteLength: ${arraybuffer ? arraybuffer.byteLength : 0}`));
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
});
|
|
235
|
-
this.decodeAudioPromiseMap[name] = promise;
|
|
236
|
-
return promise;
|
|
237
|
-
}
|
|
238
1734
|
};
|
|
239
1735
|
SoundSystem.systemName = 'SoundSystem';
|
|
240
1736
|
SoundSystem = __decorate([eva_js.decorators.componentObserver({
|
|
@@ -251,34 +1747,32 @@ var _EVA_IIFE_sound = function (exports, eva_js) {
|
|
|
251
1747
|
muted: false,
|
|
252
1748
|
volume: 1,
|
|
253
1749
|
loop: false,
|
|
254
|
-
seek: 0
|
|
1750
|
+
seek: 0,
|
|
1751
|
+
speed: 1
|
|
255
1752
|
};
|
|
256
|
-
this.playTime = 0;
|
|
257
|
-
this.startTime = 0;
|
|
258
|
-
this.duration = 0;
|
|
259
1753
|
this.actionQueue = [];
|
|
1754
|
+
this.startTime = 0;
|
|
1755
|
+
}
|
|
1756
|
+
get systemContext() {
|
|
1757
|
+
return sound.context.audioContext;
|
|
1758
|
+
}
|
|
1759
|
+
get playing() {
|
|
1760
|
+
if (!this.buffer) return false;
|
|
1761
|
+
return this.buffer.isPlaying;
|
|
260
1762
|
}
|
|
261
1763
|
get muted() {
|
|
262
|
-
|
|
1764
|
+
var _a;
|
|
1765
|
+
return ((_a = this.buffer) === null || _a === void 0 ? void 0 : _a.muted) || false;
|
|
263
1766
|
}
|
|
264
1767
|
set muted(v) {
|
|
265
|
-
if (
|
|
266
|
-
return;
|
|
267
|
-
}
|
|
268
|
-
this.gainNode.gain.setValueAtTime(v ? 0 : this.config.volume, 0);
|
|
1768
|
+
if (this.buffer) this.buffer.muted = v;
|
|
269
1769
|
}
|
|
270
1770
|
get volume() {
|
|
271
|
-
|
|
1771
|
+
var _a;
|
|
1772
|
+
return ((_a = this.buffer) === null || _a === void 0 ? void 0 : _a.volume) || 0;
|
|
272
1773
|
}
|
|
273
1774
|
set volume(v) {
|
|
274
|
-
if (
|
|
275
|
-
return;
|
|
276
|
-
}
|
|
277
|
-
this.config.volume = v;
|
|
278
|
-
if (!this.gainNode) {
|
|
279
|
-
return;
|
|
280
|
-
}
|
|
281
|
-
this.gainNode.gain.setValueAtTime(v, 0);
|
|
1775
|
+
if (this.buffer) this.buffer.volume = v;
|
|
282
1776
|
}
|
|
283
1777
|
init(obj) {
|
|
284
1778
|
if (!obj) {
|
|
@@ -293,100 +1787,39 @@ var _EVA_IIFE_sound = function (exports, eva_js) {
|
|
|
293
1787
|
if (this.state !== 'loaded') {
|
|
294
1788
|
this.actionQueue.push(this.play.bind(this));
|
|
295
1789
|
}
|
|
296
|
-
this.
|
|
297
|
-
this.
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
const duration = this.config.duration;
|
|
304
|
-
this.sourceNode.start(0, offset, duration);
|
|
305
|
-
this.startTime = when;
|
|
306
|
-
this.playTime = when - offset;
|
|
307
|
-
this.paused = false;
|
|
308
|
-
this.playing = true;
|
|
309
|
-
this.resetConfig();
|
|
310
|
-
this.endedListener = () => {
|
|
311
|
-
if (!this.sourceNode) {
|
|
312
|
-
return;
|
|
313
|
-
}
|
|
314
|
-
if (this.config.onEnd) {
|
|
315
|
-
this.config.onEnd();
|
|
316
|
-
}
|
|
317
|
-
if (this.playing) {
|
|
318
|
-
this.destroySource();
|
|
319
|
-
}
|
|
320
|
-
};
|
|
321
|
-
this.sourceNode.addEventListener('ended', this.endedListener);
|
|
1790
|
+
if (!this.buffer) return;
|
|
1791
|
+
this.startTime = this.systemContext.currentTime;
|
|
1792
|
+
this.buffer.play();
|
|
1793
|
+
}
|
|
1794
|
+
resume() {
|
|
1795
|
+
if (!this.buffer) return;
|
|
1796
|
+
this.buffer.resume();
|
|
322
1797
|
}
|
|
323
1798
|
pause() {
|
|
324
|
-
if (this.
|
|
325
|
-
|
|
326
|
-
}
|
|
327
|
-
if (this.paused || !this.playing) {
|
|
328
|
-
return;
|
|
329
|
-
}
|
|
330
|
-
this.paused = true;
|
|
331
|
-
this.playing = false;
|
|
332
|
-
this.config.seek = this.getCurrentTime();
|
|
333
|
-
this.destroySource();
|
|
1799
|
+
if (!this.buffer) return;
|
|
1800
|
+
this.buffer.pause();
|
|
334
1801
|
}
|
|
335
1802
|
stop() {
|
|
336
|
-
if (this.
|
|
337
|
-
|
|
338
|
-
}
|
|
339
|
-
if (!this.paused && !this.playing) {
|
|
340
|
-
return;
|
|
341
|
-
}
|
|
342
|
-
this.playing = false;
|
|
343
|
-
this.paused = false;
|
|
344
|
-
this.destroySource();
|
|
345
|
-
this.resetConfig();
|
|
1803
|
+
if (!this.buffer) return;
|
|
1804
|
+
this.buffer.stop();
|
|
346
1805
|
}
|
|
347
1806
|
onload(buffer) {
|
|
348
1807
|
this.state = 'loaded';
|
|
349
1808
|
this.buffer = buffer;
|
|
350
|
-
this.
|
|
1809
|
+
this.buffer.muted = this.config.muted;
|
|
1810
|
+
this.buffer.volume = this.config.volume;
|
|
1811
|
+
this.buffer.loop = this.config.loop;
|
|
1812
|
+
this.buffer.speed = this.config.speed;
|
|
351
1813
|
this.actionQueue.forEach(action => action());
|
|
352
1814
|
this.actionQueue.length = 0;
|
|
353
1815
|
}
|
|
354
1816
|
onDestroy() {
|
|
355
1817
|
this.actionQueue.length = 0;
|
|
356
|
-
this.destroySource();
|
|
357
|
-
}
|
|
358
|
-
resetConfig() {
|
|
359
|
-
this.config.seek = 0;
|
|
360
|
-
}
|
|
361
|
-
getCurrentTime() {
|
|
362
|
-
if (this.config.loop && this.duration > 0) {
|
|
363
|
-
return (this.systemContext.currentTime - this.playTime) % this.duration;
|
|
364
|
-
}
|
|
365
|
-
return this.systemContext.currentTime - this.playTime;
|
|
366
|
-
}
|
|
367
|
-
createSource() {
|
|
368
|
-
if (!this.systemContext || this.state !== 'loaded') {
|
|
369
|
-
return;
|
|
370
|
-
}
|
|
371
|
-
this.sourceNode = this.systemContext.createBufferSource();
|
|
372
|
-
this.sourceNode.buffer = this.buffer;
|
|
373
|
-
this.sourceNode.loop = this.config.loop;
|
|
374
|
-
if (!this.gainNode) {
|
|
375
|
-
this.gainNode = this.systemContext.createGain();
|
|
376
|
-
this.gainNode.connect(this.systemDestination);
|
|
377
|
-
_extends(this, this.config);
|
|
378
|
-
}
|
|
379
|
-
this.sourceNode.connect(this.gainNode);
|
|
380
|
-
}
|
|
381
|
-
destroySource() {
|
|
382
|
-
if (!this.sourceNode) return;
|
|
383
|
-
this.sourceNode.removeEventListener('ended', this.endedListener);
|
|
384
|
-
this.sourceNode.stop();
|
|
385
|
-
this.sourceNode.disconnect();
|
|
386
|
-
this.sourceNode = null;
|
|
387
1818
|
this.startTime = 0;
|
|
388
|
-
this.
|
|
389
|
-
|
|
1819
|
+
if (this.buffer) {
|
|
1820
|
+
this.buffer.destroy();
|
|
1821
|
+
this.buffer = null;
|
|
1822
|
+
}
|
|
390
1823
|
}
|
|
391
1824
|
}
|
|
392
1825
|
Sound.componentName = 'Sound';
|
|
@@ -397,5 +1830,5 @@ var _EVA_IIFE_sound = function (exports, eva_js) {
|
|
|
397
1830
|
value: true
|
|
398
1831
|
});
|
|
399
1832
|
return exports;
|
|
400
|
-
}({}, EVA);
|
|
401
|
-
|
|
1833
|
+
}({}, EVA, PIXI);
|
|
1834
|
+
globalThis.EVA.plugin.sound = globalThis.EVA.plugin.sound || _EVA_IIFE_sound;
|