waa-play 0.2.0 → 0.2.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.
Files changed (121) hide show
  1. package/README.md +41 -89
  2. package/dist/adapters.cjs +6 -6
  3. package/dist/adapters.d.cts +1 -1
  4. package/dist/adapters.d.ts +1 -1
  5. package/dist/adapters.js +1 -1
  6. package/dist/buffer.cjs +5 -5
  7. package/dist/buffer.d.cts +1 -1
  8. package/dist/buffer.d.ts +1 -1
  9. package/dist/buffer.js +1 -1
  10. package/dist/{chunk-T74FBKTY.js → chunk-2FGUFHZM.js} +2 -2
  11. package/dist/chunk-2FGUFHZM.js.map +1 -0
  12. package/dist/{chunk-CPAT75WD.cjs → chunk-3VTU5OX5.cjs} +2 -2
  13. package/dist/chunk-3VTU5OX5.cjs.map +1 -0
  14. package/dist/{chunk-2DL7CAEP.js → chunk-7JUVBZ6B.js} +2 -2
  15. package/dist/chunk-7JUVBZ6B.js.map +1 -0
  16. package/dist/{chunk-D5CD5KQZ.cjs → chunk-BRS7LZVH.cjs} +2 -2
  17. package/dist/chunk-BRS7LZVH.cjs.map +1 -0
  18. package/dist/{chunk-QWNV2BZ5.cjs → chunk-F6WXD3XW.cjs} +2 -2
  19. package/dist/chunk-F6WXD3XW.cjs.map +1 -0
  20. package/dist/{chunk-C2ASIYN5.js → chunk-FESPIMZM.js} +3 -7
  21. package/dist/chunk-FESPIMZM.js.map +1 -0
  22. package/dist/{chunk-GYH2JSCY.js → chunk-FY273Z3I.js} +2 -2
  23. package/dist/chunk-FY273Z3I.js.map +1 -0
  24. package/dist/{chunk-SIMLANWE.cjs → chunk-G37HMZEX.cjs} +1028 -955
  25. package/dist/chunk-G37HMZEX.cjs.map +1 -0
  26. package/dist/{chunk-2FFORBOP.js → chunk-GDBOHOGF.js} +1027 -955
  27. package/dist/chunk-GDBOHOGF.js.map +1 -0
  28. package/dist/{chunk-5J7S6QV3.cjs → chunk-HIF3UAF3.cjs} +2 -2
  29. package/dist/chunk-HIF3UAF3.cjs.map +1 -0
  30. package/dist/{chunk-CRODJ4KS.js → chunk-HTN52U23.js} +13 -6
  31. package/dist/chunk-HTN52U23.js.map +1 -0
  32. package/dist/{chunk-X4IFO7U7.js → chunk-HYRDCTBO.js} +143 -116
  33. package/dist/chunk-HYRDCTBO.js.map +1 -0
  34. package/dist/{chunk-VKT7YCWK.js → chunk-JIHPQAEA.js} +6 -3
  35. package/dist/chunk-JIHPQAEA.js.map +1 -0
  36. package/dist/chunk-KVKW7W66.cjs +148 -0
  37. package/dist/chunk-KVKW7W66.cjs.map +1 -0
  38. package/dist/{chunk-4LNVRSTM.cjs → chunk-OIY6I4TU.cjs} +3 -7
  39. package/dist/chunk-OIY6I4TU.cjs.map +1 -0
  40. package/dist/{chunk-7S5KWTZ6.cjs → chunk-OZN5X4N6.cjs} +6 -3
  41. package/dist/chunk-OZN5X4N6.cjs.map +1 -0
  42. package/dist/{chunk-CJJC6ASU.js → chunk-PL4J3NR7.js} +2 -2
  43. package/dist/chunk-PL4J3NR7.js.map +1 -0
  44. package/dist/{chunk-IMNRPYBM.js → chunk-QFJQU7TQ.js} +10 -10
  45. package/dist/chunk-QFJQU7TQ.js.map +1 -0
  46. package/dist/{chunk-M5PDY5EZ.cjs → chunk-QGZGERGK.cjs} +2 -2
  47. package/dist/chunk-QGZGERGK.cjs.map +1 -0
  48. package/dist/{chunk-QFFQQMU4.cjs → chunk-VOSIA3GF.cjs} +13 -6
  49. package/dist/chunk-VOSIA3GF.cjs.map +1 -0
  50. package/dist/{chunk-CTUCTTIE.cjs → chunk-VY4UMZMJ.cjs} +145 -118
  51. package/dist/chunk-VY4UMZMJ.cjs.map +1 -0
  52. package/dist/{chunk-LETS7FKB.js → chunk-YFK7ETCF.js} +2 -2
  53. package/dist/chunk-YFK7ETCF.js.map +1 -0
  54. package/dist/context.d.cts +1 -1
  55. package/dist/context.d.ts +1 -1
  56. package/dist/emitter.cjs +2 -2
  57. package/dist/emitter.js +1 -1
  58. package/dist/engine-7DCOERRN.js +4 -0
  59. package/dist/{engine-TYI7OX7O.js.map → engine-7DCOERRN.js.map} +1 -1
  60. package/dist/engine-ALWPAIX6.cjs +17 -0
  61. package/dist/{engine-QUMYW73L.cjs.map → engine-ALWPAIX6.cjs.map} +1 -1
  62. package/dist/fade.cjs +5 -5
  63. package/dist/fade.d.cts +1 -1
  64. package/dist/fade.d.ts +1 -1
  65. package/dist/fade.js +1 -1
  66. package/dist/index.cjs +44 -44
  67. package/dist/index.d.cts +7 -7
  68. package/dist/index.d.ts +7 -7
  69. package/dist/index.js +10 -10
  70. package/dist/nodes.cjs +11 -11
  71. package/dist/nodes.js +1 -1
  72. package/dist/play.cjs +3 -3
  73. package/dist/play.d.cts +1 -1
  74. package/dist/play.d.ts +1 -1
  75. package/dist/play.js +2 -2
  76. package/dist/player.cjs +11 -11
  77. package/dist/player.d.cts +1 -1
  78. package/dist/player.d.ts +1 -1
  79. package/dist/player.js +10 -10
  80. package/dist/scheduler.cjs +3 -3
  81. package/dist/scheduler.d.cts +1 -1
  82. package/dist/scheduler.d.ts +1 -1
  83. package/dist/scheduler.js +1 -1
  84. package/dist/stretcher.cjs +3 -3
  85. package/dist/stretcher.d.cts +4 -4
  86. package/dist/stretcher.d.ts +4 -4
  87. package/dist/stretcher.js +2 -2
  88. package/dist/synth.cjs +4 -4
  89. package/dist/synth.js +1 -1
  90. package/dist/{types-DUrbEbPl.d.cts → types-BYC6m7Q0.d.cts} +6 -6
  91. package/dist/{types-DUrbEbPl.d.ts → types-BYC6m7Q0.d.ts} +6 -6
  92. package/dist/waveform.cjs +4 -4
  93. package/dist/waveform.d.cts +1 -1
  94. package/dist/waveform.d.ts +1 -1
  95. package/dist/waveform.js +1 -1
  96. package/package.json +12 -5
  97. package/dist/chunk-2DL7CAEP.js.map +0 -1
  98. package/dist/chunk-2FFORBOP.js.map +0 -1
  99. package/dist/chunk-4LNVRSTM.cjs.map +0 -1
  100. package/dist/chunk-5J7S6QV3.cjs.map +0 -1
  101. package/dist/chunk-7S5KWTZ6.cjs.map +0 -1
  102. package/dist/chunk-C2ASIYN5.js.map +0 -1
  103. package/dist/chunk-CJJC6ASU.js.map +0 -1
  104. package/dist/chunk-CPAT75WD.cjs.map +0 -1
  105. package/dist/chunk-CRODJ4KS.js.map +0 -1
  106. package/dist/chunk-CTUCTTIE.cjs.map +0 -1
  107. package/dist/chunk-D5CD5KQZ.cjs.map +0 -1
  108. package/dist/chunk-GYH2JSCY.js.map +0 -1
  109. package/dist/chunk-IMNRPYBM.js.map +0 -1
  110. package/dist/chunk-LETS7FKB.js.map +0 -1
  111. package/dist/chunk-M5PDY5EZ.cjs.map +0 -1
  112. package/dist/chunk-QFFQQMU4.cjs.map +0 -1
  113. package/dist/chunk-QWNV2BZ5.cjs.map +0 -1
  114. package/dist/chunk-SIMLANWE.cjs.map +0 -1
  115. package/dist/chunk-T74FBKTY.js.map +0 -1
  116. package/dist/chunk-VKT7YCWK.js.map +0 -1
  117. package/dist/chunk-X4IFO7U7.js.map +0 -1
  118. package/dist/chunk-XZBMBZA3.cjs +0 -148
  119. package/dist/chunk-XZBMBZA3.cjs.map +0 -1
  120. package/dist/engine-QUMYW73L.cjs +0 -13
  121. package/dist/engine-TYI7OX7O.js +0 -4
@@ -1,4 +1,58 @@
1
- import { createEmitter } from './chunk-GYH2JSCY.js';
1
+ import { createEmitter } from './chunk-FY273Z3I.js';
2
+
3
+ // src/playback-position.ts
4
+ function calcLoopPosition(elapsed, loopStart, loopEnd) {
5
+ const loopDur = loopEnd - loopStart;
6
+ if (loopDur <= 0) return null;
7
+ const offset = elapsed - loopStart;
8
+ return (offset % loopDur + loopDur) % loopDur + loopStart;
9
+ }
10
+ function calcPlaybackPosition(state, elapsed, duration, pausedAt, isLooping, loopStart, loopEnd) {
11
+ if (state === "paused") return pausedAt;
12
+ if (state === "stopped") return 0;
13
+ if (isLooping) {
14
+ const looped = calcLoopPosition(elapsed, loopStart ?? 0, loopEnd ?? duration);
15
+ if (looped !== null) return looped;
16
+ }
17
+ return Math.min(Math.max(elapsed, 0), duration);
18
+ }
19
+
20
+ // src/playback-state.ts
21
+ function createPlaybackStateManager(opts) {
22
+ let state = opts.initialState;
23
+ let timerId = null;
24
+ let disposed = false;
25
+ function getState() {
26
+ return state;
27
+ }
28
+ function setState(next) {
29
+ if (state === next) return false;
30
+ state = next;
31
+ opts.onStateChange(next);
32
+ return true;
33
+ }
34
+ function startTimer() {
35
+ if (timerId !== null) return;
36
+ timerId = setInterval(() => {
37
+ if (state !== "playing" || disposed) return;
38
+ opts.onTimerTick();
39
+ }, opts.timerInterval);
40
+ }
41
+ function stopTimer() {
42
+ if (timerId !== null) {
43
+ clearInterval(timerId);
44
+ timerId = null;
45
+ }
46
+ }
47
+ function isDisposed() {
48
+ return disposed;
49
+ }
50
+ function markDisposed() {
51
+ disposed = true;
52
+ stopTimer();
53
+ }
54
+ return { getState, setState, startTimer, stopTimer, isDisposed, markDisposed };
55
+ }
2
56
 
3
57
  // src/play.ts
4
58
  function play(ctx, buffer, options) {
@@ -18,14 +72,22 @@ function play(ctx, buffer, options) {
18
72
  } = options ?? {};
19
73
  const emitter = createEmitter();
20
74
  const duration = buffer.duration;
21
- let state = "stopped";
22
75
  let sourceNode = null;
23
76
  let startedAt = 0;
24
77
  let pausedAt = initialOffset;
25
- let currentRate = initialRate;
78
+ let currentRate = initialRate > 0 ? initialRate : 1;
26
79
  let isLooping = loop;
27
- let timerId = null;
28
- let disposed = false;
80
+ const sm = createPlaybackStateManager({
81
+ initialState: "stopped",
82
+ onStateChange: (next) => emitter.emit("statechange", { state: next }),
83
+ onTimerTick: () => {
84
+ emitter.emit("timeupdate", {
85
+ position: getCurrentTime(),
86
+ duration
87
+ });
88
+ },
89
+ timerInterval: timeupdateInterval
90
+ });
29
91
  function createSource() {
30
92
  const src = ctx.createBufferSource();
31
93
  src.buffer = buffer;
@@ -62,90 +124,63 @@ function play(ctx, buffer, options) {
62
124
  }
63
125
  }
64
126
  function handleEnded() {
65
- if (state !== "playing") return;
127
+ if (sm.getState() !== "playing") return;
66
128
  if (isLooping) {
67
129
  emitter.emit("loop", void 0);
68
130
  return;
69
131
  }
70
- setState("stopped");
132
+ sm.setState("stopped");
71
133
  pausedAt = 0;
72
- stopTimer();
134
+ sm.stopTimer();
73
135
  emitter.emit("ended", void 0);
74
136
  }
75
- function setState(next) {
76
- if (state === next) return;
77
- state = next;
78
- emitter.emit("statechange", { state: next });
79
- }
80
- function startTimer() {
81
- if (timerId !== null) return;
82
- timerId = setInterval(() => {
83
- if (state !== "playing") return;
84
- emitter.emit("timeupdate", {
85
- position: getCurrentTime(),
86
- duration
87
- });
88
- }, timeupdateInterval);
89
- }
90
- function stopTimer() {
91
- if (timerId !== null) {
92
- clearInterval(timerId);
93
- timerId = null;
94
- }
95
- }
96
137
  function getCurrentTime() {
97
- if (state === "playing") {
98
- const elapsed = (ctx.currentTime - startedAt) * currentRate;
99
- if (isLooping) {
100
- const loopDur = (loopEnd ?? duration) - (loopStart ?? 0);
101
- return (elapsed - (loopStart ?? 0)) % loopDur + (loopStart ?? 0);
102
- }
103
- return Math.min(elapsed, duration);
104
- }
105
- if (state === "paused") return pausedAt;
106
- return 0;
138
+ const state = sm.getState();
139
+ const elapsed = state === "playing" ? (ctx.currentTime - startedAt) * currentRate : 0;
140
+ return calcPlaybackPosition(state, elapsed, duration, pausedAt, isLooping, loopStart, loopEnd);
107
141
  }
108
142
  function pause() {
109
- if (state !== "playing" || disposed) return;
143
+ if (sm.getState() !== "playing" || sm.isDisposed()) return;
110
144
  pausedAt = getCurrentTime();
111
145
  stopSource();
112
- stopTimer();
113
- setState("paused");
146
+ sm.stopTimer();
147
+ sm.setState("paused");
114
148
  emitter.emit("pause", void 0);
115
149
  }
116
150
  function resume() {
117
- if (state !== "paused" || disposed) return;
151
+ if (sm.getState() !== "paused" || sm.isDisposed()) return;
118
152
  startSource(pausedAt);
119
- setState("playing");
120
- startTimer();
153
+ sm.setState("playing");
154
+ sm.startTimer();
121
155
  emitter.emit("resume", void 0);
122
156
  }
123
157
  function togglePlayPause() {
124
- if (state === "playing") pause();
125
- else if (state === "paused") resume();
158
+ if (sm.getState() === "playing") pause();
159
+ else if (sm.getState() === "paused") resume();
126
160
  }
127
161
  function seek(position) {
128
- if (disposed) return;
162
+ if (sm.isDisposed()) return;
129
163
  const clamped = Math.max(0, Math.min(position, duration));
130
- const wasPlaying = state === "playing";
164
+ const wasPlaying = sm.getState() === "playing";
131
165
  stopSource();
132
- stopTimer();
166
+ sm.stopTimer();
133
167
  pausedAt = clamped;
134
168
  if (wasPlaying) {
135
169
  startSource(clamped);
136
- startTimer();
170
+ sm.startTimer();
137
171
  }
138
172
  emitter.emit("seek", { position: clamped });
139
173
  }
140
174
  function stop() {
141
- if (state === "stopped" || disposed) return;
175
+ if (sm.getState() === "stopped" || sm.isDisposed()) return;
142
176
  stopSource();
143
- stopTimer();
177
+ sm.stopTimer();
144
178
  pausedAt = 0;
145
- setState("stopped");
179
+ sm.setState("stopped");
146
180
  emitter.emit("stop", void 0);
147
181
  }
148
182
  function setPlaybackRate(rate) {
183
+ if (rate <= 0) return;
149
184
  const position = getCurrentTime();
150
185
  currentRate = rate;
151
186
  if (sourceNode) {
@@ -160,18 +195,17 @@ function play(ctx, buffer, options) {
160
195
  }
161
196
  }
162
197
  function dispose() {
163
- if (disposed) return;
164
- disposed = true;
198
+ if (sm.isDisposed()) return;
199
+ sm.markDisposed();
165
200
  stopSource();
166
- stopTimer();
167
201
  emitter.clear();
168
202
  }
169
203
  startSource(initialOffset);
170
- setState("playing");
171
- startTimer();
204
+ sm.setState("playing");
205
+ sm.startTimer();
172
206
  emitter.emit("play", void 0);
173
207
  return {
174
- getState: () => state,
208
+ getState: () => sm.getState(),
175
209
  getCurrentTime,
176
210
  getDuration: () => duration,
177
211
  getProgress: () => duration > 0 ? getCurrentTime() / duration : 0,
@@ -198,17 +232,25 @@ function createStretchedPlayback(ctx, buffer, options) {
198
232
  } = options;
199
233
  const emitter = createEmitter();
200
234
  const duration = buffer.duration;
201
- let state = "playing";
202
235
  let engineInstance = null;
203
- let timerId = null;
204
- let disposed = false;
205
- let currentRate = initialRate;
236
+ let currentRate = initialRate > 0 ? initialRate : 1;
206
237
  let isLooping = loop;
207
238
  let pendingSeek = null;
239
+ const sm = createPlaybackStateManager({
240
+ initialState: "playing",
241
+ onStateChange: (next) => emitter.emit("statechange", { state: next }),
242
+ onTimerTick: () => {
243
+ emitter.emit("timeupdate", {
244
+ position: getCurrentTime(),
245
+ duration
246
+ });
247
+ },
248
+ timerInterval: timeupdateInterval
249
+ });
208
250
  emitter.emit("statechange", { state: "playing" });
209
251
  emitter.emit("play", void 0);
210
- import('./engine-TYI7OX7O.js').then(({ createStretcherEngine }) => {
211
- if (disposed) return;
252
+ import('./engine-7DCOERRN.js').then(({ createStretcherEngine }) => {
253
+ if (sm.isDisposed()) return;
212
254
  engineInstance = createStretcherEngine(ctx, buffer, {
213
255
  tempo: currentRate,
214
256
  offset: initialOffset,
@@ -218,60 +260,48 @@ function createStretchedPlayback(ctx, buffer, options) {
218
260
  timeupdateInterval
219
261
  });
220
262
  engineInstance.on("buffering", (data) => {
221
- if (disposed) return;
263
+ if (sm.isDisposed()) return;
222
264
  emitter.emit("buffering", data);
223
265
  });
224
266
  engineInstance.on("buffered", (data) => {
225
- if (disposed) return;
267
+ if (sm.isDisposed()) return;
226
268
  emitter.emit("buffered", data);
227
269
  });
228
270
  engineInstance.on("loop", () => {
229
- if (disposed) return;
271
+ if (sm.isDisposed()) return;
230
272
  emitter.emit("loop", void 0);
231
273
  });
232
274
  engineInstance.on("ended", () => {
233
- if (disposed) return;
234
- state = "stopped";
235
- stopTimer();
236
- emitter.emit("statechange", { state: "stopped" });
275
+ if (sm.isDisposed()) return;
276
+ if (sm.getState() === "stopped") return;
277
+ sm.stopTimer();
278
+ sm.setState("stopped");
237
279
  emitter.emit("ended", void 0);
238
280
  });
239
281
  engineInstance.on("error", (data) => {
240
- if (disposed) return;
282
+ if (sm.isDisposed()) return;
241
283
  if (data.fatal) {
242
- state = "stopped";
243
- emitter.emit("statechange", { state: "stopped" });
284
+ sm.setState("stopped");
244
285
  emitter.emit("ended", void 0);
245
286
  }
246
287
  });
247
288
  engineInstance.start();
248
- startTimer();
289
+ sm.startTimer();
249
290
  if (pendingSeek !== null) {
250
291
  engineInstance.seek(pendingSeek);
251
292
  pendingSeek = null;
252
293
  }
253
- if (state === "paused") {
294
+ if (sm.getState() === "paused") {
254
295
  engineInstance.pause();
255
- } else if (state === "stopped") {
296
+ } else if (sm.getState() === "stopped") {
256
297
  engineInstance.stop();
257
298
  }
299
+ }).catch(() => {
300
+ if (sm.isDisposed()) return;
301
+ sm.stopTimer();
302
+ sm.setState("stopped");
303
+ emitter.emit("ended", void 0);
258
304
  });
259
- function startTimer() {
260
- if (timerId !== null) return;
261
- timerId = setInterval(() => {
262
- if (state !== "playing" || disposed) return;
263
- emitter.emit("timeupdate", {
264
- position: getCurrentTime(),
265
- duration
266
- });
267
- }, timeupdateInterval);
268
- }
269
- function stopTimer() {
270
- if (timerId !== null) {
271
- clearInterval(timerId);
272
- timerId = null;
273
- }
274
- }
275
305
  function getCurrentTime() {
276
306
  if (pendingSeek !== null) {
277
307
  return pendingSeek;
@@ -282,27 +312,25 @@ function createStretchedPlayback(ctx, buffer, options) {
282
312
  return initialOffset;
283
313
  }
284
314
  function pause() {
285
- if (state !== "playing" || disposed) return;
286
- state = "paused";
315
+ if (sm.getState() !== "playing" || sm.isDisposed()) return;
287
316
  engineInstance?.pause();
288
- stopTimer();
289
- emitter.emit("statechange", { state: "paused" });
317
+ sm.stopTimer();
318
+ sm.setState("paused");
290
319
  emitter.emit("pause", void 0);
291
320
  }
292
321
  function resume() {
293
- if (state !== "paused" || disposed) return;
294
- state = "playing";
322
+ if (sm.getState() !== "paused" || sm.isDisposed()) return;
295
323
  engineInstance?.resume();
296
- startTimer();
297
- emitter.emit("statechange", { state: "playing" });
324
+ sm.startTimer();
325
+ sm.setState("playing");
298
326
  emitter.emit("resume", void 0);
299
327
  }
300
328
  function togglePlayPause() {
301
- if (state === "playing") pause();
302
- else if (state === "paused") resume();
329
+ if (sm.getState() === "playing") pause();
330
+ else if (sm.getState() === "paused") resume();
303
331
  }
304
332
  function seek(position) {
305
- if (disposed) return;
333
+ if (sm.isDisposed()) return;
306
334
  const clamped = Math.max(0, Math.min(position, duration));
307
335
  if (engineInstance) {
308
336
  engineInstance.seek(clamped);
@@ -312,14 +340,14 @@ function createStretchedPlayback(ctx, buffer, options) {
312
340
  emitter.emit("seek", { position: clamped });
313
341
  }
314
342
  function stop() {
315
- if (state === "stopped" || disposed) return;
316
- state = "stopped";
343
+ if (sm.getState() === "stopped" || sm.isDisposed()) return;
317
344
  engineInstance?.stop();
318
- stopTimer();
319
- emitter.emit("statechange", { state: "stopped" });
345
+ sm.stopTimer();
346
+ sm.setState("stopped");
320
347
  emitter.emit("stop", void 0);
321
348
  }
322
349
  function setPlaybackRate(rate) {
350
+ if (rate <= 0) return;
323
351
  currentRate = rate;
324
352
  if (engineInstance) {
325
353
  engineInstance.setTempo(rate);
@@ -330,9 +358,8 @@ function createStretchedPlayback(ctx, buffer, options) {
330
358
  engineInstance?.setLoop(value);
331
359
  }
332
360
  function dispose() {
333
- if (disposed) return;
334
- disposed = true;
335
- stopTimer();
361
+ if (sm.isDisposed()) return;
362
+ sm.markDisposed();
336
363
  engineInstance?.dispose();
337
364
  emitter.clear();
338
365
  }
@@ -341,7 +368,7 @@ function createStretchedPlayback(ctx, buffer, options) {
341
368
  return engineInstance.getSnapshot();
342
369
  }
343
370
  const playback = {
344
- getState: () => state,
371
+ getState: () => sm.getState(),
345
372
  getCurrentTime,
346
373
  getDuration: () => duration,
347
374
  getProgress: () => duration > 0 ? getCurrentTime() / duration : 0,
@@ -361,5 +388,5 @@ function createStretchedPlayback(ctx, buffer, options) {
361
388
  }
362
389
 
363
390
  export { play };
364
- //# sourceMappingURL=chunk-X4IFO7U7.js.map
365
- //# sourceMappingURL=chunk-X4IFO7U7.js.map
391
+ //# sourceMappingURL=chunk-HYRDCTBO.js.map
392
+ //# sourceMappingURL=chunk-HYRDCTBO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/playback-position.ts","../src/playback-state.ts","../src/play.ts"],"names":[],"mappings":"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","file":"chunk-HYRDCTBO.js","sourcesContent":["// ---------------------------------------------------------------------------\n// Pure functions for playback position calculation\n// ---------------------------------------------------------------------------\n\n/**\n * Calculate the current position within a loop region.\n *\n * Uses a true modulo (always non-negative) to avoid the JS `%` sign-preservation\n * issue where `elapsed < loopStart` would produce a value outside the loop region.\n *\n * Returns `null` when the loop region is invalid (loopDur <= 0) so the caller\n * can fall back to non-loop behaviour.\n */\nexport function calcLoopPosition(\n elapsed: number,\n loopStart: number,\n loopEnd: number,\n): number | null {\n const loopDur = loopEnd - loopStart;\n if (loopDur <= 0) return null;\n const offset = elapsed - loopStart;\n return (((offset % loopDur) + loopDur) % loopDur) + loopStart;\n}\n\n/**\n * Calculate the playback position for a given state.\n *\n * Pure function — no side effects, no dependency on AudioContext.\n */\nexport function calcPlaybackPosition(\n state: \"playing\" | \"paused\" | \"stopped\",\n elapsed: number,\n duration: number,\n pausedAt: number,\n isLooping: boolean,\n loopStart: number | undefined,\n loopEnd: number | undefined,\n): number {\n if (state === \"paused\") return pausedAt;\n if (state === \"stopped\") return 0;\n\n // state === \"playing\"\n if (isLooping) {\n const looped = calcLoopPosition(elapsed, loopStart ?? 0, loopEnd ?? duration);\n // Invalid loop region → fall back to non-loop clamping\n if (looped !== null) return looped;\n }\n return Math.min(Math.max(elapsed, 0), duration);\n}\n","// ---------------------------------------------------------------------------\n// Shared playback state management (used by both normal and stretched modes)\n// ---------------------------------------------------------------------------\n\nimport type { PlaybackState } from \"./types.js\";\n\nexport interface PlaybackStateManager {\n getState(): PlaybackState;\n setState(next: PlaybackState): boolean;\n startTimer(): void;\n stopTimer(): void;\n isDisposed(): boolean;\n markDisposed(): void;\n}\n\n/**\n * Create a reusable state manager that encapsulates the setState / startTimer /\n * stopTimer / dispose pattern shared between normal and stretched playback.\n */\nexport function createPlaybackStateManager(opts: {\n initialState: PlaybackState;\n onStateChange: (state: PlaybackState) => void;\n onTimerTick: () => void;\n timerInterval: number;\n}): PlaybackStateManager {\n let state: PlaybackState = opts.initialState;\n let timerId: ReturnType<typeof setInterval> | null = null;\n let disposed = false;\n\n function getState(): PlaybackState {\n return state;\n }\n\n /** Returns `true` if state actually changed. */\n function setState(next: PlaybackState): boolean {\n if (state === next) return false;\n state = next;\n opts.onStateChange(next);\n return true;\n }\n\n function startTimer(): void {\n if (timerId !== null) return;\n timerId = setInterval(() => {\n if (state !== \"playing\" || disposed) return;\n opts.onTimerTick();\n }, opts.timerInterval);\n }\n\n function stopTimer(): void {\n if (timerId !== null) {\n clearInterval(timerId);\n timerId = null;\n }\n }\n\n function isDisposed(): boolean {\n return disposed;\n }\n\n function markDisposed(): void {\n disposed = true;\n stopTimer();\n }\n\n return { getState, setState, startTimer, stopTimer, isDisposed, markDisposed };\n}\n","// ---------------------------------------------------------------------------\n// M3: Playback engine\n// ---------------------------------------------------------------------------\n\nimport { createEmitter } from \"./emitter.js\";\nimport { calcPlaybackPosition } from \"./playback-position.js\";\nimport { createPlaybackStateManager } from \"./playback-state.js\";\nimport type {\n Playback,\n PlaybackEventMap,\n PlayOptions,\n StretcherSnapshotExtension,\n} from \"./types.js\";\n\n/**\n * Play an `AudioBuffer` through an `AudioContext` and return a controllable\n * `Playback` handle.\n *\n * ```ts\n * const pb = play(ctx, buffer, { loop: true });\n * pb.on(\"timeupdate\", ({ position }) => console.log(position));\n * pb.pause();\n * pb.resume();\n * pb.seek(10);\n * pb.stop();\n * pb.dispose();\n * ```\n */\nexport function play(ctx: AudioContext, buffer: AudioBuffer, options?: PlayOptions): Playback {\n const { preservePitch = true } = options ?? {};\n\n // ----- Pitch-preserving mode (WSOLA-based time-stretch) -----\n if (preservePitch) {\n return createStretchedPlayback(ctx, buffer, options ?? {});\n }\n\n const {\n offset: initialOffset = 0,\n loop = false,\n loopStart,\n loopEnd,\n playbackRate: initialRate = 1,\n through = [],\n destination = ctx.destination,\n timeupdateInterval = 50,\n } = options ?? {};\n\n const emitter = createEmitter<PlaybackEventMap>();\n const duration = buffer.duration;\n\n // ----- mutable internal state -----\n let sourceNode: AudioBufferSourceNode | null = null;\n let startedAt = 0; // ctx.currentTime when playback last started/resumed\n let pausedAt = initialOffset; // position in the buffer (seconds)\n let currentRate = initialRate > 0 ? initialRate : 1;\n let isLooping = loop;\n\n const sm = createPlaybackStateManager({\n initialState: \"stopped\",\n onStateChange: (next) => emitter.emit(\"statechange\", { state: next }),\n onTimerTick: () => {\n emitter.emit(\"timeupdate\", {\n position: getCurrentTime(),\n duration,\n });\n },\n timerInterval: timeupdateInterval,\n });\n\n // ----- helpers -----\n\n function createSource(): AudioBufferSourceNode {\n const src = ctx.createBufferSource();\n src.buffer = buffer;\n src.playbackRate.value = currentRate;\n src.loop = isLooping;\n if (loopStart !== undefined) src.loopStart = loopStart;\n if (loopEnd !== undefined) src.loopEnd = loopEnd;\n\n // Connect through the node chain (or directly to destination).\n if (through.length > 0) {\n src.connect(through[0]!);\n for (let i = 0; i < through.length - 1; i++) {\n through[i]!.connect(through[i + 1]!);\n }\n through[through.length - 1]!.connect(destination);\n } else {\n src.connect(destination);\n }\n\n src.onended = handleEnded;\n return src;\n }\n\n function startSource(positionInBuffer: number) {\n sourceNode = createSource();\n sourceNode.start(0, positionInBuffer);\n startedAt = ctx.currentTime - positionInBuffer / currentRate;\n }\n\n function stopSource() {\n if (sourceNode) {\n sourceNode.onended = null;\n try {\n sourceNode.stop();\n } catch {\n // Already stopped — safe to ignore.\n }\n sourceNode.disconnect();\n sourceNode = null;\n }\n }\n\n function handleEnded() {\n // If we manually stopped / paused, the handler was already removed.\n if (sm.getState() !== \"playing\") return;\n if (isLooping) {\n emitter.emit(\"loop\", undefined as never);\n return;\n }\n sm.setState(\"stopped\");\n pausedAt = 0;\n sm.stopTimer();\n emitter.emit(\"ended\", undefined as never);\n }\n\n // ----- public API -----\n\n function getCurrentTime(): number {\n const state = sm.getState();\n const elapsed = state === \"playing\" ? (ctx.currentTime - startedAt) * currentRate : 0;\n return calcPlaybackPosition(state, elapsed, duration, pausedAt, isLooping, loopStart, loopEnd);\n }\n\n function pause() {\n if (sm.getState() !== \"playing\" || sm.isDisposed()) return;\n pausedAt = getCurrentTime();\n stopSource();\n sm.stopTimer();\n sm.setState(\"paused\");\n emitter.emit(\"pause\", undefined as never);\n }\n\n function resume() {\n if (sm.getState() !== \"paused\" || sm.isDisposed()) return;\n startSource(pausedAt);\n sm.setState(\"playing\");\n sm.startTimer();\n emitter.emit(\"resume\", undefined as never);\n }\n\n function togglePlayPause() {\n if (sm.getState() === \"playing\") pause();\n else if (sm.getState() === \"paused\") resume();\n }\n\n function seek(position: number) {\n if (sm.isDisposed()) return;\n const clamped = Math.max(0, Math.min(position, duration));\n const wasPlaying = sm.getState() === \"playing\";\n\n stopSource();\n sm.stopTimer();\n\n pausedAt = clamped;\n\n if (wasPlaying) {\n startSource(clamped);\n sm.startTimer();\n }\n\n emitter.emit(\"seek\", { position: clamped });\n }\n\n function stop() {\n if (sm.getState() === \"stopped\" || sm.isDisposed()) return;\n stopSource();\n sm.stopTimer();\n pausedAt = 0;\n sm.setState(\"stopped\");\n emitter.emit(\"stop\", undefined as never);\n }\n\n function setPlaybackRate(rate: number) {\n if (rate <= 0) return;\n const position = getCurrentTime();\n currentRate = rate;\n if (sourceNode) {\n sourceNode.playbackRate.value = rate;\n startedAt = ctx.currentTime - position / rate;\n }\n }\n\n function setLoop(value: boolean) {\n isLooping = value;\n if (sourceNode) {\n sourceNode.loop = value;\n }\n }\n\n function dispose() {\n if (sm.isDisposed()) return;\n sm.markDisposed();\n stopSource();\n emitter.clear();\n }\n\n // ----- kick off initial playback -----\n\n startSource(initialOffset);\n sm.setState(\"playing\");\n sm.startTimer();\n emitter.emit(\"play\", undefined as never);\n\n return {\n getState: () => sm.getState(),\n getCurrentTime,\n getDuration: () => duration,\n getProgress: () => (duration > 0 ? getCurrentTime() / duration : 0),\n pause,\n resume,\n togglePlayPause,\n seek,\n stop,\n setPlaybackRate,\n setLoop,\n on: emitter.on.bind(emitter) as Playback[\"on\"],\n off: emitter.off.bind(emitter) as Playback[\"off\"],\n dispose,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Stretched playback (preservePitch: true)\n// ---------------------------------------------------------------------------\n\nfunction createStretchedPlayback(\n ctx: AudioContext,\n buffer: AudioBuffer,\n options: PlayOptions,\n): Playback {\n const {\n offset: initialOffset = 0,\n loop = false,\n playbackRate: initialRate = 1,\n through = [],\n destination = ctx.destination,\n timeupdateInterval = 50,\n } = options;\n\n const emitter = createEmitter<PlaybackEventMap>();\n const duration = buffer.duration;\n\n let engineInstance: import(\"./stretcher/types.js\").StretcherEngine | null = null;\n let currentRate = initialRate > 0 ? initialRate : 1;\n let isLooping = loop;\n let pendingSeek: number | null = null;\n\n const sm = createPlaybackStateManager({\n initialState: \"playing\",\n onStateChange: (next) => emitter.emit(\"statechange\", { state: next }),\n onTimerTick: () => {\n emitter.emit(\"timeupdate\", {\n position: getCurrentTime(),\n duration,\n });\n },\n timerInterval: timeupdateInterval,\n });\n\n // Emit initial play event\n emitter.emit(\"statechange\", { state: \"playing\" });\n emitter.emit(\"play\", undefined as never);\n\n // Fire-and-forget dynamic import of the stretcher engine\n import(\"./stretcher/engine.js\")\n .then(({ createStretcherEngine }) => {\n if (sm.isDisposed()) return;\n\n engineInstance = createStretcherEngine(ctx, buffer, {\n tempo: currentRate,\n offset: initialOffset,\n loop: isLooping,\n through,\n destination,\n timeupdateInterval,\n });\n\n // Wire stretcher events to playback events\n engineInstance.on(\"buffering\", (data) => {\n if (sm.isDisposed()) return;\n emitter.emit(\"buffering\", data);\n });\n\n engineInstance.on(\"buffered\", (data) => {\n if (sm.isDisposed()) return;\n emitter.emit(\"buffered\", data);\n });\n\n engineInstance.on(\"loop\", () => {\n if (sm.isDisposed()) return;\n emitter.emit(\"loop\", undefined as never);\n });\n\n engineInstance.on(\"ended\", () => {\n if (sm.isDisposed()) return;\n if (sm.getState() === \"stopped\") return;\n sm.stopTimer();\n sm.setState(\"stopped\");\n emitter.emit(\"ended\", undefined as never);\n });\n\n engineInstance.on(\"error\", (data) => {\n if (sm.isDisposed()) return;\n if (data.fatal) {\n sm.setState(\"stopped\");\n emitter.emit(\"ended\", undefined as never);\n }\n });\n\n // Start engine and timeupdate timer\n engineInstance.start();\n sm.startTimer();\n\n // Apply pending seek if any\n if (pendingSeek !== null) {\n engineInstance.seek(pendingSeek);\n pendingSeek = null;\n }\n\n // If we were paused before the engine loaded, pause it\n if (sm.getState() === \"paused\") {\n engineInstance.pause();\n } else if (sm.getState() === \"stopped\") {\n engineInstance.stop();\n }\n })\n .catch(() => {\n if (sm.isDisposed()) return;\n sm.stopTimer();\n sm.setState(\"stopped\");\n emitter.emit(\"ended\", undefined as never);\n });\n\n function getCurrentTime(): number {\n if (pendingSeek !== null) {\n return pendingSeek;\n }\n if (engineInstance) {\n return engineInstance.getCurrentPosition();\n }\n return initialOffset;\n }\n\n function pause() {\n if (sm.getState() !== \"playing\" || sm.isDisposed()) return;\n engineInstance?.pause();\n sm.stopTimer();\n sm.setState(\"paused\");\n emitter.emit(\"pause\", undefined as never);\n }\n\n function resume() {\n if (sm.getState() !== \"paused\" || sm.isDisposed()) return;\n engineInstance?.resume();\n sm.startTimer();\n sm.setState(\"playing\");\n emitter.emit(\"resume\", undefined as never);\n }\n\n function togglePlayPause() {\n if (sm.getState() === \"playing\") pause();\n else if (sm.getState() === \"paused\") resume();\n }\n\n function seek(position: number) {\n if (sm.isDisposed()) return;\n const clamped = Math.max(0, Math.min(position, duration));\n if (engineInstance) {\n engineInstance.seek(clamped);\n } else {\n pendingSeek = clamped;\n }\n emitter.emit(\"seek\", { position: clamped });\n }\n\n function stop() {\n if (sm.getState() === \"stopped\" || sm.isDisposed()) return;\n engineInstance?.stop();\n sm.stopTimer();\n sm.setState(\"stopped\");\n emitter.emit(\"stop\", undefined as never);\n }\n\n function setPlaybackRate(rate: number) {\n if (rate <= 0) return;\n currentRate = rate;\n if (engineInstance) {\n engineInstance.setTempo(rate);\n }\n }\n\n function setLoop(value: boolean) {\n isLooping = value;\n engineInstance?.setLoop(value);\n }\n\n function dispose() {\n if (sm.isDisposed()) return;\n sm.markDisposed();\n engineInstance?.dispose();\n emitter.clear();\n }\n\n function _getStretcherSnapshot(): StretcherSnapshotExtension | null {\n if (!engineInstance) return null;\n return engineInstance.getSnapshot();\n }\n\n const playback: Playback & {\n _getStretcherSnapshot: typeof _getStretcherSnapshot;\n } = {\n getState: () => sm.getState(),\n getCurrentTime,\n getDuration: () => duration,\n getProgress: () => (duration > 0 ? getCurrentTime() / duration : 0),\n pause,\n resume,\n togglePlayPause,\n seek,\n stop,\n setPlaybackRate,\n setLoop,\n on: emitter.on.bind(emitter) as Playback[\"on\"],\n off: emitter.off.bind(emitter) as Playback[\"off\"],\n dispose,\n _getStretcherSnapshot,\n };\n\n return playback;\n}\n"]}
@@ -6,7 +6,7 @@ function computeSnapshot(playback) {
6
6
  const position = playback.getCurrentTime();
7
7
  const duration = playback.getDuration();
8
8
  const progress = playback.getProgress();
9
- const getter = playback["_getStretcherSnapshot"];
9
+ const getter = playback._getStretcherSnapshot;
10
10
  let stretcher;
11
11
  if (typeof getter === "function") {
12
12
  stretcher = getter();
@@ -72,6 +72,9 @@ function whenEnded(playback) {
72
72
  });
73
73
  }
74
74
  function whenPosition(playback, position) {
75
+ if (playback.getCurrentTime() >= position) {
76
+ return Promise.resolve();
77
+ }
75
78
  return new Promise((resolve) => {
76
79
  const unsub = playback.on("timeupdate", ({ position: current }) => {
77
80
  if (current >= position) {
@@ -83,5 +86,5 @@ function whenPosition(playback, position) {
83
86
  }
84
87
 
85
88
  export { getSnapshot, onFrame, subscribeSnapshot, whenEnded, whenPosition };
86
- //# sourceMappingURL=chunk-VKT7YCWK.js.map
87
- //# sourceMappingURL=chunk-VKT7YCWK.js.map
89
+ //# sourceMappingURL=chunk-JIHPQAEA.js.map
90
+ //# sourceMappingURL=chunk-JIHPQAEA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/adapters.ts"],"names":[],"mappings":"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","file":"chunk-JIHPQAEA.js","sourcesContent":["// ---------------------------------------------------------------------------\n// M10: Framework adapters\n// ---------------------------------------------------------------------------\n\nimport type { Playback, PlaybackSnapshot } from \"./types.js\";\n\nconst snapshotCache = new WeakMap<Playback, PlaybackSnapshot>();\nconst subscriberCount = new WeakMap<Playback, number>();\n\nfunction computeSnapshot(playback: Playback): PlaybackSnapshot {\n const state = playback.getState();\n const position = playback.getCurrentTime();\n const duration = playback.getDuration();\n const progress = playback.getProgress();\n\n const getter = (playback as unknown as Record<string, unknown>)._getStretcherSnapshot;\n let stretcher: PlaybackSnapshot[\"stretcher\"];\n if (typeof getter === \"function\") {\n stretcher = (getter as () => PlaybackSnapshot[\"stretcher\"])();\n }\n\n const snap: PlaybackSnapshot = { state, position, duration, progress };\n if (stretcher) {\n snap.stretcher = stretcher;\n }\n return snap;\n}\n\n/**\n * Get an immutable snapshot of the current playback state.\n * Designed for use with React's `useSyncExternalStore` or similar patterns.\n *\n * Always returns a referentially stable (cached) object. The cache is updated\n * by `subscribeSnapshot` (on playback events) and `onFrame` (every animation\n * frame), so `getSnapshot` itself never computes a fresh snapshot — it only\n * reads or initialises the cache. This guarantees the reference-equality\n * contract required by `useSyncExternalStore`.\n */\nexport function getSnapshot(playback: Playback): PlaybackSnapshot {\n const cached = snapshotCache.get(playback);\n if (cached) return cached;\n\n const snap = computeSnapshot(playback);\n snapshotCache.set(playback, snap);\n return snap;\n}\n\n/**\n * Subscribe to playback state changes, calling `callback` with a fresh\n * snapshot whenever the state updates.\n *\n * Returns an unsubscribe function. Works as the `subscribe` parameter for\n * React's `useSyncExternalStore`.\n *\n * ```ts\n * // React example:\n * import { useCallback } from \"react\";\n * const subscribe = useCallback(\n * (cb: () => void) => subscribeSnapshot(playback, cb),\n * [playback],\n * );\n * const snap = useCallback(\n * () => getSnapshot(playback),\n * [playback],\n * );\n * const snapshot = useSyncExternalStore(subscribe, snap, snap);\n * ```\n */\nexport function subscribeSnapshot(playback: Playback, callback: () => void): () => void {\n const count = (subscriberCount.get(playback) ?? 0) + 1;\n subscriberCount.set(playback, count);\n\n // Eagerly compute the initial snapshot so getSnapshot() has a\n // stable reference before the first event fires.\n snapshotCache.set(playback, computeSnapshot(playback));\n\n const notify = () => {\n // Pre-compute and cache the snapshot BEFORE notifying the\n // subscriber. This ensures getSnapshot() returns the same\n // reference during React's render and post-commit check.\n snapshotCache.set(playback, computeSnapshot(playback));\n callback();\n };\n\n const unsubs: Array<() => void> = [];\n unsubs.push(playback.on(\"statechange\", notify));\n unsubs.push(playback.on(\"timeupdate\", notify));\n unsubs.push(playback.on(\"seek\", notify));\n unsubs.push(playback.on(\"ended\", notify));\n\n return () => {\n for (const unsub of unsubs) unsub();\n const c = (subscriberCount.get(playback) ?? 1) - 1;\n if (c <= 0) {\n subscriberCount.delete(playback);\n } else {\n subscriberCount.set(playback, c);\n }\n };\n}\n\n/**\n * Call `callback` on every animation frame with the current playback snapshot.\n * Useful for smooth UI animations (waveform cursors, progress bars, etc.).\n *\n * Returns a `stop` function that cancels the loop.\n */\nexport function onFrame(\n playback: Playback,\n callback: (snapshot: PlaybackSnapshot) => void,\n): () => void {\n let rafId: number | null = null;\n\n function tick() {\n const snap = computeSnapshot(playback);\n snapshotCache.set(playback, snap);\n callback(snap);\n rafId = requestAnimationFrame(tick);\n }\n\n rafId = requestAnimationFrame(tick);\n\n return () => {\n if (rafId !== null) {\n cancelAnimationFrame(rafId);\n rafId = null;\n }\n };\n}\n\n/**\n * Return a `Promise` that resolves when the playback reaches the `\"stopped\"`\n * state via the `ended` event (natural end, not manual stop).\n */\nexport function whenEnded(playback: Playback): Promise<void> {\n return new Promise<void>((resolve) => {\n const unsub = playback.on(\"ended\", () => {\n unsub();\n resolve();\n });\n });\n}\n\n/**\n * Return a `Promise` that resolves when the playback position reaches or\n * exceeds `position` seconds.\n */\nexport function whenPosition(playback: Playback, position: number): Promise<void> {\n if (playback.getCurrentTime() >= position) {\n return Promise.resolve();\n }\n return new Promise<void>((resolve) => {\n const unsub = playback.on(\"timeupdate\", ({ position: current }) => {\n if (current >= position) {\n unsub();\n resolve();\n }\n });\n });\n}\n"]}
@@ -0,0 +1,148 @@
1
+ 'use strict';
2
+
3
+ var chunkBRS7LZVH_cjs = require('./chunk-BRS7LZVH.cjs');
4
+ var chunkF6WXD3XW_cjs = require('./chunk-F6WXD3XW.cjs');
5
+ var chunkOZN5X4N6_cjs = require('./chunk-OZN5X4N6.cjs');
6
+ var chunk6UTN73HG_cjs = require('./chunk-6UTN73HG.cjs');
7
+ var chunk3VTU5OX5_cjs = require('./chunk-3VTU5OX5.cjs');
8
+ var chunkVY4UMZMJ_cjs = require('./chunk-VY4UMZMJ.cjs');
9
+ var chunkQGZGERGK_cjs = require('./chunk-QGZGERGK.cjs');
10
+ var chunkVOSIA3GF_cjs = require('./chunk-VOSIA3GF.cjs');
11
+ var chunkOIY6I4TU_cjs = require('./chunk-OIY6I4TU.cjs');
12
+
13
+ // src/player.ts
14
+ var WaaPlayer = class {
15
+ constructor(ctxOrOptions) {
16
+ if (ctxOrOptions && typeof ctxOrOptions.createGain === "function") {
17
+ this.ctx = ctxOrOptions;
18
+ this._ownsContext = false;
19
+ } else {
20
+ this.ctx = chunk6UTN73HG_cjs.createContext(ctxOrOptions);
21
+ this._ownsContext = true;
22
+ }
23
+ }
24
+ // --- Context ---
25
+ resume() {
26
+ return chunk6UTN73HG_cjs.resumeContext(this.ctx);
27
+ }
28
+ ensureRunning() {
29
+ return chunk6UTN73HG_cjs.ensureRunning(this.ctx);
30
+ }
31
+ now() {
32
+ return chunk6UTN73HG_cjs.now(this.ctx);
33
+ }
34
+ // --- Buffer ---
35
+ load(url, options) {
36
+ return chunk3VTU5OX5_cjs.loadBuffer(this.ctx, url, options);
37
+ }
38
+ loadFromBlob(blob) {
39
+ return chunk3VTU5OX5_cjs.loadBufferFromBlob(this.ctx, blob);
40
+ }
41
+ loadAll(map) {
42
+ return chunk3VTU5OX5_cjs.loadBuffers(this.ctx, map);
43
+ }
44
+ getBufferInfo(buffer) {
45
+ return chunk3VTU5OX5_cjs.getBufferInfo(buffer);
46
+ }
47
+ // --- Play ---
48
+ play(buffer, options) {
49
+ return chunkVY4UMZMJ_cjs.play(this.ctx, buffer, options);
50
+ }
51
+ // --- Nodes ---
52
+ createGain(initialValue) {
53
+ return chunkQGZGERGK_cjs.createGain(this.ctx, initialValue);
54
+ }
55
+ createAnalyser(options) {
56
+ return chunkQGZGERGK_cjs.createAnalyser(this.ctx, options);
57
+ }
58
+ createFilter(options) {
59
+ return chunkQGZGERGK_cjs.createFilter(this.ctx, options);
60
+ }
61
+ createPanner(pan) {
62
+ return chunkQGZGERGK_cjs.createPanner(this.ctx, pan);
63
+ }
64
+ createCompressor(options) {
65
+ return chunkQGZGERGK_cjs.createCompressor(this.ctx, options);
66
+ }
67
+ rampGain(gain, target, duration) {
68
+ chunkQGZGERGK_cjs.rampGain(gain, target, duration);
69
+ }
70
+ getFrequencyData(analyser) {
71
+ return chunkQGZGERGK_cjs.getFrequencyData(analyser);
72
+ }
73
+ getFrequencyDataByte(analyser) {
74
+ return chunkQGZGERGK_cjs.getFrequencyDataByte(analyser);
75
+ }
76
+ chain(...nodes) {
77
+ chunkQGZGERGK_cjs.chain(...nodes);
78
+ }
79
+ disconnectChain(...nodes) {
80
+ chunkQGZGERGK_cjs.disconnectChain(...nodes);
81
+ }
82
+ // --- Waveform ---
83
+ extractPeaks(buffer, options) {
84
+ return chunkVOSIA3GF_cjs.extractPeaks(buffer, options);
85
+ }
86
+ extractPeakPairs(buffer, options) {
87
+ return chunkVOSIA3GF_cjs.extractPeakPairs(buffer, options);
88
+ }
89
+ extractRMS(buffer, options) {
90
+ return chunkVOSIA3GF_cjs.extractRMS(buffer, options);
91
+ }
92
+ // --- Fade ---
93
+ fadeIn(gain, target, options) {
94
+ chunkOIY6I4TU_cjs.fadeIn(gain, target, options);
95
+ }
96
+ fadeOut(gain, options) {
97
+ chunkOIY6I4TU_cjs.fadeOut(gain, options);
98
+ }
99
+ crossfade(gainA, gainB, options) {
100
+ chunkOIY6I4TU_cjs.crossfade(gainA, gainB, options);
101
+ }
102
+ autoFade(playback, gain, options) {
103
+ return chunkOIY6I4TU_cjs.autoFade(playback, gain, options);
104
+ }
105
+ // --- Scheduler ---
106
+ createScheduler(options) {
107
+ return chunkBRS7LZVH_cjs.createScheduler(this.ctx, options);
108
+ }
109
+ createClock(options) {
110
+ return chunkBRS7LZVH_cjs.createClock(this.ctx, options);
111
+ }
112
+ // --- Synth ---
113
+ createSineBuffer(frequency, duration) {
114
+ return chunkF6WXD3XW_cjs.createSineBuffer(this.ctx, frequency, duration);
115
+ }
116
+ createNoiseBuffer(duration) {
117
+ return chunkF6WXD3XW_cjs.createNoiseBuffer(this.ctx, duration);
118
+ }
119
+ createClickBuffer(frequency, duration) {
120
+ return chunkF6WXD3XW_cjs.createClickBuffer(this.ctx, frequency, duration);
121
+ }
122
+ // --- Adapters ---
123
+ getSnapshot(playback) {
124
+ return chunkOZN5X4N6_cjs.getSnapshot(playback);
125
+ }
126
+ subscribeSnapshot(playback, callback) {
127
+ return chunkOZN5X4N6_cjs.subscribeSnapshot(playback, callback);
128
+ }
129
+ onFrame(playback, callback) {
130
+ return chunkOZN5X4N6_cjs.onFrame(playback, callback);
131
+ }
132
+ whenEnded(playback) {
133
+ return chunkOZN5X4N6_cjs.whenEnded(playback);
134
+ }
135
+ whenPosition(playback, position) {
136
+ return chunkOZN5X4N6_cjs.whenPosition(playback, position);
137
+ }
138
+ // --- Lifecycle ---
139
+ dispose() {
140
+ if (this._ownsContext) {
141
+ this.ctx.close();
142
+ }
143
+ }
144
+ };
145
+
146
+ exports.WaaPlayer = WaaPlayer;
147
+ //# sourceMappingURL=chunk-KVKW7W66.cjs.map
148
+ //# sourceMappingURL=chunk-KVKW7W66.cjs.map