@al8b/audio 0.1.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 (56) hide show
  1. package/README.md +23 -0
  2. package/dist/constants.d.mts +8 -0
  3. package/dist/constants.d.ts +8 -0
  4. package/dist/constants.js +37 -0
  5. package/dist/constants.js.map +1 -0
  6. package/dist/constants.mjs +10 -0
  7. package/dist/constants.mjs.map +1 -0
  8. package/dist/core/audio-core.d.mts +98 -0
  9. package/dist/core/audio-core.d.ts +98 -0
  10. package/dist/core/audio-core.js +664 -0
  11. package/dist/core/audio-core.js.map +1 -0
  12. package/dist/core/audio-core.mjs +641 -0
  13. package/dist/core/audio-core.mjs.map +1 -0
  14. package/dist/core/audio-worklet.d.mts +3 -0
  15. package/dist/core/audio-worklet.d.ts +3 -0
  16. package/dist/core/audio-worklet.js +153 -0
  17. package/dist/core/audio-worklet.js.map +1 -0
  18. package/dist/core/audio-worklet.mjs +128 -0
  19. package/dist/core/audio-worklet.mjs.map +1 -0
  20. package/dist/core/index.d.mts +2 -0
  21. package/dist/core/index.d.ts +2 -0
  22. package/dist/core/index.js +666 -0
  23. package/dist/core/index.js.map +1 -0
  24. package/dist/core/index.mjs +641 -0
  25. package/dist/core/index.mjs.map +1 -0
  26. package/dist/devices/beeper.d.mts +21 -0
  27. package/dist/devices/beeper.d.ts +21 -0
  28. package/dist/devices/beeper.js +286 -0
  29. package/dist/devices/beeper.js.map +1 -0
  30. package/dist/devices/beeper.mjs +261 -0
  31. package/dist/devices/beeper.mjs.map +1 -0
  32. package/dist/devices/index.d.mts +3 -0
  33. package/dist/devices/index.d.ts +3 -0
  34. package/dist/devices/index.js +534 -0
  35. package/dist/devices/index.js.map +1 -0
  36. package/dist/devices/index.mjs +507 -0
  37. package/dist/devices/index.mjs.map +1 -0
  38. package/dist/devices/music.d.mts +27 -0
  39. package/dist/devices/music.d.ts +27 -0
  40. package/dist/devices/music.js +104 -0
  41. package/dist/devices/music.js.map +1 -0
  42. package/dist/devices/music.mjs +81 -0
  43. package/dist/devices/music.mjs.map +1 -0
  44. package/dist/devices/sound.d.mts +22 -0
  45. package/dist/devices/sound.d.ts +22 -0
  46. package/dist/devices/sound.js +198 -0
  47. package/dist/devices/sound.js.map +1 -0
  48. package/dist/devices/sound.mjs +175 -0
  49. package/dist/devices/sound.mjs.map +1 -0
  50. package/dist/index.d.mts +4 -0
  51. package/dist/index.d.ts +4 -0
  52. package/dist/index.js +916 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/index.mjs +888 -0
  55. package/dist/index.mjs.map +1 -0
  56. package/package.json +37 -0
@@ -0,0 +1,666 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // src/core/index.ts
22
+ var core_exports = {};
23
+ __export(core_exports, {
24
+ AudioCore: () => AudioCore
25
+ });
26
+ module.exports = __toCommonJS(core_exports);
27
+
28
+ // src/core/audio-core.ts
29
+ var import_diagnostics = require("@al8b/diagnostics");
30
+
31
+ // src/constants.ts
32
+ var A4_FREQUENCY = 440;
33
+ var SEMITONE_RATIO = 2 ** (1 / 12);
34
+ var A4_MIDI_NOTE = 69;
35
+
36
+ // src/devices/beeper.ts
37
+ var Beeper = class {
38
+ static {
39
+ __name(this, "Beeper");
40
+ }
41
+ audio;
42
+ notes = {};
43
+ plainNotes = {};
44
+ currentOctave = 5;
45
+ currentDuration = 0.5;
46
+ currentVolume = 0.5;
47
+ currentSpan = 1;
48
+ currentWaveform = "square";
49
+ constructor(audio) {
50
+ this.audio = audio;
51
+ this.initializeNotes();
52
+ }
53
+ /**
54
+ * Initialize note mappings
55
+ */
56
+ initializeNotes() {
57
+ const noteNames = [
58
+ [
59
+ "C",
60
+ "DO"
61
+ ],
62
+ [
63
+ "C#",
64
+ "DO#",
65
+ "Db",
66
+ "REb"
67
+ ],
68
+ [
69
+ "D",
70
+ "RE"
71
+ ],
72
+ [
73
+ "D#",
74
+ "RE#",
75
+ "Eb",
76
+ "MIb"
77
+ ],
78
+ [
79
+ "E",
80
+ "MI"
81
+ ],
82
+ [
83
+ "F",
84
+ "FA"
85
+ ],
86
+ [
87
+ "F#",
88
+ "FA#",
89
+ "Gb",
90
+ "SOLb"
91
+ ],
92
+ [
93
+ "G",
94
+ "SOL"
95
+ ],
96
+ [
97
+ "G#",
98
+ "SOL#",
99
+ "Ab",
100
+ "LAb"
101
+ ],
102
+ [
103
+ "A",
104
+ "LA"
105
+ ],
106
+ [
107
+ "A#",
108
+ "LA#",
109
+ "Bb",
110
+ "SIb"
111
+ ],
112
+ [
113
+ "B",
114
+ "SI"
115
+ ]
116
+ ];
117
+ for (let i = 0; i <= 127; i++) {
118
+ this.notes[i] = i;
119
+ const oct = Math.floor(i / 12) - 1;
120
+ for (const n of noteNames[i % 12]) {
121
+ this.notes[n + oct] = i;
122
+ }
123
+ if (oct === -1) {
124
+ for (const n of noteNames[i % 12]) {
125
+ this.plainNotes[n] = i;
126
+ }
127
+ }
128
+ }
129
+ }
130
+ /**
131
+ * Parse and play beep sequence
132
+ */
133
+ beep(input) {
134
+ let status = "normal";
135
+ const sequence = [];
136
+ const loops = [];
137
+ let note;
138
+ const parsed = input.split(" ");
139
+ for (const t of parsed) {
140
+ if (t === "") continue;
141
+ switch (status) {
142
+ case "normal":
143
+ if (this.notes[t] !== void 0) {
144
+ note = this.notes[t];
145
+ this.currentOctave = Math.floor(note / 12);
146
+ sequence.push({
147
+ frequency: A4_FREQUENCY * SEMITONE_RATIO ** (note - A4_MIDI_NOTE),
148
+ volume: this.currentVolume,
149
+ span: this.currentSpan,
150
+ duration: this.currentDuration,
151
+ waveform: this.currentWaveform
152
+ });
153
+ } else if (this.plainNotes[t] !== void 0) {
154
+ note = this.plainNotes[t] + this.currentOctave * 12;
155
+ sequence.push({
156
+ frequency: A4_FREQUENCY * SEMITONE_RATIO ** (note - A4_MIDI_NOTE),
157
+ volume: this.currentVolume,
158
+ span: this.currentSpan,
159
+ duration: this.currentDuration,
160
+ waveform: this.currentWaveform
161
+ });
162
+ } else if ([
163
+ "square",
164
+ "sine",
165
+ "saw",
166
+ "noise"
167
+ ].includes(t)) {
168
+ this.currentWaveform = t;
169
+ } else if ([
170
+ "tempo",
171
+ "duration",
172
+ "volume",
173
+ "span",
174
+ "loop",
175
+ "to"
176
+ ].includes(t)) {
177
+ status = t;
178
+ } else if (t === "-") {
179
+ sequence.push({
180
+ frequency: A4_FREQUENCY,
181
+ volume: 0,
182
+ span: this.currentSpan,
183
+ duration: this.currentDuration,
184
+ waveform: this.currentWaveform
185
+ });
186
+ } else if (t === "end") {
187
+ if (loops.length > 0 && sequence.length > 0) {
188
+ sequence.push({
189
+ frequency: A4_FREQUENCY,
190
+ volume: 0,
191
+ span: this.currentSpan,
192
+ duration: 0,
193
+ waveform: this.currentWaveform
194
+ });
195
+ const lop = loops.splice(loops.length - 1, 1)[0];
196
+ sequence[sequence.length - 1].loopto = lop.start;
197
+ sequence[sequence.length - 1].repeats = lop.repeats;
198
+ }
199
+ }
200
+ break;
201
+ case "tempo": {
202
+ status = "normal";
203
+ const tempo = Number.parseFloat(t);
204
+ if (!Number.isNaN(tempo) && tempo > 0) {
205
+ this.currentDuration = 60 / tempo;
206
+ }
207
+ break;
208
+ }
209
+ case "duration": {
210
+ status = "normal";
211
+ const duration = Number.parseFloat(t);
212
+ if (!Number.isNaN(duration) && duration > 0) {
213
+ this.currentDuration = duration / 1e3;
214
+ }
215
+ break;
216
+ }
217
+ case "volume": {
218
+ status = "normal";
219
+ const volume = Number.parseFloat(t);
220
+ if (!Number.isNaN(volume)) {
221
+ this.currentVolume = volume / 100;
222
+ }
223
+ break;
224
+ }
225
+ case "span": {
226
+ status = "normal";
227
+ const span = Number.parseFloat(t);
228
+ if (!Number.isNaN(span)) {
229
+ this.currentSpan = span / 100;
230
+ }
231
+ break;
232
+ }
233
+ case "loop": {
234
+ status = "normal";
235
+ loops.push({
236
+ start: sequence.length
237
+ });
238
+ const repeats = Number.parseFloat(t);
239
+ if (!Number.isNaN(repeats)) {
240
+ loops[loops.length - 1].repeats = repeats;
241
+ }
242
+ break;
243
+ }
244
+ case "to":
245
+ status = "normal";
246
+ if (note !== void 0) {
247
+ let n;
248
+ if (this.notes[t] !== void 0) {
249
+ n = this.notes[t];
250
+ } else if (this.plainNotes[t] !== void 0) {
251
+ n = this.plainNotes[t] + this.currentOctave * 12;
252
+ }
253
+ if (n !== void 0 && n !== note) {
254
+ const step = n > note ? 1 : -1;
255
+ for (let i = note + step; step > 0 ? i <= n : i >= n; i += step) {
256
+ sequence.push({
257
+ frequency: A4_FREQUENCY * SEMITONE_RATIO ** (i - A4_MIDI_NOTE),
258
+ volume: this.currentVolume,
259
+ span: this.currentSpan,
260
+ duration: this.currentDuration,
261
+ waveform: this.currentWaveform
262
+ });
263
+ }
264
+ note = n;
265
+ }
266
+ }
267
+ break;
268
+ }
269
+ }
270
+ if (loops.length > 0 && sequence.length > 0) {
271
+ const lop = loops.splice(loops.length - 1, 1)[0];
272
+ sequence.push({
273
+ frequency: A4_FREQUENCY,
274
+ volume: 0,
275
+ span: this.currentSpan,
276
+ duration: 0,
277
+ waveform: this.currentWaveform
278
+ });
279
+ sequence[sequence.length - 1].loopto = lop.start;
280
+ sequence[sequence.length - 1].repeats = lop.repeats;
281
+ }
282
+ this.audio.addBeeps(sequence);
283
+ }
284
+ };
285
+
286
+ // src/core/audio-worklet.ts
287
+ var AUDIO_WORKLET_CODE = `
288
+ class L8bAudioProcessor extends AudioWorkletProcessor {
289
+ constructor() {
290
+ super();
291
+ this.beeps = [];
292
+ this.last = 0;
293
+ this.port.onmessage = (event) => {
294
+ const data = JSON.parse(event.data);
295
+ if (data.name === "cancel_beeps") {
296
+ this.beeps = [];
297
+ } else if (data.name === "beep") {
298
+ const seq = data.sequence;
299
+ // Link sequence notes together
300
+ for (let i = 0; i < seq.length; i++) {
301
+ const note = seq[i];
302
+ if (i > 0) {
303
+ seq[i - 1].next = note;
304
+ }
305
+ // Resolve loopto index to actual note reference
306
+ if (note.loopto != null) {
307
+ note.loopto = seq[note.loopto];
308
+ }
309
+ // Initialize phase and time
310
+ note.phase = 0;
311
+ note.time = 0;
312
+ }
313
+ // Add first note to beeps queue
314
+ if (seq.length > 0) {
315
+ this.beeps.push(seq[0]);
316
+ }
317
+ }
318
+ };
319
+ }
320
+
321
+ process(inputs, outputs, parameters) {
322
+ const output = outputs[0];
323
+
324
+ for (let i = 0; i < output.length; i++) {
325
+ const channel = output[i];
326
+
327
+ if (i > 0) {
328
+ // Copy first channel to other channels
329
+ for (let j = 0; j < channel.length; j++) {
330
+ channel[j] = output[0][j];
331
+ }
332
+ } else {
333
+ // Generate audio for first channel
334
+ for (let j = 0; j < channel.length; j++) {
335
+ let sig = 0;
336
+
337
+ for (let k = this.beeps.length - 1; k >= 0; k--) {
338
+ const b = this.beeps[k];
339
+ let volume = b.volume;
340
+
341
+ if (b.time / b.duration > b.span) {
342
+ volume = 0;
343
+ }
344
+
345
+ // Generate waveform
346
+ switch (b.waveform) {
347
+ case "square":
348
+ sig += b.phase > 0.5 ? volume : -volume;
349
+ break;
350
+ case "saw":
351
+ sig += (b.phase * 2 - 1) * volume;
352
+ break;
353
+ case "noise":
354
+ sig += (Math.random() * 2 - 1) * volume;
355
+ break;
356
+ default: // sine
357
+ sig += Math.sin(b.phase * Math.PI * 2) * volume;
358
+ }
359
+
360
+ b.phase = (b.phase + b.increment) % 1;
361
+ b.time += 1;
362
+
363
+ if (b.time >= b.duration) {
364
+ b.time = 0;
365
+
366
+ if (b.loopto != null) {
367
+ if (b.repeats != null && b.repeats > 0) {
368
+ if (b.loopcount == null) {
369
+ b.loopcount = 0;
370
+ }
371
+ b.loopcount++;
372
+
373
+ if (b.loopcount >= b.repeats) {
374
+ b.loopcount = 0;
375
+ if (b.next != null) {
376
+ b.next.phase = b.phase;
377
+ this.beeps[k] = b.next;
378
+ } else {
379
+ this.beeps.splice(k, 1);
380
+ }
381
+ } else {
382
+ b.loopto.phase = b.phase;
383
+ this.beeps[k] = b.loopto;
384
+ }
385
+ } else {
386
+ b.loopto.phase = b.phase;
387
+ this.beeps[k] = b.loopto;
388
+ }
389
+ } else if (b.next != null) {
390
+ b.next.phase = b.phase;
391
+ this.beeps[k] = b.next;
392
+ } else {
393
+ this.beeps.splice(k, 1);
394
+ }
395
+ }
396
+ }
397
+
398
+ this.last = this.last * 0.9 + sig * 0.1;
399
+ channel[j] = this.last;
400
+ }
401
+ }
402
+ }
403
+
404
+ return true;
405
+ }
406
+ }
407
+
408
+ registerProcessor("l8b-audio-processor", L8bAudioProcessor);
409
+ `;
410
+
411
+ // src/core/audio-core.ts
412
+ var AudioCore = class {
413
+ static {
414
+ __name(this, "AudioCore");
415
+ }
416
+ context;
417
+ buffer = [];
418
+ playing = [];
419
+ wakeupList = [];
420
+ workletNode;
421
+ beeper;
422
+ runtime;
423
+ masterVolume = 1;
424
+ constructor(runtime) {
425
+ this.runtime = runtime;
426
+ this.getContext();
427
+ }
428
+ /**
429
+ * Check if audio context is running
430
+ */
431
+ isStarted() {
432
+ return this.context.state === "running";
433
+ }
434
+ /**
435
+ * Add item to wakeup list (for mobile audio activation)
436
+ */
437
+ addToWakeUpList(item) {
438
+ this.wakeupList.push(item);
439
+ }
440
+ interfaceCache = null;
441
+ /**
442
+ * Set master volume (0-1). Applied as a multiplier to all sound/music playback.
443
+ */
444
+ setVolume(volume) {
445
+ this.masterVolume = Math.max(0, Math.min(1, volume));
446
+ }
447
+ /**
448
+ * Get current master volume (0-1)
449
+ */
450
+ getVolume() {
451
+ return this.masterVolume;
452
+ }
453
+ /**
454
+ * Get interface for game code
455
+ */
456
+ getInterface() {
457
+ if (this.interfaceCache) {
458
+ return this.interfaceCache;
459
+ }
460
+ this.interfaceCache = {
461
+ beep: /* @__PURE__ */ __name((sequence) => this.beep(sequence), "beep"),
462
+ cancelBeeps: /* @__PURE__ */ __name(() => this.cancelBeeps(), "cancelBeeps"),
463
+ playSound: /* @__PURE__ */ __name((sound, volume, pitch, pan, loopit) => this.playSound(sound, volume, pitch, pan, loopit), "playSound"),
464
+ playMusic: /* @__PURE__ */ __name((music, volume, loopit) => this.playMusic(music, volume, loopit), "playMusic"),
465
+ setVolume: /* @__PURE__ */ __name((volume) => this.setVolume(volume), "setVolume"),
466
+ getVolume: /* @__PURE__ */ __name(() => this.getVolume(), "getVolume"),
467
+ stopAll: /* @__PURE__ */ __name(() => this.stopAll(), "stopAll")
468
+ };
469
+ return this.interfaceCache;
470
+ }
471
+ /**
472
+ * Play sound effect
473
+ */
474
+ playSound(sound, volume = 1, pitch = 1, pan = 0, loopit = false) {
475
+ if (typeof sound === "string") {
476
+ const soundName = sound.replace(/\//g, "-");
477
+ const s = this.runtime.sounds[soundName];
478
+ if (!s) {
479
+ (0, import_diagnostics.reportRuntimeError)(this.runtime?.listener, import_diagnostics.APIErrorCode.E7013, {
480
+ soundName
481
+ });
482
+ return 0;
483
+ }
484
+ return s.play(volume * this.masterVolume, pitch, pan, loopit);
485
+ }
486
+ return 0;
487
+ }
488
+ /**
489
+ * Play music
490
+ */
491
+ playMusic(music, volume = 1, loopit = false) {
492
+ if (typeof music === "string") {
493
+ const musicName = music.replace(/\//g, "-");
494
+ const m = this.runtime.music[musicName];
495
+ if (!m) {
496
+ (0, import_diagnostics.reportRuntimeError)(this.runtime?.listener, import_diagnostics.APIErrorCode.E7014, {
497
+ musicName
498
+ });
499
+ return 0;
500
+ }
501
+ return m.play(volume * this.masterVolume, loopit);
502
+ }
503
+ return 0;
504
+ }
505
+ /**
506
+ * Get or create audio context (lazy initialization - created on first use)
507
+ * Note: Browser may suspend context until user interaction, which is handled automatically
508
+ */
509
+ getContext() {
510
+ if (!this.context) {
511
+ const AudioContextClass = window.AudioContext || window.webkitAudioContext;
512
+ this.context = new AudioContextClass();
513
+ if (this.context.state !== "running") {
514
+ const activate = /* @__PURE__ */ __name(() => {
515
+ if (this.context && this.context.state !== "running") {
516
+ this.context.resume();
517
+ if (this.beeper) {
518
+ this.start();
519
+ }
520
+ for (const item of this.wakeupList) {
521
+ item.wakeUp();
522
+ }
523
+ document.body.removeEventListener("touchend", activate);
524
+ document.body.removeEventListener("mouseup", activate);
525
+ document.body.removeEventListener("click", activate);
526
+ document.body.removeEventListener("keydown", activate);
527
+ }
528
+ }, "activate");
529
+ document.body.addEventListener("touchend", activate, {
530
+ once: true
531
+ });
532
+ document.body.addEventListener("mouseup", activate, {
533
+ once: true
534
+ });
535
+ document.body.addEventListener("click", activate, {
536
+ once: true
537
+ });
538
+ document.body.addEventListener("keydown", activate, {
539
+ once: true
540
+ });
541
+ } else if (this.beeper) {
542
+ this.start();
543
+ }
544
+ }
545
+ return this.context;
546
+ }
547
+ /**
548
+ * Start audio processor
549
+ */
550
+ async start() {
551
+ if (this.workletNode) return;
552
+ try {
553
+ const blob = new Blob([
554
+ AUDIO_WORKLET_CODE
555
+ ], {
556
+ type: "application/javascript"
557
+ });
558
+ const url = URL.createObjectURL(blob);
559
+ await this.context.audioWorklet.addModule(url);
560
+ this.workletNode = new AudioWorkletNode(this.context, "l8b-audio-processor");
561
+ this.workletNode.connect(this.context.destination);
562
+ this.flushBuffer();
563
+ } catch (e) {
564
+ (0, import_diagnostics.reportRuntimeError)(this.runtime?.listener, import_diagnostics.APIErrorCode.E7012, {
565
+ error: String(e)
566
+ });
567
+ }
568
+ }
569
+ /**
570
+ * Flush buffered messages
571
+ */
572
+ flushBuffer() {
573
+ if (!this.workletNode) return;
574
+ while (this.buffer.length > 0) {
575
+ this.workletNode.port.postMessage(this.buffer.splice(0, 1)[0]);
576
+ }
577
+ }
578
+ /**
579
+ * Get or create beeper
580
+ */
581
+ getBeeper() {
582
+ if (!this.beeper) {
583
+ this.beeper = new Beeper(this);
584
+ if (this.context.state === "running") {
585
+ this.start();
586
+ }
587
+ }
588
+ return this.beeper;
589
+ }
590
+ /**
591
+ * Play beep sequence
592
+ */
593
+ beep(sequence) {
594
+ this.getBeeper().beep(sequence);
595
+ }
596
+ /**
597
+ * Add beeps to audio processor
598
+ */
599
+ addBeeps(beeps) {
600
+ for (const b of beeps) {
601
+ b.duration *= this.context.sampleRate;
602
+ b.increment = b.frequency / this.context.sampleRate;
603
+ }
604
+ if (this.workletNode) {
605
+ this.workletNode.port.postMessage(JSON.stringify({
606
+ name: "beep",
607
+ sequence: beeps
608
+ }));
609
+ } else {
610
+ this.buffer.push(JSON.stringify({
611
+ name: "beep",
612
+ sequence: beeps
613
+ }));
614
+ }
615
+ }
616
+ /**
617
+ * Cancel all beeps
618
+ */
619
+ cancelBeeps() {
620
+ if (this.workletNode) {
621
+ this.workletNode.port.postMessage(JSON.stringify({
622
+ name: "cancel_beeps"
623
+ }));
624
+ } else {
625
+ this.buffer.push(JSON.stringify({
626
+ name: "cancel_beeps"
627
+ }));
628
+ }
629
+ this.stopAll();
630
+ }
631
+ /**
632
+ * Add playing sound/music to list
633
+ */
634
+ addPlaying(item) {
635
+ this.playing.push(item);
636
+ }
637
+ /**
638
+ * Remove playing sound/music from list
639
+ */
640
+ removePlaying(item) {
641
+ const index = this.playing.indexOf(item);
642
+ if (index >= 0) {
643
+ this.playing.splice(index, 1);
644
+ }
645
+ }
646
+ /**
647
+ * Stop all playing sounds/music
648
+ */
649
+ stopAll() {
650
+ for (const p of this.playing) {
651
+ try {
652
+ p.stop();
653
+ } catch (err) {
654
+ (0, import_diagnostics.reportRuntimeError)(this.runtime?.listener, import_diagnostics.APIErrorCode.E7016, {
655
+ error: String(err)
656
+ });
657
+ }
658
+ }
659
+ this.playing = [];
660
+ }
661
+ };
662
+ // Annotate the CommonJS export names for ESM import in node:
663
+ 0 && (module.exports = {
664
+ AudioCore
665
+ });
666
+ //# sourceMappingURL=index.js.map