@tsparticles/plugin-sounds 3.0.0-alpha.1 → 3.0.0-beta.0

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.
Files changed (37) hide show
  1. package/README.md +15 -11
  2. package/browser/Options/Classes/SoundsAudio.js +2 -1
  3. package/browser/Options/Classes/SoundsEvent.js +4 -3
  4. package/browser/Options/Classes/SoundsVolume.js +2 -1
  5. package/browser/SoundsInstance.js +300 -279
  6. package/browser/index.js +6 -8
  7. package/browser/utils.js +0 -1
  8. package/cjs/Options/Classes/SoundsAudio.js +2 -1
  9. package/cjs/Options/Classes/SoundsEvent.js +4 -3
  10. package/cjs/Options/Classes/SoundsVolume.js +2 -1
  11. package/cjs/SoundsInstance.js +283 -281
  12. package/cjs/index.js +6 -19
  13. package/cjs/utils.js +0 -1
  14. package/esm/Options/Classes/SoundsAudio.js +2 -1
  15. package/esm/Options/Classes/SoundsEvent.js +4 -3
  16. package/esm/Options/Classes/SoundsVolume.js +2 -1
  17. package/esm/SoundsInstance.js +300 -279
  18. package/esm/index.js +6 -8
  19. package/esm/utils.js +0 -1
  20. package/package.json +6 -5
  21. package/report.html +4 -4
  22. package/tsparticles.plugin.sounds.js +343 -305
  23. package/tsparticles.plugin.sounds.min.js +1 -1
  24. package/tsparticles.plugin.sounds.min.js.LICENSE.txt +1 -8
  25. package/types/Options/Classes/SoundsAudio.d.ts +1 -1
  26. package/types/Options/Classes/SoundsEvent.d.ts +1 -1
  27. package/types/Options/Classes/SoundsVolume.d.ts +1 -1
  28. package/types/SoundsInstance.d.ts +15 -15
  29. package/types/enums.d.ts +4 -0
  30. package/types/index.d.ts +1 -1
  31. package/types/types.d.ts +16 -0
  32. package/umd/Options/Classes/SoundsAudio.js +3 -2
  33. package/umd/Options/Classes/SoundsEvent.js +5 -4
  34. package/umd/Options/Classes/SoundsVolume.js +3 -2
  35. package/umd/SoundsInstance.js +301 -280
  36. package/umd/index.js +6 -8
  37. package/umd/utils.js +0 -1
@@ -4,7 +4,7 @@
4
4
  * Demo / Generator : https://particles.js.org/
5
5
  * GitHub : https://www.github.com/matteobruni/tsparticles
6
6
  * How to use? : Check the GitHub README
7
- * v3.0.0-alpha.1
7
+ * v3.0.0-beta.0
8
8
  */
9
9
  (function webpackUniversalModuleDefinition(root, factory) {
10
10
  if(typeof exports === 'object' && typeof module === 'object')
@@ -91,10 +91,13 @@ __webpack_require__.r(__webpack_exports__);
91
91
 
92
92
  // EXPORTS
93
93
  __webpack_require__.d(__webpack_exports__, {
94
- "loadSoundsPlugin": () => (/* binding */ loadSoundsPlugin)
94
+ loadSoundsPlugin: () => (/* binding */ loadSoundsPlugin)
95
95
  });
96
96
 
97
+ // EXTERNAL MODULE: external {"commonjs":"@tsparticles/engine","commonjs2":"@tsparticles/engine","amd":"@tsparticles/engine","root":"window"}
98
+ var engine_root_window_ = __webpack_require__(533);
97
99
  ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/SoundsAudio.js
100
+
98
101
  class SoundsAudio {
99
102
  constructor() {
100
103
  this.loop = false;
@@ -104,7 +107,7 @@ class SoundsAudio {
104
107
  if (data === undefined) {
105
108
  return;
106
109
  }
107
- if (typeof data === "object") {
110
+ if ((0,engine_root_window_.isObject)(data)) {
108
111
  if (data.loop !== undefined) {
109
112
  this.loop = data.loop;
110
113
  }
@@ -169,6 +172,7 @@ class SoundsMelody {
169
172
 
170
173
 
171
174
 
175
+
172
176
  class SoundsEvent {
173
177
  constructor() {
174
178
  this.event = [];
@@ -182,7 +186,7 @@ class SoundsEvent {
182
186
  this.event = data.event;
183
187
  }
184
188
  if (data.audio !== undefined) {
185
- if (data.audio instanceof Array) {
189
+ if ((0,engine_root_window_.isArray)(data.audio)) {
186
190
  this.audio = data.audio.map(s => {
187
191
  const tmp = new SoundsAudio();
188
192
  tmp.load(s);
@@ -208,8 +212,8 @@ class SoundsEvent {
208
212
  });
209
213
  }
210
214
  if (data.filter !== undefined) {
211
- if (typeof data.filter === "string") {
212
- if (typeof window[data.filter] === "function") {
215
+ if ((0,engine_root_window_.isString)(data.filter)) {
216
+ if ((0,engine_root_window_.isFunction)(window[data.filter])) {
213
217
  this.filter = window[data.filter];
214
218
  }
215
219
  } else {
@@ -298,6 +302,7 @@ class SoundsIcons {
298
302
  }
299
303
  }
300
304
  ;// CONCATENATED MODULE: ./dist/browser/Options/Classes/SoundsVolume.js
305
+
301
306
  class SoundsVolume {
302
307
  constructor() {
303
308
  this.value = 100;
@@ -309,7 +314,7 @@ class SoundsVolume {
309
314
  if (data === undefined) {
310
315
  return;
311
316
  }
312
- if (typeof data === "object") {
317
+ if ((0,engine_root_window_.isObject)(data)) {
313
318
  if (data.max !== undefined) {
314
319
  this.max = data.max;
315
320
  }
@@ -358,8 +363,6 @@ class Sounds {
358
363
  }
359
364
  }
360
365
  }
361
- // EXTERNAL MODULE: external {"commonjs":"@tsparticles/engine","commonjs2":"@tsparticles/engine","amd":"@tsparticles/engine","root":"window"}
362
- var engine_root_window_ = __webpack_require__(533);
363
366
  ;// CONCATENATED MODULE: ./dist/browser/utils.js
364
367
  const notes = new Map();
365
368
  notes.set("C", [16.35, 32.7, 65.41, 130.81, 261.63, 523.25, 1046.5, 2093.0, 4186.01]);
@@ -381,7 +384,6 @@ function getNoteFrequency(note) {
381
384
  if (!result || !result.length) {
382
385
  return;
383
386
  }
384
- console.log(result);
385
387
  const noteKey = result[2] || result[0],
386
388
  noteItem = notes.get(noteKey);
387
389
  if (!noteItem) {
@@ -392,7 +394,36 @@ function getNoteFrequency(note) {
392
394
  ;// CONCATENATED MODULE: ./dist/browser/SoundsInstance.js
393
395
 
394
396
 
395
-
397
+ function initImage(data) {
398
+ const img = document.createElement("img"),
399
+ {
400
+ clickCb,
401
+ container,
402
+ display,
403
+ iconOptions,
404
+ margin,
405
+ options,
406
+ pos,
407
+ rightOffsets
408
+ } = data,
409
+ {
410
+ width,
411
+ path,
412
+ svg
413
+ } = iconOptions;
414
+ setIconStyle(img, pos.top + margin, pos.right - (margin * (rightOffsets.length + 1) + width + rightOffsets.reduce((a, b) => a + b, 0)), display, options.fullScreen.zIndex + 1, width, margin);
415
+ img.src = path ?? (svg ? `data:image/svg+xml;base64,${btoa(svg)}` : "");
416
+ const parent = container.canvas.element?.parentNode || document.body;
417
+ parent.append(img);
418
+ img.addEventListener("click", clickCb);
419
+ return img;
420
+ }
421
+ function removeImage(image) {
422
+ if (!image) {
423
+ return;
424
+ }
425
+ image.remove();
426
+ }
396
427
  function setIconStyle(icon, top, left, display, zIndex, width, margin) {
397
428
  icon.style.userSelect = "none";
398
429
  icon.style.webkitUserSelect = "none";
@@ -404,6 +435,234 @@ function setIconStyle(icon, top, left, display, zIndex, width, margin) {
404
435
  }
405
436
  class SoundsInstance {
406
437
  constructor(container, engine) {
438
+ this._addBuffer = audioCtx => {
439
+ const buffer = audioCtx.createBufferSource();
440
+ this._audioSources.push(buffer);
441
+ return buffer;
442
+ };
443
+ this._addOscillator = audioCtx => {
444
+ const oscillator = audioCtx.createOscillator();
445
+ this._audioSources.push(oscillator);
446
+ return oscillator;
447
+ };
448
+ this._initEvents = () => {
449
+ const container = this._container,
450
+ soundsOptions = container.actualOptions.sounds;
451
+ if (!soundsOptions?.enable || !container.canvas.element) {
452
+ return;
453
+ }
454
+ for (const event of soundsOptions.events) {
455
+ const cb = async args => {
456
+ if (this._container !== args.container) {
457
+ return;
458
+ }
459
+ if (!this._container || this._container.muted || this._container.destroyed) {
460
+ (0,engine_root_window_.executeOnSingleOrMultiple)(event.event, item => {
461
+ this._engine.removeEventListener(item, cb);
462
+ });
463
+ return;
464
+ }
465
+ if (event.filter && !event.filter(args)) {
466
+ return;
467
+ }
468
+ if (event.audio) {
469
+ this._playBuffer((0,engine_root_window_.itemFromSingleOrMultiple)(event.audio));
470
+ } else if (event.melodies) {
471
+ const melody = (0,engine_root_window_.itemFromArray)(event.melodies);
472
+ if (melody.melodies.length) {
473
+ await Promise.allSettled(melody.melodies.map(m => this._playNote(m.notes, 0, melody.loop)));
474
+ } else {
475
+ await this._playNote(melody.notes, 0, melody.loop);
476
+ }
477
+ } else if (event.notes) {
478
+ const note = (0,engine_root_window_.itemFromArray)(event.notes);
479
+ await this._playNote([note], 0, false);
480
+ }
481
+ };
482
+ (0,engine_root_window_.executeOnSingleOrMultiple)(event.event, item => {
483
+ this._engine.addEventListener(item, cb);
484
+ });
485
+ }
486
+ };
487
+ this._mute = () => {
488
+ const container = this._container;
489
+ if (!container.audioContext) {
490
+ return;
491
+ }
492
+ for (const source of this._audioSources) {
493
+ this._removeAudioSource(source);
494
+ }
495
+ if (this._gain) {
496
+ this._gain.disconnect();
497
+ }
498
+ container.audioContext.close();
499
+ container.audioContext = undefined;
500
+ this._engine.dispatchEvent("soundsMuted", {
501
+ container: this._container
502
+ });
503
+ };
504
+ this._playBuffer = audio => {
505
+ const audioBuffer = this._audioMap.get(audio.source);
506
+ if (!audioBuffer) {
507
+ return;
508
+ }
509
+ const audioCtx = this._container.audioContext;
510
+ if (!audioCtx) {
511
+ return;
512
+ }
513
+ const source = this._addBuffer(audioCtx);
514
+ source.loop = audio.loop;
515
+ source.buffer = audioBuffer;
516
+ source.connect(this._gain ?? audioCtx.destination);
517
+ source.start();
518
+ };
519
+ this._playFrequency = async (frequency, duration) => {
520
+ if (!this._container.audioContext || !this._gain) {
521
+ return;
522
+ }
523
+ const oscillator = this._addOscillator(this._container.audioContext);
524
+ oscillator.connect(this._gain);
525
+ oscillator.type = "sine";
526
+ oscillator.frequency.value = frequency;
527
+ oscillator.start();
528
+ return new Promise(resolve => {
529
+ setTimeout(() => {
530
+ this._removeAudioSource(oscillator);
531
+ resolve();
532
+ }, duration);
533
+ });
534
+ };
535
+ this._playMuteSound = () => {
536
+ const container = this._container;
537
+ if (!container.audioContext) {
538
+ return;
539
+ }
540
+ const gain = container.audioContext.createGain();
541
+ gain.connect(container.audioContext.destination);
542
+ gain.gain.value = 0;
543
+ const oscillator = container.audioContext.createOscillator();
544
+ oscillator.connect(gain);
545
+ oscillator.type = "sine";
546
+ oscillator.frequency.value = 1;
547
+ oscillator.start();
548
+ setTimeout(() => {
549
+ oscillator.stop();
550
+ oscillator.disconnect();
551
+ gain.disconnect();
552
+ });
553
+ };
554
+ this._playNote = async (notes, noteIdx, loop) => {
555
+ if (this._container.muted) {
556
+ return;
557
+ }
558
+ const note = notes[noteIdx];
559
+ if (!note) {
560
+ return;
561
+ }
562
+ const value = note.value;
563
+ const promises = (0,engine_root_window_.executeOnSingleOrMultiple)(value, async (_, idx) => {
564
+ return this._playNoteValue(notes, noteIdx, idx);
565
+ });
566
+ await ((0,engine_root_window_.isArray)(promises) ? Promise.allSettled(promises) : promises);
567
+ let nextNoteIdx = noteIdx + 1;
568
+ if (loop && nextNoteIdx >= notes.length) {
569
+ nextNoteIdx = nextNoteIdx % notes.length;
570
+ }
571
+ if (this._container.muted) {
572
+ return;
573
+ }
574
+ await this._playNote(notes, nextNoteIdx, loop);
575
+ };
576
+ this._playNoteValue = async (notes, noteIdx, valueIdx) => {
577
+ const note = notes[noteIdx];
578
+ if (!note) {
579
+ return;
580
+ }
581
+ const value = (0,engine_root_window_.itemFromSingleOrMultiple)(note.value, valueIdx, true);
582
+ try {
583
+ const freq = getNoteFrequency(value);
584
+ if (!(0,engine_root_window_.isNumber)(freq)) {
585
+ return;
586
+ }
587
+ await this._playFrequency(freq, note.duration);
588
+ } catch (e) {
589
+ (0,engine_root_window_.getLogger)().error(e);
590
+ }
591
+ };
592
+ this._removeAudioSource = source => {
593
+ source.stop();
594
+ source.disconnect();
595
+ this._audioSources.splice(this._audioSources.indexOf(source), 1);
596
+ };
597
+ this._unmute = () => {
598
+ const container = this._container,
599
+ options = container.actualOptions,
600
+ soundsOptions = options.sounds;
601
+ if (!soundsOptions) {
602
+ return;
603
+ }
604
+ if (!container.audioContext) {
605
+ container.audioContext = new AudioContext();
606
+ }
607
+ const {
608
+ audioContext
609
+ } = container;
610
+ if (!this._audioSources) {
611
+ this._audioSources = [];
612
+ }
613
+ const gain = audioContext.createGain();
614
+ gain.connect(audioContext.destination);
615
+ gain.gain.value = soundsOptions.volume.value / 100;
616
+ this._gain = gain;
617
+ this._initEvents();
618
+ this._engine.dispatchEvent("soundsUnmuted", {
619
+ container: this._container
620
+ });
621
+ };
622
+ this._updateMuteIcons = () => {
623
+ const container = this._container,
624
+ muteImg = this._muteImg,
625
+ unmuteImg = this._unmuteImg;
626
+ if (muteImg) {
627
+ muteImg.style.display = container.muted ? "block" : "none";
628
+ }
629
+ if (unmuteImg) {
630
+ unmuteImg.style.display = container.muted ? "none" : "block";
631
+ }
632
+ };
633
+ this._updateMuteStatus = () => {
634
+ const container = this._container;
635
+ if (container.muted) {
636
+ this._mute();
637
+ } else {
638
+ this._unmute();
639
+ this._playMuteSound();
640
+ }
641
+ };
642
+ this._updateVolume = () => {
643
+ const container = this._container,
644
+ soundsOptions = container.actualOptions.sounds;
645
+ if (!soundsOptions?.enable) {
646
+ return;
647
+ }
648
+ (0,engine_root_window_.clamp)(this._volume, soundsOptions.volume.min, soundsOptions.volume.max);
649
+ let stateChanged = false;
650
+ if (this._volume <= 0 && !container.muted) {
651
+ this._volume = 0;
652
+ container.muted = true;
653
+ stateChanged = true;
654
+ } else if (this._volume > 0 && container.muted) {
655
+ container.muted = false;
656
+ stateChanged = true;
657
+ }
658
+ if (stateChanged) {
659
+ this._updateMuteIcons();
660
+ this._updateMuteStatus();
661
+ }
662
+ if (this._gain?.gain) {
663
+ this._gain.gain.value = this._volume / 100;
664
+ }
665
+ };
407
666
  this._container = container;
408
667
  this._engine = engine;
409
668
  this._volume = 0;
@@ -414,7 +673,7 @@ class SoundsInstance {
414
673
  const container = this._container,
415
674
  options = container.actualOptions,
416
675
  soundsOptions = options.sounds;
417
- if (!(soundsOptions === null || soundsOptions === void 0 ? void 0 : soundsOptions.enable)) {
676
+ if (!soundsOptions?.enable) {
418
677
  return;
419
678
  }
420
679
  this._volume = soundsOptions.volume.value;
@@ -437,309 +696,90 @@ class SoundsInstance {
437
696
  }
438
697
  }
439
698
  async start() {
440
- var _a, _b, _c, _d;
441
699
  const container = this._container,
442
700
  options = container.actualOptions,
443
701
  soundsOptions = options.sounds;
444
- if (!(soundsOptions === null || soundsOptions === void 0 ? void 0 : soundsOptions.enable) || !container.canvas.element) {
702
+ if (!soundsOptions?.enable || !container.canvas.element) {
445
703
  return;
446
704
  }
447
705
  container.muted = true;
448
- this._muteImg = document.createElement("img");
449
- this._unmuteImg = document.createElement("img");
450
- this._volumeDownImg = document.createElement("img");
451
- this._volumeUpImg = document.createElement("img");
452
- const muteImg = this._muteImg,
453
- unmuteImg = this._unmuteImg,
454
- volumeDownImg = this._volumeDownImg,
455
- volumeUpImg = this._volumeUpImg,
456
- containerTop = container.canvas.element.offsetTop,
457
- containerRight = container.canvas.element.offsetLeft + container.canvas.element.offsetWidth,
458
- iconsOptions = soundsOptions.icons,
459
- muteOptions = iconsOptions.mute,
460
- unmuteOptions = iconsOptions.unmute,
461
- volumeDownOptions = iconsOptions.volumeDown,
462
- volumeUpOptions = iconsOptions.volumeUp,
706
+ const canvas = container.canvas.element,
707
+ pos = {
708
+ top: canvas.offsetTop,
709
+ right: canvas.offsetLeft + canvas.offsetWidth
710
+ },
711
+ {
712
+ mute,
713
+ unmute,
714
+ volumeDown,
715
+ volumeUp
716
+ } = soundsOptions.icons,
463
717
  margin = 10;
464
- setIconStyle(muteImg, containerTop + margin, containerRight - margin * 3 - muteOptions.width - volumeDownOptions.width - volumeUpOptions.width, "block", options.fullScreen.zIndex + 1, muteOptions.width, margin);
465
- setIconStyle(unmuteImg, containerTop + margin, containerRight - margin * 3 - unmuteOptions.width - volumeDownOptions.width - volumeUpOptions.width, "none", options.fullScreen.zIndex + 1, unmuteOptions.width, margin);
466
- setIconStyle(volumeDownImg, containerTop + margin, containerRight - margin * 2 - volumeDownOptions.width - volumeUpOptions.width, "block", options.fullScreen.zIndex + 1, volumeDownOptions.width, margin);
467
- setIconStyle(volumeUpImg, containerTop + margin, containerRight - margin - volumeUpOptions.width, "block", options.fullScreen.zIndex + 1, volumeUpOptions.width, margin);
468
- muteImg.src = (_a = muteOptions.path) !== null && _a !== void 0 ? _a : muteOptions.svg ? `data:image/svg+xml;base64,${btoa(muteOptions.svg)}` : "";
469
- unmuteImg.src = (_b = unmuteOptions.path) !== null && _b !== void 0 ? _b : unmuteOptions.svg ? `data:image/svg+xml;base64,${btoa(unmuteOptions.svg)}` : "";
470
- volumeDownImg.src = (_c = volumeDownOptions.path) !== null && _c !== void 0 ? _c : volumeDownOptions.svg ? `data:image/svg+xml;base64,${btoa(volumeDownOptions.svg)}` : "";
471
- volumeUpImg.src = (_d = volumeUpOptions.path) !== null && _d !== void 0 ? _d : volumeUpOptions.svg ? `data:image/svg+xml;base64,${btoa(volumeUpOptions.svg)}` : "";
472
- const parent = container.canvas.element.parentNode || document.body;
473
- parent.append(muteImg);
474
- parent.append(unmuteImg);
475
- parent.append(volumeDownImg);
476
- parent.append(volumeUpImg);
477
718
  const toggleMute = () => {
478
719
  container.muted = !container.muted;
479
720
  this._updateMuteIcons();
480
721
  this._updateMuteStatus();
481
722
  };
482
- const volumeDown = () => {
483
- if (container.muted) {
484
- this._volume = 0;
485
- }
486
- this._volume -= soundsOptions.volume.step;
487
- this._updateVolume();
488
- };
489
- const volumeUp = () => {
490
- if (container.muted) {
491
- this._volume = 0;
492
- }
493
- this._volume += soundsOptions.volume.step;
494
- this._updateVolume();
495
- };
496
- muteImg.addEventListener("click", toggleMute);
497
- unmuteImg.addEventListener("click", toggleMute);
498
- volumeDownImg.addEventListener("click", volumeDown);
499
- volumeUpImg.addEventListener("click", volumeUp);
500
- }
501
- stop() {
502
- this._container.muted = true;
503
- this._mute();
504
- if (this._muteImg) {
505
- this._muteImg.remove();
506
- }
507
- if (this._unmuteImg) {
508
- this._unmuteImg.remove();
509
- }
510
- if (this._volumeDownImg) {
511
- this._volumeDownImg.remove();
512
- }
513
- if (this._volumeUpImg) {
514
- this._volumeUpImg.remove();
515
- }
516
- }
517
- _addBuffer(audioCtx) {
518
- const buffer = audioCtx.createBufferSource();
519
- this._audioSources.push(buffer);
520
- return buffer;
521
- }
522
- _addOscillator(audioCtx) {
523
- const oscillator = audioCtx.createOscillator();
524
- this._audioSources.push(oscillator);
525
- return oscillator;
526
- }
527
- _initEvents() {
528
- const container = this._container,
529
- soundsOptions = container.actualOptions.sounds;
530
- if (!(soundsOptions === null || soundsOptions === void 0 ? void 0 : soundsOptions.enable) || !container.canvas.element) {
531
- return;
532
- }
533
- for (const event of soundsOptions.events) {
534
- const cb = async args => {
535
- if (this._container !== args.container) {
536
- return;
537
- }
538
- if (!this._container || this._container.muted || this._container.destroyed) {
539
- (0,engine_root_window_.executeOnSingleOrMultiple)(event.event, item => {
540
- this._engine.removeEventListener(item, cb);
541
- });
542
- return;
543
- }
544
- if (event.filter && !event.filter(args)) {
545
- return;
546
- }
547
- if (event.audio) {
548
- this._playBuffer((0,engine_root_window_.itemFromSingleOrMultiple)(event.audio));
549
- } else if (event.melodies) {
550
- const melody = (0,engine_root_window_.itemFromArray)(event.melodies);
551
- if (melody.melodies.length) {
552
- await Promise.allSettled(melody.melodies.map(m => this._playNote(m.notes, 0, melody.loop)));
553
- } else {
554
- await this._playNote(melody.notes, 0, melody.loop);
555
- }
556
- } else if (event.notes) {
557
- const note = (0,engine_root_window_.itemFromArray)(event.notes);
558
- await this._playNote([note], 0, false);
559
- }
560
- };
561
- (0,engine_root_window_.executeOnSingleOrMultiple)(event.event, item => {
562
- this._engine.addEventListener(item, cb);
563
- });
564
- }
565
- }
566
- _mute() {
567
- const container = this._container;
568
- if (!container.audioContext) {
569
- return;
570
- }
571
- for (const source of this._audioSources) {
572
- this._removeAudioSource(source);
573
- }
574
- if (this._gain) {
575
- this._gain.disconnect();
576
- }
577
- container.audioContext.close();
578
- container.audioContext = undefined;
579
- this._engine.dispatchEvent("soundsMuted", {
580
- container: this._container
723
+ this._muteImg = initImage({
724
+ container,
725
+ options,
726
+ pos,
727
+ display: "block",
728
+ iconOptions: mute,
729
+ margin,
730
+ rightOffsets: [volumeDown.width, volumeUp.width],
731
+ clickCb: toggleMute
581
732
  });
582
- }
583
- _playBuffer(audio) {
584
- var _a;
585
- const audioBuffer = this._audioMap.get(audio.source);
586
- if (!audioBuffer) {
587
- return;
588
- }
589
- const audioCtx = this._container.audioContext;
590
- if (!audioCtx) {
591
- return;
592
- }
593
- const source = this._addBuffer(audioCtx);
594
- source.loop = audio.loop;
595
- source.buffer = audioBuffer;
596
- source.connect((_a = this._gain) !== null && _a !== void 0 ? _a : audioCtx.destination);
597
- source.start();
598
- }
599
- async _playFrequency(frequency, duration) {
600
- if (!this._container.audioContext || !this._gain) {
601
- return;
602
- }
603
- const oscillator = this._addOscillator(this._container.audioContext);
604
- oscillator.connect(this._gain);
605
- oscillator.type = "sine";
606
- oscillator.frequency.value = frequency;
607
- oscillator.start();
608
- return new Promise(resolve => {
609
- setTimeout(() => {
610
- this._removeAudioSource(oscillator);
611
- resolve();
612
- }, duration);
613
- });
614
- }
615
- _playMuteSound() {
616
- const container = this._container;
617
- if (!container.audioContext) {
618
- return;
619
- }
620
- const gain = container.audioContext.createGain();
621
- gain.connect(container.audioContext.destination);
622
- gain.gain.value = 0;
623
- const oscillator = container.audioContext.createOscillator();
624
- oscillator.connect(gain);
625
- oscillator.type = "sine";
626
- oscillator.frequency.value = 1;
627
- oscillator.start();
628
- setTimeout(() => {
629
- oscillator.stop();
630
- oscillator.disconnect();
631
- gain.disconnect();
733
+ this._unmuteImg = initImage({
734
+ container,
735
+ options,
736
+ pos,
737
+ display: "none",
738
+ iconOptions: unmute,
739
+ margin,
740
+ rightOffsets: [volumeDown.width, volumeUp.width],
741
+ clickCb: toggleMute
632
742
  });
633
- }
634
- async _playNote(notes, noteIdx, loop) {
635
- if (this._container.muted) {
636
- return;
637
- }
638
- const note = notes[noteIdx];
639
- if (!note) {
640
- return;
641
- }
642
- const value = note.value;
643
- const promises = (0,engine_root_window_.executeOnSingleOrMultiple)(value, async (_, idx) => {
644
- return this._playNoteValue(notes, noteIdx, idx);
743
+ this._volumeDownImg = initImage({
744
+ container,
745
+ options,
746
+ pos,
747
+ display: "block",
748
+ iconOptions: volumeDown,
749
+ margin,
750
+ rightOffsets: [volumeUp.width],
751
+ clickCb: () => {
752
+ if (container.muted) {
753
+ this._volume = 0;
754
+ }
755
+ this._volume -= soundsOptions.volume.step;
756
+ this._updateVolume();
757
+ }
645
758
  });
646
- await (promises instanceof Array ? Promise.allSettled(promises) : promises);
647
- let nextNoteIdx = noteIdx + 1;
648
- if (loop && nextNoteIdx >= notes.length) {
649
- nextNoteIdx = nextNoteIdx % notes.length;
650
- }
651
- if (this._container.muted) {
652
- return;
653
- }
654
- await this._playNote(notes, nextNoteIdx, loop);
655
- }
656
- async _playNoteValue(notes, noteIdx, valueIdx) {
657
- const note = notes[noteIdx];
658
- if (!note) {
659
- return;
660
- }
661
- const value = (0,engine_root_window_.itemFromSingleOrMultiple)(note.value, valueIdx, true);
662
- try {
663
- const freq = getNoteFrequency(value);
664
- if (typeof freq !== "number") {
665
- return;
759
+ this._volumeUpImg = initImage({
760
+ container,
761
+ options,
762
+ pos,
763
+ display: "block",
764
+ iconOptions: volumeUp,
765
+ margin,
766
+ rightOffsets: [],
767
+ clickCb: () => {
768
+ if (container.muted) {
769
+ this._volume = 0;
770
+ }
771
+ this._volume += soundsOptions.volume.step;
772
+ this._updateVolume();
666
773
  }
667
- await this._playFrequency(freq, note.duration);
668
- } catch (e) {
669
- console.error(e);
670
- }
671
- }
672
- _removeAudioSource(source) {
673
- source.stop();
674
- source.disconnect();
675
- this._audioSources.splice(this._audioSources.indexOf(source), 1);
676
- }
677
- _unmute() {
678
- const container = this._container,
679
- options = container.actualOptions,
680
- soundsOptions = options.sounds;
681
- if (!soundsOptions) {
682
- return;
683
- }
684
- if (!container.audioContext) {
685
- container.audioContext = new AudioContext();
686
- }
687
- if (!this._audioSources) {
688
- this._audioSources = [];
689
- }
690
- const gain = container.audioContext.createGain();
691
- gain.connect(container.audioContext.destination);
692
- gain.gain.value = soundsOptions.volume.value / 100;
693
- this._gain = gain;
694
- this._initEvents();
695
- this._engine.dispatchEvent("soundsUnmuted", {
696
- container: this._container
697
774
  });
698
775
  }
699
- _updateMuteIcons() {
700
- const container = this._container,
701
- muteImg = this._muteImg,
702
- unmuteImg = this._unmuteImg;
703
- if (muteImg) {
704
- muteImg.style.display = container.muted ? "block" : "none";
705
- }
706
- if (unmuteImg) {
707
- unmuteImg.style.display = container.muted ? "none" : "block";
708
- }
709
- }
710
- _updateMuteStatus() {
711
- const container = this._container;
712
- if (container.muted) {
713
- this._mute();
714
- } else {
715
- this._unmute();
716
- this._playMuteSound();
717
- }
718
- }
719
- _updateVolume() {
720
- var _a;
721
- const container = this._container,
722
- soundsOptions = container.actualOptions.sounds;
723
- if (!(soundsOptions === null || soundsOptions === void 0 ? void 0 : soundsOptions.enable)) {
724
- return;
725
- }
726
- (0,engine_root_window_.clamp)(this._volume, soundsOptions.volume.min, soundsOptions.volume.max);
727
- let stateChanged = false;
728
- if (this._volume <= 0 && !container.muted) {
729
- this._volume = 0;
730
- container.muted = true;
731
- stateChanged = true;
732
- } else if (this._volume > 0 && container.muted) {
733
- container.muted = false;
734
- stateChanged = true;
735
- }
736
- if (stateChanged) {
737
- this._updateMuteIcons();
738
- this._updateMuteStatus();
739
- }
740
- if ((_a = this._gain) === null || _a === void 0 ? void 0 : _a.gain) {
741
- this._gain.gain.value = this._volume / 100;
742
- }
776
+ stop() {
777
+ this._container.muted = true;
778
+ this._mute();
779
+ removeImage(this._muteImg);
780
+ removeImage(this._unmuteImg);
781
+ removeImage(this._volumeDownImg);
782
+ removeImage(this._volumeUpImg);
743
783
  }
744
784
  }
745
785
  ;// CONCATENATED MODULE: ./dist/browser/index.js
@@ -754,23 +794,21 @@ class SoundsPlugin {
754
794
  return new SoundsInstance(container, this._engine);
755
795
  }
756
796
  loadOptions(options, source) {
757
- if (!this.needsPlugin(source)) {
797
+ if (!this.needsPlugin(options) && !this.needsPlugin(source)) {
758
798
  return;
759
799
  }
760
800
  let soundsOptions = options.sounds;
761
- if ((soundsOptions === null || soundsOptions === void 0 ? void 0 : soundsOptions.load) === undefined) {
801
+ if (soundsOptions?.load === undefined) {
762
802
  options.sounds = soundsOptions = new Sounds();
763
803
  }
764
- soundsOptions.load(source === null || source === void 0 ? void 0 : source.sounds);
804
+ soundsOptions.load(source?.sounds);
765
805
  }
766
806
  needsPlugin(options) {
767
- var _a, _b;
768
- return (_b = (_a = options === null || options === void 0 ? void 0 : options.sounds) === null || _a === void 0 ? void 0 : _a.enable) !== null && _b !== void 0 ? _b : false;
807
+ return options?.sounds?.enable ?? false;
769
808
  }
770
809
  }
771
- async function loadSoundsPlugin(engine) {
772
- const plugin = new SoundsPlugin(engine);
773
- await engine.addPlugin(plugin);
810
+ async function loadSoundsPlugin(engine, refresh = true) {
811
+ await engine.addPlugin(new SoundsPlugin(engine), refresh);
774
812
  }
775
813
  })();
776
814