waa-play 0.1.1 → 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 (122) hide show
  1. package/README.md +40 -123
  2. package/dist/adapters.cjs +6 -6
  3. package/dist/adapters.d.cts +15 -3
  4. package/dist/adapters.d.ts +15 -3
  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-TULV7V5M.cjs → chunk-G37HMZEX.cjs} +1075 -982
  25. package/dist/chunk-G37HMZEX.cjs.map +1 -0
  26. package/dist/{chunk-V2QX5K42.js → chunk-GDBOHOGF.js} +1074 -982
  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-RWJ4EWJT.js → chunk-HYRDCTBO.js} +152 -116
  33. package/dist/chunk-HYRDCTBO.js.map +1 -0
  34. package/dist/chunk-JIHPQAEA.js +90 -0
  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-OZN5X4N6.cjs +96 -0
  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-QFJQU7TQ.js +146 -0
  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-PZE6HTZR.cjs → chunk-VY4UMZMJ.cjs} +154 -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-M2U4LE3F.js.map → engine-7DCOERRN.js.map} +1 -1
  60. package/dist/engine-ALWPAIX6.cjs +17 -0
  61. package/dist/{engine-5JK2FCNL.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 +47 -42
  67. package/dist/index.d.cts +7 -6
  68. package/dist/index.d.ts +7 -6
  69. package/dist/index.js +10 -9
  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 +22 -0
  77. package/dist/player.cjs.map +1 -0
  78. package/dist/player.d.cts +64 -0
  79. package/dist/player.d.ts +64 -0
  80. package/dist/player.js +13 -0
  81. package/dist/player.js.map +1 -0
  82. package/dist/scheduler.cjs +3 -3
  83. package/dist/scheduler.d.cts +1 -1
  84. package/dist/scheduler.d.ts +1 -1
  85. package/dist/scheduler.js +1 -1
  86. package/dist/stretcher.cjs +3 -3
  87. package/dist/stretcher.d.cts +5 -3
  88. package/dist/stretcher.d.ts +5 -3
  89. package/dist/stretcher.js +2 -2
  90. package/dist/synth.cjs +4 -4
  91. package/dist/synth.js +1 -1
  92. package/dist/{types-DUrbEbPl.d.cts → types-BYC6m7Q0.d.cts} +6 -6
  93. package/dist/{types-DUrbEbPl.d.ts → types-BYC6m7Q0.d.ts} +6 -6
  94. package/dist/waveform.cjs +4 -4
  95. package/dist/waveform.d.cts +1 -1
  96. package/dist/waveform.d.ts +1 -1
  97. package/dist/waveform.js +1 -1
  98. package/package.json +19 -7
  99. package/dist/chunk-2DL7CAEP.js.map +0 -1
  100. package/dist/chunk-4LNVRSTM.cjs.map +0 -1
  101. package/dist/chunk-5J7S6QV3.cjs.map +0 -1
  102. package/dist/chunk-AGP2IRC6.js +0 -63
  103. package/dist/chunk-AGP2IRC6.js.map +0 -1
  104. package/dist/chunk-C2ASIYN5.js.map +0 -1
  105. package/dist/chunk-CJJC6ASU.js.map +0 -1
  106. package/dist/chunk-CPAT75WD.cjs.map +0 -1
  107. package/dist/chunk-CRODJ4KS.js.map +0 -1
  108. package/dist/chunk-D5CD5KQZ.cjs.map +0 -1
  109. package/dist/chunk-GYH2JSCY.js.map +0 -1
  110. package/dist/chunk-HTGOHC73.cjs +0 -69
  111. package/dist/chunk-HTGOHC73.cjs.map +0 -1
  112. package/dist/chunk-LETS7FKB.js.map +0 -1
  113. package/dist/chunk-M5PDY5EZ.cjs.map +0 -1
  114. package/dist/chunk-PZE6HTZR.cjs.map +0 -1
  115. package/dist/chunk-QFFQQMU4.cjs.map +0 -1
  116. package/dist/chunk-QWNV2BZ5.cjs.map +0 -1
  117. package/dist/chunk-RWJ4EWJT.js.map +0 -1
  118. package/dist/chunk-T74FBKTY.js.map +0 -1
  119. package/dist/chunk-TULV7V5M.cjs.map +0 -1
  120. package/dist/chunk-V2QX5K42.js.map +0 -1
  121. package/dist/engine-5JK2FCNL.cjs +0 -13
  122. package/dist/engine-M2U4LE3F.js +0 -4
@@ -1,6 +1,60 @@
1
1
  'use strict';
2
2
 
3
- var chunk5J7S6QV3_cjs = require('./chunk-5J7S6QV3.cjs');
3
+ var chunkHIF3UAF3_cjs = require('./chunk-HIF3UAF3.cjs');
4
+
5
+ // src/playback-position.ts
6
+ function calcLoopPosition(elapsed, loopStart, loopEnd) {
7
+ const loopDur = loopEnd - loopStart;
8
+ if (loopDur <= 0) return null;
9
+ const offset = elapsed - loopStart;
10
+ return (offset % loopDur + loopDur) % loopDur + loopStart;
11
+ }
12
+ function calcPlaybackPosition(state, elapsed, duration, pausedAt, isLooping, loopStart, loopEnd) {
13
+ if (state === "paused") return pausedAt;
14
+ if (state === "stopped") return 0;
15
+ if (isLooping) {
16
+ const looped = calcLoopPosition(elapsed, loopStart ?? 0, loopEnd ?? duration);
17
+ if (looped !== null) return looped;
18
+ }
19
+ return Math.min(Math.max(elapsed, 0), duration);
20
+ }
21
+
22
+ // src/playback-state.ts
23
+ function createPlaybackStateManager(opts) {
24
+ let state = opts.initialState;
25
+ let timerId = null;
26
+ let disposed = false;
27
+ function getState() {
28
+ return state;
29
+ }
30
+ function setState(next) {
31
+ if (state === next) return false;
32
+ state = next;
33
+ opts.onStateChange(next);
34
+ return true;
35
+ }
36
+ function startTimer() {
37
+ if (timerId !== null) return;
38
+ timerId = setInterval(() => {
39
+ if (state !== "playing" || disposed) return;
40
+ opts.onTimerTick();
41
+ }, opts.timerInterval);
42
+ }
43
+ function stopTimer() {
44
+ if (timerId !== null) {
45
+ clearInterval(timerId);
46
+ timerId = null;
47
+ }
48
+ }
49
+ function isDisposed() {
50
+ return disposed;
51
+ }
52
+ function markDisposed() {
53
+ disposed = true;
54
+ stopTimer();
55
+ }
56
+ return { getState, setState, startTimer, stopTimer, isDisposed, markDisposed };
57
+ }
4
58
 
5
59
  // src/play.ts
6
60
  function play(ctx, buffer, options) {
@@ -18,16 +72,24 @@ function play(ctx, buffer, options) {
18
72
  destination = ctx.destination,
19
73
  timeupdateInterval = 50
20
74
  } = options ?? {};
21
- const emitter = chunk5J7S6QV3_cjs.createEmitter();
75
+ const emitter = chunkHIF3UAF3_cjs.createEmitter();
22
76
  const duration = buffer.duration;
23
- let state = "stopped";
24
77
  let sourceNode = null;
25
78
  let startedAt = 0;
26
79
  let pausedAt = initialOffset;
27
- let currentRate = initialRate;
80
+ let currentRate = initialRate > 0 ? initialRate : 1;
28
81
  let isLooping = loop;
29
- let timerId = null;
30
- let disposed = false;
82
+ const sm = createPlaybackStateManager({
83
+ initialState: "stopped",
84
+ onStateChange: (next) => emitter.emit("statechange", { state: next }),
85
+ onTimerTick: () => {
86
+ emitter.emit("timeupdate", {
87
+ position: getCurrentTime(),
88
+ duration
89
+ });
90
+ },
91
+ timerInterval: timeupdateInterval
92
+ });
31
93
  function createSource() {
32
94
  const src = ctx.createBufferSource();
33
95
  src.buffer = buffer;
@@ -64,90 +126,63 @@ function play(ctx, buffer, options) {
64
126
  }
65
127
  }
66
128
  function handleEnded() {
67
- if (state !== "playing") return;
129
+ if (sm.getState() !== "playing") return;
68
130
  if (isLooping) {
69
131
  emitter.emit("loop", void 0);
70
132
  return;
71
133
  }
72
- setState("stopped");
134
+ sm.setState("stopped");
73
135
  pausedAt = 0;
74
- stopTimer();
136
+ sm.stopTimer();
75
137
  emitter.emit("ended", void 0);
76
138
  }
77
- function setState(next) {
78
- if (state === next) return;
79
- state = next;
80
- emitter.emit("statechange", { state: next });
81
- }
82
- function startTimer() {
83
- if (timerId !== null) return;
84
- timerId = setInterval(() => {
85
- if (state !== "playing") return;
86
- emitter.emit("timeupdate", {
87
- position: getCurrentTime(),
88
- duration
89
- });
90
- }, timeupdateInterval);
91
- }
92
- function stopTimer() {
93
- if (timerId !== null) {
94
- clearInterval(timerId);
95
- timerId = null;
96
- }
97
- }
98
139
  function getCurrentTime() {
99
- if (state === "playing") {
100
- const elapsed = (ctx.currentTime - startedAt) * currentRate;
101
- if (isLooping) {
102
- const loopDur = (loopEnd ?? duration) - (loopStart ?? 0);
103
- return (elapsed - (loopStart ?? 0)) % loopDur + (loopStart ?? 0);
104
- }
105
- return Math.min(elapsed, duration);
106
- }
107
- if (state === "paused") return pausedAt;
108
- return 0;
140
+ const state = sm.getState();
141
+ const elapsed = state === "playing" ? (ctx.currentTime - startedAt) * currentRate : 0;
142
+ return calcPlaybackPosition(state, elapsed, duration, pausedAt, isLooping, loopStart, loopEnd);
109
143
  }
110
144
  function pause() {
111
- if (state !== "playing" || disposed) return;
145
+ if (sm.getState() !== "playing" || sm.isDisposed()) return;
112
146
  pausedAt = getCurrentTime();
113
147
  stopSource();
114
- stopTimer();
115
- setState("paused");
148
+ sm.stopTimer();
149
+ sm.setState("paused");
116
150
  emitter.emit("pause", void 0);
117
151
  }
118
152
  function resume() {
119
- if (state !== "paused" || disposed) return;
153
+ if (sm.getState() !== "paused" || sm.isDisposed()) return;
120
154
  startSource(pausedAt);
121
- setState("playing");
122
- startTimer();
155
+ sm.setState("playing");
156
+ sm.startTimer();
123
157
  emitter.emit("resume", void 0);
124
158
  }
125
159
  function togglePlayPause() {
126
- if (state === "playing") pause();
127
- else if (state === "paused") resume();
160
+ if (sm.getState() === "playing") pause();
161
+ else if (sm.getState() === "paused") resume();
128
162
  }
129
163
  function seek(position) {
130
- if (disposed) return;
164
+ if (sm.isDisposed()) return;
131
165
  const clamped = Math.max(0, Math.min(position, duration));
132
- const wasPlaying = state === "playing";
166
+ const wasPlaying = sm.getState() === "playing";
133
167
  stopSource();
134
- stopTimer();
168
+ sm.stopTimer();
135
169
  pausedAt = clamped;
136
170
  if (wasPlaying) {
137
171
  startSource(clamped);
138
- startTimer();
172
+ sm.startTimer();
139
173
  }
140
174
  emitter.emit("seek", { position: clamped });
141
175
  }
142
176
  function stop() {
143
- if (state === "stopped" || disposed) return;
177
+ if (sm.getState() === "stopped" || sm.isDisposed()) return;
144
178
  stopSource();
145
- stopTimer();
179
+ sm.stopTimer();
146
180
  pausedAt = 0;
147
- setState("stopped");
181
+ sm.setState("stopped");
148
182
  emitter.emit("stop", void 0);
149
183
  }
150
184
  function setPlaybackRate(rate) {
185
+ if (rate <= 0) return;
151
186
  const position = getCurrentTime();
152
187
  currentRate = rate;
153
188
  if (sourceNode) {
@@ -162,18 +197,17 @@ function play(ctx, buffer, options) {
162
197
  }
163
198
  }
164
199
  function dispose() {
165
- if (disposed) return;
166
- disposed = true;
200
+ if (sm.isDisposed()) return;
201
+ sm.markDisposed();
167
202
  stopSource();
168
- stopTimer();
169
203
  emitter.clear();
170
204
  }
171
205
  startSource(initialOffset);
172
- setState("playing");
173
- startTimer();
206
+ sm.setState("playing");
207
+ sm.startTimer();
174
208
  emitter.emit("play", void 0);
175
209
  return {
176
- getState: () => state,
210
+ getState: () => sm.getState(),
177
211
  getCurrentTime,
178
212
  getDuration: () => duration,
179
213
  getProgress: () => duration > 0 ? getCurrentTime() / duration : 0,
@@ -192,81 +226,84 @@ function play(ctx, buffer, options) {
192
226
  function createStretchedPlayback(ctx, buffer, options) {
193
227
  const {
194
228
  offset: initialOffset = 0,
229
+ loop = false,
195
230
  playbackRate: initialRate = 1,
196
231
  through = [],
197
232
  destination = ctx.destination,
198
233
  timeupdateInterval = 50
199
234
  } = options;
200
- const emitter = chunk5J7S6QV3_cjs.createEmitter();
235
+ const emitter = chunkHIF3UAF3_cjs.createEmitter();
201
236
  const duration = buffer.duration;
202
- let state = "playing";
203
237
  let engineInstance = null;
204
- let timerId = null;
205
- let disposed = false;
206
- let currentRate = initialRate;
238
+ let currentRate = initialRate > 0 ? initialRate : 1;
239
+ let isLooping = loop;
207
240
  let pendingSeek = null;
241
+ const sm = createPlaybackStateManager({
242
+ initialState: "playing",
243
+ onStateChange: (next) => emitter.emit("statechange", { state: next }),
244
+ onTimerTick: () => {
245
+ emitter.emit("timeupdate", {
246
+ position: getCurrentTime(),
247
+ duration
248
+ });
249
+ },
250
+ timerInterval: timeupdateInterval
251
+ });
208
252
  emitter.emit("statechange", { state: "playing" });
209
253
  emitter.emit("play", void 0);
210
- import('./engine-5JK2FCNL.cjs').then(({ createStretcherEngine }) => {
211
- if (disposed) return;
254
+ import('./engine-ALWPAIX6.cjs').then(({ createStretcherEngine }) => {
255
+ if (sm.isDisposed()) return;
212
256
  engineInstance = createStretcherEngine(ctx, buffer, {
213
257
  tempo: currentRate,
214
258
  offset: initialOffset,
259
+ loop: isLooping,
215
260
  through,
216
261
  destination,
217
262
  timeupdateInterval
218
263
  });
219
264
  engineInstance.on("buffering", (data) => {
220
- if (disposed) return;
265
+ if (sm.isDisposed()) return;
221
266
  emitter.emit("buffering", data);
222
267
  });
223
268
  engineInstance.on("buffered", (data) => {
224
- if (disposed) return;
269
+ if (sm.isDisposed()) return;
225
270
  emitter.emit("buffered", data);
226
271
  });
272
+ engineInstance.on("loop", () => {
273
+ if (sm.isDisposed()) return;
274
+ emitter.emit("loop", void 0);
275
+ });
227
276
  engineInstance.on("ended", () => {
228
- if (disposed) return;
229
- state = "stopped";
230
- stopTimer();
231
- emitter.emit("statechange", { state: "stopped" });
277
+ if (sm.isDisposed()) return;
278
+ if (sm.getState() === "stopped") return;
279
+ sm.stopTimer();
280
+ sm.setState("stopped");
232
281
  emitter.emit("ended", void 0);
233
282
  });
234
283
  engineInstance.on("error", (data) => {
235
- if (disposed) return;
284
+ if (sm.isDisposed()) return;
236
285
  if (data.fatal) {
237
- state = "stopped";
238
- emitter.emit("statechange", { state: "stopped" });
286
+ sm.setState("stopped");
239
287
  emitter.emit("ended", void 0);
240
288
  }
241
289
  });
242
290
  engineInstance.start();
243
- startTimer();
291
+ sm.startTimer();
244
292
  if (pendingSeek !== null) {
245
293
  engineInstance.seek(pendingSeek);
246
294
  pendingSeek = null;
247
295
  }
248
- if (state === "paused") {
296
+ if (sm.getState() === "paused") {
249
297
  engineInstance.pause();
250
- } else if (state === "stopped") {
298
+ } else if (sm.getState() === "stopped") {
251
299
  engineInstance.stop();
252
300
  }
301
+ }).catch(() => {
302
+ if (sm.isDisposed()) return;
303
+ sm.stopTimer();
304
+ sm.setState("stopped");
305
+ emitter.emit("ended", void 0);
253
306
  });
254
- function startTimer() {
255
- if (timerId !== null) return;
256
- timerId = setInterval(() => {
257
- if (state !== "playing" || disposed) return;
258
- emitter.emit("timeupdate", {
259
- position: getCurrentTime(),
260
- duration
261
- });
262
- }, timeupdateInterval);
263
- }
264
- function stopTimer() {
265
- if (timerId !== null) {
266
- clearInterval(timerId);
267
- timerId = null;
268
- }
269
- }
270
307
  function getCurrentTime() {
271
308
  if (pendingSeek !== null) {
272
309
  return pendingSeek;
@@ -277,27 +314,25 @@ function createStretchedPlayback(ctx, buffer, options) {
277
314
  return initialOffset;
278
315
  }
279
316
  function pause() {
280
- if (state !== "playing" || disposed) return;
281
- state = "paused";
317
+ if (sm.getState() !== "playing" || sm.isDisposed()) return;
282
318
  engineInstance?.pause();
283
- stopTimer();
284
- emitter.emit("statechange", { state: "paused" });
319
+ sm.stopTimer();
320
+ sm.setState("paused");
285
321
  emitter.emit("pause", void 0);
286
322
  }
287
323
  function resume() {
288
- if (state !== "paused" || disposed) return;
289
- state = "playing";
324
+ if (sm.getState() !== "paused" || sm.isDisposed()) return;
290
325
  engineInstance?.resume();
291
- startTimer();
292
- emitter.emit("statechange", { state: "playing" });
326
+ sm.startTimer();
327
+ sm.setState("playing");
293
328
  emitter.emit("resume", void 0);
294
329
  }
295
330
  function togglePlayPause() {
296
- if (state === "playing") pause();
297
- else if (state === "paused") resume();
331
+ if (sm.getState() === "playing") pause();
332
+ else if (sm.getState() === "paused") resume();
298
333
  }
299
334
  function seek(position) {
300
- if (disposed) return;
335
+ if (sm.isDisposed()) return;
301
336
  const clamped = Math.max(0, Math.min(position, duration));
302
337
  if (engineInstance) {
303
338
  engineInstance.seek(clamped);
@@ -307,25 +342,26 @@ function createStretchedPlayback(ctx, buffer, options) {
307
342
  emitter.emit("seek", { position: clamped });
308
343
  }
309
344
  function stop() {
310
- if (state === "stopped" || disposed) return;
311
- state = "stopped";
345
+ if (sm.getState() === "stopped" || sm.isDisposed()) return;
312
346
  engineInstance?.stop();
313
- stopTimer();
314
- emitter.emit("statechange", { state: "stopped" });
347
+ sm.stopTimer();
348
+ sm.setState("stopped");
315
349
  emitter.emit("stop", void 0);
316
350
  }
317
351
  function setPlaybackRate(rate) {
352
+ if (rate <= 0) return;
318
353
  currentRate = rate;
319
354
  if (engineInstance) {
320
355
  engineInstance.setTempo(rate);
321
356
  }
322
357
  }
323
- function setLoop(_value) {
358
+ function setLoop(value) {
359
+ isLooping = value;
360
+ engineInstance?.setLoop(value);
324
361
  }
325
362
  function dispose() {
326
- if (disposed) return;
327
- disposed = true;
328
- stopTimer();
363
+ if (sm.isDisposed()) return;
364
+ sm.markDisposed();
329
365
  engineInstance?.dispose();
330
366
  emitter.clear();
331
367
  }
@@ -334,7 +370,7 @@ function createStretchedPlayback(ctx, buffer, options) {
334
370
  return engineInstance.getSnapshot();
335
371
  }
336
372
  const playback = {
337
- getState: () => state,
373
+ getState: () => sm.getState(),
338
374
  getCurrentTime,
339
375
  getDuration: () => duration,
340
376
  getProgress: () => duration > 0 ? getCurrentTime() / duration : 0,
@@ -354,5 +390,5 @@ function createStretchedPlayback(ctx, buffer, options) {
354
390
  }
355
391
 
356
392
  exports.play = play;
357
- //# sourceMappingURL=chunk-PZE6HTZR.cjs.map
358
- //# sourceMappingURL=chunk-PZE6HTZR.cjs.map
393
+ //# sourceMappingURL=chunk-VY4UMZMJ.cjs.map
394
+ //# sourceMappingURL=chunk-VY4UMZMJ.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/playback-position.ts","../src/playback-state.ts","../src/play.ts"],"names":["createEmitter"],"mappings":"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","file":"chunk-VY4UMZMJ.cjs","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"]}
@@ -29,5 +29,5 @@ function createClickBuffer(ctx, frequency, duration) {
29
29
  }
30
30
 
31
31
  export { createClickBuffer, createNoiseBuffer, createSineBuffer };
32
- //# sourceMappingURL=chunk-LETS7FKB.js.map
33
- //# sourceMappingURL=chunk-LETS7FKB.js.map
32
+ //# sourceMappingURL=chunk-YFK7ETCF.js.map
33
+ //# sourceMappingURL=chunk-YFK7ETCF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/synth.ts"],"names":[],"mappings":";AAQO,SAAS,gBAAA,CACd,GAAA,EACA,SAAA,EACA,QAAA,EACa;AACb,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,aAAa,QAAQ,CAAA;AAClD,EAAA,MAAM,SAAS,GAAA,CAAI,YAAA,CAAa,CAAA,EAAG,MAAA,EAAQ,IAAI,UAAU,CAAA;AACzD,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,cAAA,CAAe,CAAC,CAAA;AAEpC,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,MAAA,EAAQ,CAAA,EAAA,EAAK;AAC/B,IAAA,IAAA,CAAK,CAAC,CAAA,GAAI,IAAA,CAAK,GAAA,CAAK,CAAA,GAAI,KAAK,EAAA,GAAK,SAAA,GAAY,CAAA,GAAK,GAAA,CAAI,UAAU,CAAA;AAAA,EACnE;AAEA,EAAA,OAAO,MAAA;AACT;AAKO,SAAS,iBAAA,CAAkB,KAAmB,QAAA,EAA+B;AAClF,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,aAAa,QAAQ,CAAA;AAClD,EAAA,MAAM,SAAS,GAAA,CAAI,YAAA,CAAa,CAAA,EAAG,MAAA,EAAQ,IAAI,UAAU,CAAA;AACzD,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,cAAA,CAAe,CAAC,CAAA;AAEpC,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,MAAA,EAAQ,CAAA,EAAA,EAAK;AAC/B,IAAA,IAAA,CAAK,CAAC,CAAA,GAAI,IAAA,CAAK,MAAA,KAAW,CAAA,GAAI,CAAA;AAAA,EAChC;AAEA,EAAA,OAAO,MAAA;AACT;AAKO,SAAS,iBAAA,CACd,GAAA,EACA,SAAA,EACA,QAAA,EACa;AACb,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,aAAa,QAAQ,CAAA;AAClD,EAAA,MAAM,SAAS,GAAA,CAAI,YAAA,CAAa,CAAA,EAAG,MAAA,EAAQ,IAAI,UAAU,CAAA;AACzD,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,cAAA,CAAe,CAAC,CAAA;AAEpC,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,MAAA,EAAQ,CAAA,EAAA,EAAK;AAE/B,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,GAAA,CAAK,EAAA,GAAK,IAAK,MAAM,CAAA;AAC3C,IAAA,IAAA,CAAK,CAAC,CAAA,GAAI,QAAA,GAAW,IAAA,CAAK,GAAA,CAAK,CAAA,GAAI,IAAA,CAAK,EAAA,GAAK,SAAA,GAAY,CAAA,GAAK,GAAA,CAAI,UAAU,CAAA;AAAA,EAC9E;AAEA,EAAA,OAAO,MAAA;AACT","file":"chunk-YFK7ETCF.js","sourcesContent":["// ---------------------------------------------------------------------------\n// M9: Buffer synthesis\n// ---------------------------------------------------------------------------\n\n/**\n * Create an `AudioBuffer` containing a sine wave.\n * Useful for test tones and debugging.\n */\nexport function createSineBuffer(\n ctx: AudioContext,\n frequency: number,\n duration: number,\n): AudioBuffer {\n const length = Math.ceil(ctx.sampleRate * duration);\n const buffer = ctx.createBuffer(1, length, ctx.sampleRate);\n const data = buffer.getChannelData(0);\n\n for (let i = 0; i < length; i++) {\n data[i] = Math.sin((2 * Math.PI * frequency * i) / ctx.sampleRate);\n }\n\n return buffer;\n}\n\n/**\n * Create an `AudioBuffer` containing white noise.\n */\nexport function createNoiseBuffer(ctx: AudioContext, duration: number): AudioBuffer {\n const length = Math.ceil(ctx.sampleRate * duration);\n const buffer = ctx.createBuffer(1, length, ctx.sampleRate);\n const data = buffer.getChannelData(0);\n\n for (let i = 0; i < length; i++) {\n data[i] = Math.random() * 2 - 1;\n }\n\n return buffer;\n}\n\n/**\n * Create an `AudioBuffer` containing a short click/impulse.\n */\nexport function createClickBuffer(\n ctx: AudioContext,\n frequency: number,\n duration: number,\n): AudioBuffer {\n const length = Math.ceil(ctx.sampleRate * duration);\n const buffer = ctx.createBuffer(1, length, ctx.sampleRate);\n const data = buffer.getChannelData(0);\n\n for (let i = 0; i < length; i++) {\n // Exponential decay envelope.\n const envelope = Math.exp((-5 * i) / length);\n data[i] = envelope * Math.sin((2 * Math.PI * frequency * i) / ctx.sampleRate);\n }\n\n return buffer;\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { a as CreateContextOptions } from './types-DUrbEbPl.cjs';
1
+ import { a as CreateContextOptions } from './types-BYC6m7Q0.cjs';
2
2
 
3
3
  /**
4
4
  * Create an `AudioContext` with optional configuration.
package/dist/context.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as CreateContextOptions } from './types-DUrbEbPl.js';
1
+ import { a as CreateContextOptions } from './types-BYC6m7Q0.js';
2
2
 
3
3
  /**
4
4
  * Create an `AudioContext` with optional configuration.
package/dist/emitter.cjs CHANGED
@@ -1,12 +1,12 @@
1
1
  'use strict';
2
2
 
3
- var chunk5J7S6QV3_cjs = require('./chunk-5J7S6QV3.cjs');
3
+ var chunkHIF3UAF3_cjs = require('./chunk-HIF3UAF3.cjs');
4
4
 
5
5
 
6
6
 
7
7
  Object.defineProperty(exports, "createEmitter", {
8
8
  enumerable: true,
9
- get: function () { return chunk5J7S6QV3_cjs.createEmitter; }
9
+ get: function () { return chunkHIF3UAF3_cjs.createEmitter; }
10
10
  });
11
11
  //# sourceMappingURL=emitter.cjs.map
12
12
  //# sourceMappingURL=emitter.cjs.map
package/dist/emitter.js CHANGED
@@ -1,3 +1,3 @@
1
- export { createEmitter } from './chunk-GYH2JSCY.js';
1
+ export { createEmitter } from './chunk-FY273Z3I.js';
2
2
  //# sourceMappingURL=emitter.js.map
3
3
  //# sourceMappingURL=emitter.js.map
@@ -0,0 +1,4 @@
1
+ export { createStretcherEngine, trimOverlap } from './chunk-GDBOHOGF.js';
2
+ import './chunk-FY273Z3I.js';
3
+ //# sourceMappingURL=engine-7DCOERRN.js.map
4
+ //# sourceMappingURL=engine-7DCOERRN.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"engine-M2U4LE3F.js"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"engine-7DCOERRN.js"}
@@ -0,0 +1,17 @@
1
+ 'use strict';
2
+
3
+ var chunkG37HMZEX_cjs = require('./chunk-G37HMZEX.cjs');
4
+ require('./chunk-HIF3UAF3.cjs');
5
+
6
+
7
+
8
+ Object.defineProperty(exports, "createStretcherEngine", {
9
+ enumerable: true,
10
+ get: function () { return chunkG37HMZEX_cjs.createStretcherEngine; }
11
+ });
12
+ Object.defineProperty(exports, "trimOverlap", {
13
+ enumerable: true,
14
+ get: function () { return chunkG37HMZEX_cjs.trimOverlap; }
15
+ });
16
+ //# sourceMappingURL=engine-ALWPAIX6.cjs.map
17
+ //# sourceMappingURL=engine-ALWPAIX6.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"engine-5JK2FCNL.cjs"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"engine-ALWPAIX6.cjs"}
package/dist/fade.cjs CHANGED
@@ -1,24 +1,24 @@
1
1
  'use strict';
2
2
 
3
- var chunk4LNVRSTM_cjs = require('./chunk-4LNVRSTM.cjs');
3
+ var chunkOIY6I4TU_cjs = require('./chunk-OIY6I4TU.cjs');
4
4
 
5
5
 
6
6
 
7
7
  Object.defineProperty(exports, "autoFade", {
8
8
  enumerable: true,
9
- get: function () { return chunk4LNVRSTM_cjs.autoFade; }
9
+ get: function () { return chunkOIY6I4TU_cjs.autoFade; }
10
10
  });
11
11
  Object.defineProperty(exports, "crossfade", {
12
12
  enumerable: true,
13
- get: function () { return chunk4LNVRSTM_cjs.crossfade; }
13
+ get: function () { return chunkOIY6I4TU_cjs.crossfade; }
14
14
  });
15
15
  Object.defineProperty(exports, "fadeIn", {
16
16
  enumerable: true,
17
- get: function () { return chunk4LNVRSTM_cjs.fadeIn; }
17
+ get: function () { return chunkOIY6I4TU_cjs.fadeIn; }
18
18
  });
19
19
  Object.defineProperty(exports, "fadeOut", {
20
20
  enumerable: true,
21
- get: function () { return chunk4LNVRSTM_cjs.fadeOut; }
21
+ get: function () { return chunkOIY6I4TU_cjs.fadeOut; }
22
22
  });
23
23
  //# sourceMappingURL=fade.cjs.map
24
24
  //# sourceMappingURL=fade.cjs.map
package/dist/fade.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { e as Playback, A as AutoFadeOptions, b as CrossfadeOptions, c as FadeOptions } from './types-DUrbEbPl.cjs';
1
+ import { e as Playback, A as AutoFadeOptions, b as CrossfadeOptions, c as FadeOptions } from './types-BYC6m7Q0.cjs';
2
2
 
3
3
  /**
4
4
  * Fade a `GainNode` in from 0 to `target`.
package/dist/fade.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { e as Playback, A as AutoFadeOptions, b as CrossfadeOptions, c as FadeOptions } from './types-DUrbEbPl.js';
1
+ import { e as Playback, A as AutoFadeOptions, b as CrossfadeOptions, c as FadeOptions } from './types-BYC6m7Q0.js';
2
2
 
3
3
  /**
4
4
  * Fade a `GainNode` in from 0 to `target`.
package/dist/fade.js CHANGED
@@ -1,3 +1,3 @@
1
- export { autoFade, crossfade, fadeIn, fadeOut } from './chunk-C2ASIYN5.js';
1
+ export { autoFade, crossfade, fadeIn, fadeOut } from './chunk-FESPIMZM.js';
2
2
  //# sourceMappingURL=fade.js.map
3
3
  //# sourceMappingURL=fade.js.map