@tsparticles/plugin-sounds 4.0.0-alpha.8 → 4.0.0-beta.1
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/4.min.js +1 -0
- package/414.min.js +33 -0
- package/browser/Options/Classes/Sounds.js +5 -0
- package/browser/Options/Classes/SoundsAudio.js +2 -0
- package/browser/Options/Classes/SoundsEvent.js +5 -0
- package/browser/Options/Classes/SoundsIcon.js +5 -0
- package/browser/Options/Classes/SoundsIcons.js +5 -0
- package/browser/Options/Classes/SoundsMelody.js +3 -0
- package/browser/Options/Classes/SoundsNote.js +2 -0
- package/browser/Options/Classes/SoundsVolume.js +4 -0
- package/browser/SoundsPlugin.js +2 -1
- package/browser/SoundsPluginInstance.js +246 -237
- package/browser/index.js +3 -3
- package/cjs/Options/Classes/Sounds.js +5 -0
- package/cjs/Options/Classes/SoundsAudio.js +2 -0
- package/cjs/Options/Classes/SoundsEvent.js +5 -0
- package/cjs/Options/Classes/SoundsIcon.js +5 -0
- package/cjs/Options/Classes/SoundsIcons.js +5 -0
- package/cjs/Options/Classes/SoundsMelody.js +3 -0
- package/cjs/Options/Classes/SoundsNote.js +2 -0
- package/cjs/Options/Classes/SoundsVolume.js +4 -0
- package/cjs/SoundsPlugin.js +2 -1
- package/cjs/SoundsPluginInstance.js +246 -237
- package/cjs/index.js +3 -3
- package/dist_browser_SoundsPluginInstance_js.js +3 -3
- package/dist_browser_SoundsPlugin_js.js +12 -12
- package/esm/Options/Classes/Sounds.js +5 -0
- package/esm/Options/Classes/SoundsAudio.js +2 -0
- package/esm/Options/Classes/SoundsEvent.js +5 -0
- package/esm/Options/Classes/SoundsIcon.js +5 -0
- package/esm/Options/Classes/SoundsIcons.js +5 -0
- package/esm/Options/Classes/SoundsMelody.js +3 -0
- package/esm/Options/Classes/SoundsNote.js +2 -0
- package/esm/Options/Classes/SoundsVolume.js +4 -0
- package/esm/SoundsPlugin.js +2 -1
- package/esm/SoundsPluginInstance.js +246 -237
- package/esm/index.js +3 -3
- package/package.json +2 -2
- package/report.html +84 -29
- package/tsparticles.plugin.sounds.js +31 -19
- package/tsparticles.plugin.sounds.min.js +2 -2
- package/types/SoundsPlugin.d.ts +1 -1
- package/umd/Options/Classes/Sounds.js +5 -0
- package/umd/Options/Classes/SoundsAudio.js +2 -0
- package/umd/Options/Classes/SoundsEvent.js +5 -0
- package/umd/Options/Classes/SoundsIcon.js +5 -0
- package/umd/Options/Classes/SoundsIcons.js +5 -0
- package/umd/Options/Classes/SoundsMelody.js +3 -0
- package/umd/Options/Classes/SoundsNote.js +2 -0
- package/umd/Options/Classes/SoundsVolume.js +4 -0
- package/umd/SoundsPlugin.js +2 -1
- package/umd/SoundsPluginInstance.js +246 -237
- package/umd/index.js +3 -3
- package/296.min.js +0 -2
- package/296.min.js.LICENSE.txt +0 -1
- package/340.min.js +0 -2
- package/340.min.js.LICENSE.txt +0 -1
- package/tsparticles.plugin.sounds.min.js.LICENSE.txt +0 -1
package/browser/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export async function loadSoundsPlugin(engine) {
|
|
2
|
-
engine.checkVersion("4.0.0-
|
|
3
|
-
await engine.register(async (e) => {
|
|
2
|
+
engine.checkVersion("4.0.0-beta.1");
|
|
3
|
+
await engine.pluginManager.register(async (e) => {
|
|
4
4
|
const { SoundsPlugin } = await import("./SoundsPlugin.js");
|
|
5
|
-
e.addPlugin(new SoundsPlugin(
|
|
5
|
+
e.pluginManager.addPlugin(new SoundsPlugin(e));
|
|
6
6
|
});
|
|
7
7
|
}
|
|
@@ -3,6 +3,11 @@ import { SoundsEvent } from "./SoundsEvent.js";
|
|
|
3
3
|
import { SoundsIcons } from "./SoundsIcons.js";
|
|
4
4
|
import { SoundsVolume } from "./SoundsVolume.js";
|
|
5
5
|
export class Sounds {
|
|
6
|
+
autoPlay;
|
|
7
|
+
enable;
|
|
8
|
+
events;
|
|
9
|
+
icons;
|
|
10
|
+
volume;
|
|
6
11
|
constructor() {
|
|
7
12
|
this.autoPlay = true;
|
|
8
13
|
this.enable = false;
|
|
@@ -3,6 +3,11 @@ import { SoundsAudio } from "./SoundsAudio.js";
|
|
|
3
3
|
import { SoundsMelody } from "./SoundsMelody.js";
|
|
4
4
|
import { SoundsNote } from "./SoundsNote.js";
|
|
5
5
|
export class SoundsEvent {
|
|
6
|
+
audio;
|
|
7
|
+
event;
|
|
8
|
+
filter;
|
|
9
|
+
melodies;
|
|
10
|
+
notes;
|
|
6
11
|
constructor() {
|
|
7
12
|
this.event = [];
|
|
8
13
|
this.notes = [];
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { isNull } from "@tsparticles/engine";
|
|
2
2
|
import { SoundsIcon } from "./SoundsIcon.js";
|
|
3
3
|
export class SoundsIcons {
|
|
4
|
+
enable;
|
|
5
|
+
mute;
|
|
6
|
+
unmute;
|
|
7
|
+
volumeDown;
|
|
8
|
+
volumeUp;
|
|
4
9
|
constructor() {
|
|
5
10
|
this.mute = new SoundsIcon();
|
|
6
11
|
this.unmute = new SoundsIcon();
|
package/cjs/SoundsPlugin.js
CHANGED
|
@@ -31,242 +31,17 @@ function setIconStyle(icon, top, left, display, zIndex, width, margin, style) {
|
|
|
31
31
|
icon.style.cssText += style;
|
|
32
32
|
}
|
|
33
33
|
export class SoundsPluginInstance {
|
|
34
|
+
_audioMap;
|
|
35
|
+
_audioSources;
|
|
36
|
+
_container;
|
|
37
|
+
_engine;
|
|
38
|
+
_gain;
|
|
39
|
+
_muteImg;
|
|
40
|
+
_unmuteImg;
|
|
41
|
+
_volume;
|
|
42
|
+
_volumeDownImg;
|
|
43
|
+
_volumeUpImg;
|
|
34
44
|
constructor(container, engine) {
|
|
35
|
-
this._addBuffer = audioCtx => {
|
|
36
|
-
const buffer = audioCtx.createBufferSource();
|
|
37
|
-
this._audioSources.push(buffer);
|
|
38
|
-
return buffer;
|
|
39
|
-
};
|
|
40
|
-
this._addOscillator = audioCtx => {
|
|
41
|
-
const oscillator = audioCtx.createOscillator();
|
|
42
|
-
this._audioSources.push(oscillator);
|
|
43
|
-
return oscillator;
|
|
44
|
-
};
|
|
45
|
-
this._initEvents = () => {
|
|
46
|
-
const container = this._container, soundsOptions = container.actualOptions.sounds;
|
|
47
|
-
if (!soundsOptions?.enable || !container.canvas.element) {
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
for (const event of soundsOptions.events) {
|
|
51
|
-
const cb = (args) => {
|
|
52
|
-
if (!args) {
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
void (async () => {
|
|
56
|
-
const filterNotValid = event.filter && !event.filter(args);
|
|
57
|
-
if (this._container !== args.container) {
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
if (!!this._container.muted || this._container.destroyed) {
|
|
61
|
-
executeOnSingleOrMultiple(event.event, item => {
|
|
62
|
-
this._engine.removeEventListener(item, cb);
|
|
63
|
-
});
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
if (filterNotValid) {
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
const defaultNoteIndex = 0;
|
|
70
|
-
if (event.audio) {
|
|
71
|
-
const audio = itemFromSingleOrMultiple(event.audio);
|
|
72
|
-
if (!audio) {
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
this._playBuffer(audio);
|
|
76
|
-
}
|
|
77
|
-
else if (event.melodies) {
|
|
78
|
-
const melody = itemFromArray(event.melodies);
|
|
79
|
-
if (!melody) {
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
if (melody.melodies.length) {
|
|
83
|
-
await Promise.allSettled(melody.melodies.map(m => this._playNote(m.notes, defaultNoteIndex, melody.loop)));
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
await this._playNote(melody.notes, defaultNoteIndex, melody.loop);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
else if (event.notes) {
|
|
90
|
-
const note = itemFromArray(event.notes);
|
|
91
|
-
if (!note) {
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
await this._playNote([note], defaultNoteIndex, false);
|
|
95
|
-
}
|
|
96
|
-
})();
|
|
97
|
-
};
|
|
98
|
-
executeOnSingleOrMultiple(event.event, item => {
|
|
99
|
-
this._engine.addEventListener(item, cb);
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
};
|
|
103
|
-
this._mute = async () => {
|
|
104
|
-
const container = this._container, audioContext = this._getAudioContext();
|
|
105
|
-
for (const source of this._audioSources) {
|
|
106
|
-
this._removeAudioSource(source);
|
|
107
|
-
}
|
|
108
|
-
if (this._gain) {
|
|
109
|
-
this._gain.disconnect();
|
|
110
|
-
}
|
|
111
|
-
await audioContext.close();
|
|
112
|
-
container.audioContext = undefined;
|
|
113
|
-
this._engine.dispatchEvent(SoundsEventType.mute, { container: this._container });
|
|
114
|
-
};
|
|
115
|
-
this._playBuffer = audio => {
|
|
116
|
-
const audioBuffer = this._audioMap.get(audio.source);
|
|
117
|
-
if (!audioBuffer) {
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
const audioCtx = this._container.audioContext;
|
|
121
|
-
if (!audioCtx) {
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
const source = this._addBuffer(audioCtx);
|
|
125
|
-
source.loop = audio.loop;
|
|
126
|
-
source.buffer = audioBuffer;
|
|
127
|
-
source.connect(this._gain ?? audioCtx.destination);
|
|
128
|
-
source.start();
|
|
129
|
-
};
|
|
130
|
-
this._playFrequency = async (frequency, duration) => {
|
|
131
|
-
if (!this._gain || this._container.muted) {
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
const audioContext = this._getAudioContext(), oscillator = this._addOscillator(audioContext);
|
|
135
|
-
oscillator.connect(this._gain);
|
|
136
|
-
oscillator.type = "sine";
|
|
137
|
-
oscillator.frequency.value = frequency;
|
|
138
|
-
oscillator.start();
|
|
139
|
-
return new Promise(resolve => {
|
|
140
|
-
setTimeout(() => {
|
|
141
|
-
this._removeAudioSource(oscillator);
|
|
142
|
-
resolve();
|
|
143
|
-
}, duration);
|
|
144
|
-
});
|
|
145
|
-
};
|
|
146
|
-
this._playMuteSound = () => {
|
|
147
|
-
if (this._container.muted) {
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
const audioContext = this._getAudioContext(), gain = audioContext.createGain();
|
|
151
|
-
gain.connect(audioContext.destination);
|
|
152
|
-
gain.gain.value = 0;
|
|
153
|
-
const oscillator = audioContext.createOscillator();
|
|
154
|
-
oscillator.connect(gain);
|
|
155
|
-
oscillator.type = "sine";
|
|
156
|
-
oscillator.frequency.value = 1;
|
|
157
|
-
oscillator.start();
|
|
158
|
-
setTimeout(() => {
|
|
159
|
-
oscillator.stop();
|
|
160
|
-
oscillator.disconnect();
|
|
161
|
-
gain.disconnect();
|
|
162
|
-
});
|
|
163
|
-
};
|
|
164
|
-
this._playNote = async (notes, noteIdx, loop) => {
|
|
165
|
-
if (this._container.muted) {
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
const note = notes[noteIdx];
|
|
169
|
-
if (!note) {
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
const value = note.value, promises = executeOnSingleOrMultiple(value, async (_, idx) => {
|
|
173
|
-
return this._playNoteValue(notes, noteIdx, idx);
|
|
174
|
-
});
|
|
175
|
-
await (isArray(promises) ? Promise.allSettled(promises) : promises);
|
|
176
|
-
const indexOffset = 1;
|
|
177
|
-
let nextNoteIdx = noteIdx + indexOffset;
|
|
178
|
-
if (loop && nextNoteIdx >= notes.length) {
|
|
179
|
-
nextNoteIdx = nextNoteIdx % notes.length;
|
|
180
|
-
}
|
|
181
|
-
await this._playNote(notes, nextNoteIdx, loop);
|
|
182
|
-
};
|
|
183
|
-
this._playNoteValue = async (notes, noteIdx, valueIdx) => {
|
|
184
|
-
const note = notes[noteIdx];
|
|
185
|
-
if (!note) {
|
|
186
|
-
return;
|
|
187
|
-
}
|
|
188
|
-
const value = itemFromSingleOrMultiple(note.value, valueIdx, true);
|
|
189
|
-
if (!value) {
|
|
190
|
-
return;
|
|
191
|
-
}
|
|
192
|
-
try {
|
|
193
|
-
const freq = getNoteFrequency(value);
|
|
194
|
-
if (!isNumber(freq)) {
|
|
195
|
-
return;
|
|
196
|
-
}
|
|
197
|
-
await this._playFrequency(freq, note.duration);
|
|
198
|
-
}
|
|
199
|
-
catch (e) {
|
|
200
|
-
getLogger().error(e);
|
|
201
|
-
}
|
|
202
|
-
};
|
|
203
|
-
this._removeAudioSource = source => {
|
|
204
|
-
source.stop();
|
|
205
|
-
source.disconnect();
|
|
206
|
-
const deleteCount = 1;
|
|
207
|
-
this._audioSources.splice(this._audioSources.indexOf(source), deleteCount);
|
|
208
|
-
};
|
|
209
|
-
this._unmute = () => {
|
|
210
|
-
const container = this._container, options = container.actualOptions, soundsOptions = options.sounds;
|
|
211
|
-
if (!soundsOptions) {
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
const audioContext = this._getAudioContext(), gain = audioContext.createGain();
|
|
215
|
-
gain.connect(audioContext.destination);
|
|
216
|
-
gain.gain.value = soundsOptions.volume.value / percentDenominator;
|
|
217
|
-
this._gain = gain;
|
|
218
|
-
this._initEvents();
|
|
219
|
-
this._engine.dispatchEvent(SoundsEventType.unmute, { container: this._container });
|
|
220
|
-
};
|
|
221
|
-
this._updateMuteIcons = () => {
|
|
222
|
-
const container = this._container, soundsOptions = container.actualOptions.sounds;
|
|
223
|
-
if (!soundsOptions?.enable || !soundsOptions.icons.enable) {
|
|
224
|
-
return;
|
|
225
|
-
}
|
|
226
|
-
const muteImg = this._muteImg, unmuteImg = this._unmuteImg;
|
|
227
|
-
if (muteImg) {
|
|
228
|
-
muteImg.style.display = container.muted ? "block" : "none";
|
|
229
|
-
}
|
|
230
|
-
if (unmuteImg) {
|
|
231
|
-
unmuteImg.style.display = container.muted ? "none" : "block";
|
|
232
|
-
}
|
|
233
|
-
};
|
|
234
|
-
this._updateMuteStatus = async () => {
|
|
235
|
-
const container = this._container, audioContext = this._getAudioContext();
|
|
236
|
-
if (container.muted) {
|
|
237
|
-
await audioContext.suspend();
|
|
238
|
-
await this._mute();
|
|
239
|
-
}
|
|
240
|
-
else {
|
|
241
|
-
await audioContext.resume();
|
|
242
|
-
this._unmute();
|
|
243
|
-
this._playMuteSound();
|
|
244
|
-
}
|
|
245
|
-
};
|
|
246
|
-
this._updateVolume = async () => {
|
|
247
|
-
const container = this._container, soundsOptions = container.actualOptions.sounds;
|
|
248
|
-
if (!soundsOptions?.enable) {
|
|
249
|
-
return;
|
|
250
|
-
}
|
|
251
|
-
clamp(this._volume, soundsOptions.volume.min, soundsOptions.volume.max);
|
|
252
|
-
let stateChanged = false;
|
|
253
|
-
if (this._volume <= minVolume && !container.muted) {
|
|
254
|
-
this._volume = 0;
|
|
255
|
-
container.muted = true;
|
|
256
|
-
stateChanged = true;
|
|
257
|
-
}
|
|
258
|
-
else if (this._volume > minVolume && container.muted) {
|
|
259
|
-
container.muted = false;
|
|
260
|
-
stateChanged = true;
|
|
261
|
-
}
|
|
262
|
-
if (stateChanged) {
|
|
263
|
-
this._updateMuteIcons();
|
|
264
|
-
await this._updateMuteStatus();
|
|
265
|
-
}
|
|
266
|
-
if (this._gain?.gain) {
|
|
267
|
-
this._gain.gain.value = this._volume / percentDenominator;
|
|
268
|
-
}
|
|
269
|
-
};
|
|
270
45
|
this._container = container;
|
|
271
46
|
this._engine = engine;
|
|
272
47
|
this._volume = 0;
|
|
@@ -284,8 +59,7 @@ export class SoundsPluginInstance {
|
|
|
284
59
|
removeEventListener(touchStartEvent, firstClickHandler);
|
|
285
60
|
unmuteWindow();
|
|
286
61
|
void this.unmute();
|
|
287
|
-
}
|
|
288
|
-
const listenerOptions = {
|
|
62
|
+
}, listenerOptions = {
|
|
289
63
|
capture: true,
|
|
290
64
|
once: true,
|
|
291
65
|
};
|
|
@@ -420,9 +194,244 @@ export class SoundsPluginInstance {
|
|
|
420
194
|
this._volume += soundsOptions.volume.step;
|
|
421
195
|
await this._updateVolume();
|
|
422
196
|
}
|
|
197
|
+
_addBuffer = audioCtx => {
|
|
198
|
+
const buffer = audioCtx.createBufferSource();
|
|
199
|
+
this._audioSources.push(buffer);
|
|
200
|
+
return buffer;
|
|
201
|
+
};
|
|
202
|
+
_addOscillator = audioCtx => {
|
|
203
|
+
const oscillator = audioCtx.createOscillator();
|
|
204
|
+
this._audioSources.push(oscillator);
|
|
205
|
+
return oscillator;
|
|
206
|
+
};
|
|
423
207
|
_getAudioContext() {
|
|
424
208
|
const container = this._container;
|
|
425
209
|
container.audioContext ??= new AudioContext();
|
|
426
210
|
return container.audioContext;
|
|
427
211
|
}
|
|
212
|
+
_initEvents = () => {
|
|
213
|
+
const container = this._container, soundsOptions = container.actualOptions.sounds;
|
|
214
|
+
if (!soundsOptions?.enable || !container.canvas.element) {
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
for (const event of soundsOptions.events) {
|
|
218
|
+
const cb = (args) => {
|
|
219
|
+
if (!args) {
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
void (async () => {
|
|
223
|
+
const filterNotValid = event.filter && !event.filter(args);
|
|
224
|
+
if (this._container !== args.container) {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
if (!!this._container.muted || this._container.destroyed) {
|
|
228
|
+
executeOnSingleOrMultiple(event.event, item => {
|
|
229
|
+
this._engine.removeEventListener(item, cb);
|
|
230
|
+
});
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
if (filterNotValid) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
const defaultNoteIndex = 0;
|
|
237
|
+
if (event.audio) {
|
|
238
|
+
const audio = itemFromSingleOrMultiple(event.audio);
|
|
239
|
+
if (!audio) {
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
this._playBuffer(audio);
|
|
243
|
+
}
|
|
244
|
+
else if (event.melodies) {
|
|
245
|
+
const melody = itemFromArray(event.melodies);
|
|
246
|
+
if (!melody) {
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
if (melody.melodies.length) {
|
|
250
|
+
await Promise.allSettled(melody.melodies.map(m => this._playNote(m.notes, defaultNoteIndex, melody.loop)));
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
await this._playNote(melody.notes, defaultNoteIndex, melody.loop);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
else if (event.notes) {
|
|
257
|
+
const note = itemFromArray(event.notes);
|
|
258
|
+
if (!note) {
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
await this._playNote([note], defaultNoteIndex, false);
|
|
262
|
+
}
|
|
263
|
+
})();
|
|
264
|
+
};
|
|
265
|
+
executeOnSingleOrMultiple(event.event, item => {
|
|
266
|
+
this._engine.addEventListener(item, cb);
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
_mute = async () => {
|
|
271
|
+
const container = this._container, audioContext = this._getAudioContext();
|
|
272
|
+
for (const source of this._audioSources) {
|
|
273
|
+
this._removeAudioSource(source);
|
|
274
|
+
}
|
|
275
|
+
if (this._gain) {
|
|
276
|
+
this._gain.disconnect();
|
|
277
|
+
}
|
|
278
|
+
await audioContext.close();
|
|
279
|
+
container.audioContext = undefined;
|
|
280
|
+
this._container.dispatchEvent(SoundsEventType.mute);
|
|
281
|
+
};
|
|
282
|
+
_playBuffer = audio => {
|
|
283
|
+
const audioBuffer = this._audioMap.get(audio.source);
|
|
284
|
+
if (!audioBuffer) {
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
const audioCtx = this._container.audioContext;
|
|
288
|
+
if (!audioCtx) {
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
const source = this._addBuffer(audioCtx);
|
|
292
|
+
source.loop = audio.loop;
|
|
293
|
+
source.buffer = audioBuffer;
|
|
294
|
+
source.connect(this._gain ?? audioCtx.destination);
|
|
295
|
+
source.start();
|
|
296
|
+
};
|
|
297
|
+
_playFrequency = async (frequency, duration) => {
|
|
298
|
+
if (!this._gain || this._container.muted) {
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
const audioContext = this._getAudioContext(), oscillator = this._addOscillator(audioContext);
|
|
302
|
+
oscillator.connect(this._gain);
|
|
303
|
+
oscillator.type = "sine";
|
|
304
|
+
oscillator.frequency.value = frequency;
|
|
305
|
+
oscillator.start();
|
|
306
|
+
return new Promise(resolve => {
|
|
307
|
+
setTimeout(() => {
|
|
308
|
+
this._removeAudioSource(oscillator);
|
|
309
|
+
resolve();
|
|
310
|
+
}, duration);
|
|
311
|
+
});
|
|
312
|
+
};
|
|
313
|
+
_playMuteSound = () => {
|
|
314
|
+
if (this._container.muted) {
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
const audioContext = this._getAudioContext(), gain = audioContext.createGain();
|
|
318
|
+
gain.connect(audioContext.destination);
|
|
319
|
+
gain.gain.value = 0;
|
|
320
|
+
const oscillator = audioContext.createOscillator();
|
|
321
|
+
oscillator.connect(gain);
|
|
322
|
+
oscillator.type = "sine";
|
|
323
|
+
oscillator.frequency.value = 1;
|
|
324
|
+
oscillator.start();
|
|
325
|
+
setTimeout(() => {
|
|
326
|
+
oscillator.stop();
|
|
327
|
+
oscillator.disconnect();
|
|
328
|
+
gain.disconnect();
|
|
329
|
+
});
|
|
330
|
+
};
|
|
331
|
+
_playNote = async (notes, noteIdx, loop) => {
|
|
332
|
+
if (this._container.muted) {
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
const note = notes[noteIdx];
|
|
336
|
+
if (!note) {
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
const value = note.value, promises = executeOnSingleOrMultiple(value, async (_, idx) => {
|
|
340
|
+
return this._playNoteValue(notes, noteIdx, idx);
|
|
341
|
+
});
|
|
342
|
+
await (isArray(promises) ? Promise.allSettled(promises) : promises);
|
|
343
|
+
const indexOffset = 1;
|
|
344
|
+
let nextNoteIdx = noteIdx + indexOffset;
|
|
345
|
+
if (loop && nextNoteIdx >= notes.length) {
|
|
346
|
+
nextNoteIdx = nextNoteIdx % notes.length;
|
|
347
|
+
}
|
|
348
|
+
await this._playNote(notes, nextNoteIdx, loop);
|
|
349
|
+
};
|
|
350
|
+
_playNoteValue = async (notes, noteIdx, valueIdx) => {
|
|
351
|
+
const note = notes[noteIdx];
|
|
352
|
+
if (!note) {
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
const value = itemFromSingleOrMultiple(note.value, valueIdx, true);
|
|
356
|
+
if (!value) {
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
try {
|
|
360
|
+
const freq = getNoteFrequency(value);
|
|
361
|
+
if (!isNumber(freq)) {
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
await this._playFrequency(freq, note.duration);
|
|
365
|
+
}
|
|
366
|
+
catch (e) {
|
|
367
|
+
getLogger().error(e);
|
|
368
|
+
}
|
|
369
|
+
};
|
|
370
|
+
_removeAudioSource = source => {
|
|
371
|
+
source.stop();
|
|
372
|
+
source.disconnect();
|
|
373
|
+
const deleteCount = 1;
|
|
374
|
+
this._audioSources.splice(this._audioSources.indexOf(source), deleteCount);
|
|
375
|
+
};
|
|
376
|
+
_unmute = () => {
|
|
377
|
+
const container = this._container, options = container.actualOptions, soundsOptions = options.sounds;
|
|
378
|
+
if (!soundsOptions) {
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
const audioContext = this._getAudioContext(), gain = audioContext.createGain();
|
|
382
|
+
gain.connect(audioContext.destination);
|
|
383
|
+
gain.gain.value = soundsOptions.volume.value / percentDenominator;
|
|
384
|
+
this._gain = gain;
|
|
385
|
+
this._initEvents();
|
|
386
|
+
this._container.dispatchEvent(SoundsEventType.unmute);
|
|
387
|
+
};
|
|
388
|
+
_updateMuteIcons = () => {
|
|
389
|
+
const container = this._container, soundsOptions = container.actualOptions.sounds;
|
|
390
|
+
if (!soundsOptions?.enable || !soundsOptions.icons.enable) {
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
const muteImg = this._muteImg, unmuteImg = this._unmuteImg;
|
|
394
|
+
if (muteImg) {
|
|
395
|
+
muteImg.style.display = container.muted ? "block" : "none";
|
|
396
|
+
}
|
|
397
|
+
if (unmuteImg) {
|
|
398
|
+
unmuteImg.style.display = container.muted ? "none" : "block";
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
_updateMuteStatus = async () => {
|
|
402
|
+
const container = this._container, audioContext = this._getAudioContext();
|
|
403
|
+
if (container.muted) {
|
|
404
|
+
await audioContext.suspend();
|
|
405
|
+
await this._mute();
|
|
406
|
+
}
|
|
407
|
+
else {
|
|
408
|
+
await audioContext.resume();
|
|
409
|
+
this._unmute();
|
|
410
|
+
this._playMuteSound();
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
_updateVolume = async () => {
|
|
414
|
+
const container = this._container, soundsOptions = container.actualOptions.sounds;
|
|
415
|
+
if (!soundsOptions?.enable) {
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
clamp(this._volume, soundsOptions.volume.min, soundsOptions.volume.max);
|
|
419
|
+
let stateChanged = false;
|
|
420
|
+
if (this._volume <= minVolume && !container.muted) {
|
|
421
|
+
this._volume = 0;
|
|
422
|
+
container.muted = true;
|
|
423
|
+
stateChanged = true;
|
|
424
|
+
}
|
|
425
|
+
else if (this._volume > minVolume && container.muted) {
|
|
426
|
+
container.muted = false;
|
|
427
|
+
stateChanged = true;
|
|
428
|
+
}
|
|
429
|
+
if (stateChanged) {
|
|
430
|
+
this._updateMuteIcons();
|
|
431
|
+
await this._updateMuteStatus();
|
|
432
|
+
}
|
|
433
|
+
if (this._gain?.gain) {
|
|
434
|
+
this._gain.gain.value = this._volume / percentDenominator;
|
|
435
|
+
}
|
|
436
|
+
};
|
|
428
437
|
}
|
package/cjs/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export async function loadSoundsPlugin(engine) {
|
|
2
|
-
engine.checkVersion("4.0.0-
|
|
3
|
-
await engine.register(async (e) => {
|
|
2
|
+
engine.checkVersion("4.0.0-beta.1");
|
|
3
|
+
await engine.pluginManager.register(async (e) => {
|
|
4
4
|
const { SoundsPlugin } = await import("./SoundsPlugin.js");
|
|
5
|
-
e.addPlugin(new SoundsPlugin(
|
|
5
|
+
e.pluginManager.addPlugin(new SoundsPlugin(e));
|
|
6
6
|
});
|
|
7
7
|
}
|