waa-play 0.1.0 → 0.2.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 (52) hide show
  1. package/README.md +60 -95
  2. package/dist/adapters.cjs +6 -6
  3. package/dist/adapters.d.cts +14 -2
  4. package/dist/adapters.d.ts +14 -2
  5. package/dist/adapters.js +1 -1
  6. package/dist/{chunk-V2QX5K42.js → chunk-2FFORBOP.js} +24 -4
  7. package/dist/chunk-2FFORBOP.js.map +1 -0
  8. package/dist/chunk-7S5KWTZ6.cjs +93 -0
  9. package/dist/chunk-7S5KWTZ6.cjs.map +1 -0
  10. package/dist/{chunk-PZE6HTZR.cjs → chunk-CTUCTTIE.cjs} +13 -4
  11. package/dist/chunk-CTUCTTIE.cjs.map +1 -0
  12. package/dist/chunk-IMNRPYBM.js +146 -0
  13. package/dist/chunk-IMNRPYBM.js.map +1 -0
  14. package/dist/{chunk-TULV7V5M.cjs → chunk-SIMLANWE.cjs} +24 -4
  15. package/dist/chunk-SIMLANWE.cjs.map +1 -0
  16. package/dist/chunk-VKT7YCWK.js +87 -0
  17. package/dist/chunk-VKT7YCWK.js.map +1 -0
  18. package/dist/{chunk-RWJ4EWJT.js → chunk-X4IFO7U7.js} +13 -4
  19. package/dist/chunk-X4IFO7U7.js.map +1 -0
  20. package/dist/chunk-XZBMBZA3.cjs +148 -0
  21. package/dist/chunk-XZBMBZA3.cjs.map +1 -0
  22. package/dist/engine-QUMYW73L.cjs +13 -0
  23. package/dist/{engine-5JK2FCNL.cjs.map → engine-QUMYW73L.cjs.map} +1 -1
  24. package/dist/engine-TYI7OX7O.js +4 -0
  25. package/dist/{engine-M2U4LE3F.js.map → engine-TYI7OX7O.js.map} +1 -1
  26. package/dist/index.cjs +13 -8
  27. package/dist/index.d.cts +1 -0
  28. package/dist/index.d.ts +1 -0
  29. package/dist/index.js +3 -2
  30. package/dist/play.cjs +2 -2
  31. package/dist/play.js +1 -1
  32. package/dist/player.cjs +22 -0
  33. package/dist/player.cjs.map +1 -0
  34. package/dist/player.d.cts +64 -0
  35. package/dist/player.d.ts +64 -0
  36. package/dist/player.js +13 -0
  37. package/dist/player.js.map +1 -0
  38. package/dist/stretcher.cjs +2 -2
  39. package/dist/stretcher.d.cts +2 -0
  40. package/dist/stretcher.d.ts +2 -0
  41. package/dist/stretcher.js +1 -1
  42. package/package.json +13 -4
  43. package/dist/chunk-AGP2IRC6.js +0 -63
  44. package/dist/chunk-AGP2IRC6.js.map +0 -1
  45. package/dist/chunk-HTGOHC73.cjs +0 -69
  46. package/dist/chunk-HTGOHC73.cjs.map +0 -1
  47. package/dist/chunk-PZE6HTZR.cjs.map +0 -1
  48. package/dist/chunk-RWJ4EWJT.js.map +0 -1
  49. package/dist/chunk-TULV7V5M.cjs.map +0 -1
  50. package/dist/chunk-V2QX5K42.js.map +0 -1
  51. package/dist/engine-5JK2FCNL.cjs +0 -13
  52. package/dist/engine-M2U4LE3F.js +0 -4
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/adapters.ts"],"names":[],"mappings":"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","file":"chunk-VKT7YCWK.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(\n playback: Playback,\n callback: () => void,\n): () => 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(\n playback: Playback,\n position: number,\n): Promise<void> {\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"]}
@@ -190,6 +190,7 @@ function play(ctx, buffer, options) {
190
190
  function createStretchedPlayback(ctx, buffer, options) {
191
191
  const {
192
192
  offset: initialOffset = 0,
193
+ loop = false,
193
194
  playbackRate: initialRate = 1,
194
195
  through = [],
195
196
  destination = ctx.destination,
@@ -202,14 +203,16 @@ function createStretchedPlayback(ctx, buffer, options) {
202
203
  let timerId = null;
203
204
  let disposed = false;
204
205
  let currentRate = initialRate;
206
+ let isLooping = loop;
205
207
  let pendingSeek = null;
206
208
  emitter.emit("statechange", { state: "playing" });
207
209
  emitter.emit("play", void 0);
208
- import('./engine-M2U4LE3F.js').then(({ createStretcherEngine }) => {
210
+ import('./engine-TYI7OX7O.js').then(({ createStretcherEngine }) => {
209
211
  if (disposed) return;
210
212
  engineInstance = createStretcherEngine(ctx, buffer, {
211
213
  tempo: currentRate,
212
214
  offset: initialOffset,
215
+ loop: isLooping,
213
216
  through,
214
217
  destination,
215
218
  timeupdateInterval
@@ -222,6 +225,10 @@ function createStretchedPlayback(ctx, buffer, options) {
222
225
  if (disposed) return;
223
226
  emitter.emit("buffered", data);
224
227
  });
228
+ engineInstance.on("loop", () => {
229
+ if (disposed) return;
230
+ emitter.emit("loop", void 0);
231
+ });
225
232
  engineInstance.on("ended", () => {
226
233
  if (disposed) return;
227
234
  state = "stopped";
@@ -318,7 +325,9 @@ function createStretchedPlayback(ctx, buffer, options) {
318
325
  engineInstance.setTempo(rate);
319
326
  }
320
327
  }
321
- function setLoop(_value) {
328
+ function setLoop(value) {
329
+ isLooping = value;
330
+ engineInstance?.setLoop(value);
322
331
  }
323
332
  function dispose() {
324
333
  if (disposed) return;
@@ -352,5 +361,5 @@ function createStretchedPlayback(ctx, buffer, options) {
352
361
  }
353
362
 
354
363
  export { play };
355
- //# sourceMappingURL=chunk-RWJ4EWJT.js.map
356
- //# sourceMappingURL=chunk-RWJ4EWJT.js.map
364
+ //# sourceMappingURL=chunk-X4IFO7U7.js.map
365
+ //# sourceMappingURL=chunk-X4IFO7U7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/play.ts"],"names":[],"mappings":";;;AA2BO,SAAS,IAAA,CACd,GAAA,EACA,MAAA,EACA,OAAA,EACU;AACV,EAAA,MAAM,EAAE,aAAA,GAAgB,IAAA,EAAK,GAAI,WAAW,EAAC;AAG7C,EAAA,IAAI,aAAA,EAAe;AACjB,IAAA,OAAO,uBAAA,CAAwB,GAAA,EAAK,MAAA,EAAQ,OAAA,IAAW,EAAE,CAAA;AAAA,EAC3D;AAEA,EAAA,MAAM;AAAA,IACJ,QAAQ,aAAA,GAAgB,CAAA;AAAA,IACxB,IAAA,GAAO,KAAA;AAAA,IACP,SAAA;AAAA,IACA,OAAA;AAAA,IACA,cAAc,WAAA,GAAc,CAAA;AAAA,IAC5B,UAAU,EAAC;AAAA,IACX,cAAc,GAAA,CAAI,WAAA;AAAA,IAClB,kBAAA,GAAqB;AAAA,GACvB,GAAI,WAAW,EAAC;AAEhB,EAAA,MAAM,UAAU,aAAA,EAAgC;AAChD,EAAA,MAAM,WAAW,MAAA,CAAO,QAAA;AAGxB,EAAA,IAAI,KAAA,GAAuB,SAAA;AAC3B,EAAA,IAAI,UAAA,GAA2C,IAAA;AAC/C,EAAA,IAAI,SAAA,GAAY,CAAA;AAChB,EAAA,IAAI,QAAA,GAAW,aAAA;AACf,EAAA,IAAI,WAAA,GAAc,WAAA;AAClB,EAAA,IAAI,SAAA,GAAY,IAAA;AAChB,EAAA,IAAI,OAAA,GAAiD,IAAA;AACrD,EAAA,IAAI,QAAA,GAAW,KAAA;AAIf,EAAA,SAAS,YAAA,GAAsC;AAC7C,IAAA,MAAM,GAAA,GAAM,IAAI,kBAAA,EAAmB;AACnC,IAAA,GAAA,CAAI,MAAA,GAAS,MAAA;AACb,IAAA,GAAA,CAAI,aAAa,KAAA,GAAQ,WAAA;AACzB,IAAA,GAAA,CAAI,IAAA,GAAO,SAAA;AACX,IAAA,IAAI,SAAA,KAAc,MAAA,EAAW,GAAA,CAAI,SAAA,GAAY,SAAA;AAC7C,IAAA,IAAI,OAAA,KAAY,MAAA,EAAW,GAAA,CAAI,OAAA,GAAU,OAAA;AAGzC,IAAA,IAAI,OAAA,CAAQ,SAAS,CAAA,EAAG;AACtB,MAAA,GAAA,CAAI,OAAA,CAAQ,OAAA,CAAQ,CAAC,CAAE,CAAA;AACvB,MAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,OAAA,CAAQ,MAAA,GAAS,GAAG,CAAA,EAAA,EAAK;AAC3C,QAAA,OAAA,CAAQ,CAAC,CAAA,CAAG,OAAA,CAAQ,OAAA,CAAQ,CAAA,GAAI,CAAC,CAAE,CAAA;AAAA,MACrC;AACA,MAAA,OAAA,CAAQ,OAAA,CAAQ,MAAA,GAAS,CAAC,CAAA,CAAG,QAAQ,WAAW,CAAA;AAAA,IAClD,CAAA,MAAO;AACL,MAAA,GAAA,CAAI,QAAQ,WAAW,CAAA;AAAA,IACzB;AAEA,IAAA,GAAA,CAAI,OAAA,GAAU,WAAA;AACd,IAAA,OAAO,GAAA;AAAA,EACT;AAEA,EAAA,SAAS,YAAY,gBAAA,EAA0B;AAC7C,IAAA,UAAA,GAAa,YAAA,EAAa;AAC1B,IAAA,UAAA,CAAW,KAAA,CAAM,GAAG,gBAAgB,CAAA;AACpC,IAAA,SAAA,GAAY,GAAA,CAAI,cAAc,gBAAA,GAAmB,WAAA;AAAA,EACnD;AAEA,EAAA,SAAS,UAAA,GAAa;AACpB,IAAA,IAAI,UAAA,EAAY;AACd,MAAA,UAAA,CAAW,OAAA,GAAU,IAAA;AACrB,MAAA,IAAI;AACF,QAAA,UAAA,CAAW,IAAA,EAAK;AAAA,MAClB,CAAA,CAAA,MAAQ;AAAA,MAER;AACA,MAAA,UAAA,CAAW,UAAA,EAAW;AACtB,MAAA,UAAA,GAAa,IAAA;AAAA,IACf;AAAA,EACF;AAEA,EAAA,SAAS,WAAA,GAAc;AAErB,IAAA,IAAI,UAAU,SAAA,EAAW;AACzB,IAAA,IAAI,SAAA,EAAW;AACb,MAAA,OAAA,CAAQ,IAAA,CAAK,QAAQ,MAAkB,CAAA;AACvC,MAAA;AAAA,IACF;AACA,IAAA,QAAA,CAAS,SAAS,CAAA;AAClB,IAAA,QAAA,GAAW,CAAA;AACX,IAAA,SAAA,EAAU;AACV,IAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,MAAkB,CAAA;AAAA,EAC1C;AAEA,EAAA,SAAS,SAAS,IAAA,EAAqB;AACrC,IAAA,IAAI,UAAU,IAAA,EAAM;AACpB,IAAA,KAAA,GAAQ,IAAA;AACR,IAAA,OAAA,CAAQ,IAAA,CAAK,aAAA,EAAe,EAAE,KAAA,EAAO,MAAM,CAAA;AAAA,EAC7C;AAEA,EAAA,SAAS,UAAA,GAAa;AACpB,IAAA,IAAI,YAAY,IAAA,EAAM;AACtB,IAAA,OAAA,GAAU,YAAY,MAAM;AAC1B,MAAA,IAAI,UAAU,SAAA,EAAW;AACzB,MAAA,OAAA,CAAQ,KAAK,YAAA,EAAc;AAAA,QACzB,UAAU,cAAA,EAAe;AAAA,QACzB;AAAA,OACD,CAAA;AAAA,IACH,GAAG,kBAAkB,CAAA;AAAA,EACvB;AAEA,EAAA,SAAS,SAAA,GAAY;AACnB,IAAA,IAAI,YAAY,IAAA,EAAM;AACpB,MAAA,aAAA,CAAc,OAAO,CAAA;AACrB,MAAA,OAAA,GAAU,IAAA;AAAA,IACZ;AAAA,EACF;AAIA,EAAA,SAAS,cAAA,GAAyB;AAChC,IAAA,IAAI,UAAU,SAAA,EAAW;AACvB,MAAA,MAAM,OAAA,GAAA,CAAW,GAAA,CAAI,WAAA,GAAc,SAAA,IAAa,WAAA;AAChD,MAAA,IAAI,SAAA,EAAW;AACb,QAAA,MAAM,OAAA,GAAA,CACH,OAAA,IAAW,QAAA,KAAa,SAAA,IAAa,CAAA,CAAA;AACxC,QAAA,OAAA,CAAS,OAAA,IAAW,SAAA,IAAa,CAAA,CAAA,IAAM,OAAA,IAAY,SAAA,IAAa,CAAA,CAAA;AAAA,MAClE;AACA,MAAA,OAAO,IAAA,CAAK,GAAA,CAAI,OAAA,EAAS,QAAQ,CAAA;AAAA,IACnC;AACA,IAAA,IAAI,KAAA,KAAU,UAAU,OAAO,QAAA;AAC/B,IAAA,OAAO,CAAA;AAAA,EACT;AAEA,EAAA,SAAS,KAAA,GAAQ;AACf,IAAA,IAAI,KAAA,KAAU,aAAa,QAAA,EAAU;AACrC,IAAA,QAAA,GAAW,cAAA,EAAe;AAC1B,IAAA,UAAA,EAAW;AACX,IAAA,SAAA,EAAU;AACV,IAAA,QAAA,CAAS,QAAQ,CAAA;AACjB,IAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,MAAkB,CAAA;AAAA,EAC1C;AAEA,EAAA,SAAS,MAAA,GAAS;AAChB,IAAA,IAAI,KAAA,KAAU,YAAY,QAAA,EAAU;AACpC,IAAA,WAAA,CAAY,QAAQ,CAAA;AACpB,IAAA,QAAA,CAAS,SAAS,CAAA;AAClB,IAAA,UAAA,EAAW;AACX,IAAA,OAAA,CAAQ,IAAA,CAAK,UAAU,MAAkB,CAAA;AAAA,EAC3C;AAEA,EAAA,SAAS,eAAA,GAAkB;AACzB,IAAA,IAAI,KAAA,KAAU,WAAW,KAAA,EAAM;AAAA,SAAA,IACtB,KAAA,KAAU,UAAU,MAAA,EAAO;AAAA,EACtC;AAEA,EAAA,SAAS,KAAK,QAAA,EAAkB;AAC9B,IAAA,IAAI,QAAA,EAAU;AACd,IAAA,MAAM,OAAA,GAAU,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,GAAA,CAAI,QAAA,EAAU,QAAQ,CAAC,CAAA;AACxD,IAAA,MAAM,aAAa,KAAA,KAAU,SAAA;AAE7B,IAAA,UAAA,EAAW;AACX,IAAA,SAAA,EAAU;AAEV,IAAA,QAAA,GAAW,OAAA;AAEX,IAAA,IAAI,UAAA,EAAY;AACd,MAAA,WAAA,CAAY,OAAO,CAAA;AACnB,MAAA,UAAA,EAAW;AAAA,IACb;AAEA,IAAA,OAAA,CAAQ,IAAA,CAAK,MAAA,EAAQ,EAAE,QAAA,EAAU,SAAS,CAAA;AAAA,EAC5C;AAEA,EAAA,SAAS,IAAA,GAAO;AACd,IAAA,IAAI,KAAA,KAAU,aAAa,QAAA,EAAU;AACrC,IAAA,UAAA,EAAW;AACX,IAAA,SAAA,EAAU;AACV,IAAA,QAAA,GAAW,CAAA;AACX,IAAA,QAAA,CAAS,SAAS,CAAA;AAClB,IAAA,OAAA,CAAQ,IAAA,CAAK,QAAQ,MAAkB,CAAA;AAAA,EACzC;AAEA,EAAA,SAAS,gBAAgB,IAAA,EAAc;AACrC,IAAA,MAAM,WAAW,cAAA,EAAe;AAChC,IAAA,WAAA,GAAc,IAAA;AACd,IAAA,IAAI,UAAA,EAAY;AACd,MAAA,UAAA,CAAW,aAAa,KAAA,GAAQ,IAAA;AAChC,MAAA,SAAA,GAAY,GAAA,CAAI,cAAc,QAAA,GAAW,IAAA;AAAA,IAC3C;AAAA,EACF;AAEA,EAAA,SAAS,QAAQ,KAAA,EAAgB;AAC/B,IAAA,SAAA,GAAY,KAAA;AACZ,IAAA,IAAI,UAAA,EAAY;AACd,MAAA,UAAA,CAAW,IAAA,GAAO,KAAA;AAAA,IACpB;AAAA,EACF;AAEA,EAAA,SAAS,OAAA,GAAU;AACjB,IAAA,IAAI,QAAA,EAAU;AACd,IAAA,QAAA,GAAW,IAAA;AACX,IAAA,UAAA,EAAW;AACX,IAAA,SAAA,EAAU;AACV,IAAA,OAAA,CAAQ,KAAA,EAAM;AAAA,EAChB;AAIA,EAAA,WAAA,CAAY,aAAa,CAAA;AACzB,EAAA,QAAA,CAAS,SAAS,CAAA;AAClB,EAAA,UAAA,EAAW;AACX,EAAA,OAAA,CAAQ,IAAA,CAAK,QAAQ,MAAkB,CAAA;AAEvC,EAAA,OAAO;AAAA,IACL,UAAU,MAAM,KAAA;AAAA,IAChB,cAAA;AAAA,IACA,aAAa,MAAM,QAAA;AAAA,IACnB,aAAa,MAAO,QAAA,GAAW,CAAA,GAAI,cAAA,KAAmB,QAAA,GAAW,CAAA;AAAA,IACjE,KAAA;AAAA,IACA,MAAA;AAAA,IACA,eAAA;AAAA,IACA,IAAA;AAAA,IACA,IAAA;AAAA,IACA,eAAA;AAAA,IACA,OAAA;AAAA,IACA,EAAA,EAAI,OAAA,CAAQ,EAAA,CAAG,IAAA,CAAK,OAAO,CAAA;AAAA,IAC3B,GAAA,EAAK,OAAA,CAAQ,GAAA,CAAI,IAAA,CAAK,OAAO,CAAA;AAAA,IAC7B;AAAA,GACF;AACF;AAMA,SAAS,uBAAA,CACP,GAAA,EACA,MAAA,EACA,OAAA,EACU;AACV,EAAA,MAAM;AAAA,IACJ,QAAQ,aAAA,GAAgB,CAAA;AAAA,IACxB,IAAA,GAAO,KAAA;AAAA,IACP,cAAc,WAAA,GAAc,CAAA;AAAA,IAC5B,UAAU,EAAC;AAAA,IACX,cAAc,GAAA,CAAI,WAAA;AAAA,IAClB,kBAAA,GAAqB;AAAA,GACvB,GAAI,OAAA;AAEJ,EAAA,MAAM,UAAU,aAAA,EAAgC;AAChD,EAAA,MAAM,WAAW,MAAA,CAAO,QAAA;AAExB,EAAA,IAAI,KAAA,GAAuB,SAAA;AAC3B,EAAA,IAAI,cAAA,GACF,IAAA;AACF,EAAA,IAAI,OAAA,GAAiD,IAAA;AACrD,EAAA,IAAI,QAAA,GAAW,KAAA;AACf,EAAA,IAAI,WAAA,GAAc,WAAA;AAClB,EAAA,IAAI,SAAA,GAAY,IAAA;AAChB,EAAA,IAAI,WAAA,GAA6B,IAAA;AAGjC,EAAA,OAAA,CAAQ,IAAA,CAAK,aAAA,EAAe,EAAE,KAAA,EAAO,WAAW,CAAA;AAChD,EAAA,OAAA,CAAQ,IAAA,CAAK,QAAQ,MAAkB,CAAA;AAGvC,EAAA,OAAO,sBAAuB,CAAA,CAAE,IAAA,CAAK,CAAC,EAAE,uBAAsB,KAAM;AAClE,IAAA,IAAI,QAAA,EAAU;AAEd,IAAA,cAAA,GAAiB,qBAAA,CAAsB,KAAK,MAAA,EAAQ;AAAA,MAClD,KAAA,EAAO,WAAA;AAAA,MACP,MAAA,EAAQ,aAAA;AAAA,MACR,IAAA,EAAM,SAAA;AAAA,MACN,OAAA;AAAA,MACA,WAAA;AAAA,MACA;AAAA,KACD,CAAA;AAGD,IAAA,cAAA,CAAe,EAAA,CAAG,WAAA,EAAa,CAAC,IAAA,KAAS;AACvC,MAAA,IAAI,QAAA,EAAU;AACd,MAAA,OAAA,CAAQ,IAAA,CAAK,aAAa,IAAI,CAAA;AAAA,IAChC,CAAC,CAAA;AAED,IAAA,cAAA,CAAe,EAAA,CAAG,UAAA,EAAY,CAAC,IAAA,KAAS;AACtC,MAAA,IAAI,QAAA,EAAU;AACd,MAAA,OAAA,CAAQ,IAAA,CAAK,YAAY,IAAI,CAAA;AAAA,IAC/B,CAAC,CAAA;AAED,IAAA,cAAA,CAAe,EAAA,CAAG,QAAQ,MAAM;AAC9B,MAAA,IAAI,QAAA,EAAU;AACd,MAAA,OAAA,CAAQ,IAAA,CAAK,QAAQ,MAAkB,CAAA;AAAA,IACzC,CAAC,CAAA;AAED,IAAA,cAAA,CAAe,EAAA,CAAG,SAAS,MAAM;AAC/B,MAAA,IAAI,QAAA,EAAU;AACd,MAAA,KAAA,GAAQ,SAAA;AACR,MAAA,SAAA,EAAU;AACV,MAAA,OAAA,CAAQ,IAAA,CAAK,aAAA,EAAe,EAAE,KAAA,EAAO,WAAW,CAAA;AAChD,MAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,MAAkB,CAAA;AAAA,IAC1C,CAAC,CAAA;AAED,IAAA,cAAA,CAAe,EAAA,CAAG,OAAA,EAAS,CAAC,IAAA,KAAS;AACnC,MAAA,IAAI,QAAA,EAAU;AACd,MAAA,IAAI,KAAK,KAAA,EAAO;AACd,QAAA,KAAA,GAAQ,SAAA;AACR,QAAA,OAAA,CAAQ,IAAA,CAAK,aAAA,EAAe,EAAE,KAAA,EAAO,WAAW,CAAA;AAChD,QAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,MAAkB,CAAA;AAAA,MAC1C;AAAA,IACF,CAAC,CAAA;AAGD,IAAA,cAAA,CAAe,KAAA,EAAM;AACrB,IAAA,UAAA,EAAW;AAGX,IAAA,IAAI,gBAAgB,IAAA,EAAM;AACxB,MAAA,cAAA,CAAe,KAAK,WAAW,CAAA;AAC/B,MAAA,WAAA,GAAc,IAAA;AAAA,IAChB;AAGA,IAAA,IAAI,UAAU,QAAA,EAAU;AACtB,MAAA,cAAA,CAAe,KAAA,EAAM;AAAA,IACvB,CAAA,MAAA,IAAW,UAAU,SAAA,EAAW;AAC9B,MAAA,cAAA,CAAe,IAAA,EAAK;AAAA,IACtB;AAAA,EACF,CAAC,CAAA;AAED,EAAA,SAAS,UAAA,GAAa;AACpB,IAAA,IAAI,YAAY,IAAA,EAAM;AACtB,IAAA,OAAA,GAAU,YAAY,MAAM;AAC1B,MAAA,IAAI,KAAA,KAAU,aAAa,QAAA,EAAU;AACrC,MAAA,OAAA,CAAQ,KAAK,YAAA,EAAc;AAAA,QACzB,UAAU,cAAA,EAAe;AAAA,QACzB;AAAA,OACD,CAAA;AAAA,IACH,GAAG,kBAAkB,CAAA;AAAA,EACvB;AAEA,EAAA,SAAS,SAAA,GAAY;AACnB,IAAA,IAAI,YAAY,IAAA,EAAM;AACpB,MAAA,aAAA,CAAc,OAAO,CAAA;AACrB,MAAA,OAAA,GAAU,IAAA;AAAA,IACZ;AAAA,EACF;AAEA,EAAA,SAAS,cAAA,GAAyB;AAChC,IAAA,IAAI,gBAAgB,IAAA,EAAM;AACxB,MAAA,OAAO,WAAA;AAAA,IACT;AACA,IAAA,IAAI,cAAA,EAAgB;AAClB,MAAA,OAAO,eAAe,kBAAA,EAAmB;AAAA,IAC3C;AACA,IAAA,OAAO,aAAA;AAAA,EACT;AAEA,EAAA,SAAS,KAAA,GAAQ;AACf,IAAA,IAAI,KAAA,KAAU,aAAa,QAAA,EAAU;AACrC,IAAA,KAAA,GAAQ,QAAA;AACR,IAAA,cAAA,EAAgB,KAAA,EAAM;AACtB,IAAA,SAAA,EAAU;AACV,IAAA,OAAA,CAAQ,IAAA,CAAK,aAAA,EAAe,EAAE,KAAA,EAAO,UAAU,CAAA;AAC/C,IAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,MAAkB,CAAA;AAAA,EAC1C;AAEA,EAAA,SAAS,MAAA,GAAS;AAChB,IAAA,IAAI,KAAA,KAAU,YAAY,QAAA,EAAU;AACpC,IAAA,KAAA,GAAQ,SAAA;AACR,IAAA,cAAA,EAAgB,MAAA,EAAO;AACvB,IAAA,UAAA,EAAW;AACX,IAAA,OAAA,CAAQ,IAAA,CAAK,aAAA,EAAe,EAAE,KAAA,EAAO,WAAW,CAAA;AAChD,IAAA,OAAA,CAAQ,IAAA,CAAK,UAAU,MAAkB,CAAA;AAAA,EAC3C;AAEA,EAAA,SAAS,eAAA,GAAkB;AACzB,IAAA,IAAI,KAAA,KAAU,WAAW,KAAA,EAAM;AAAA,SAAA,IACtB,KAAA,KAAU,UAAU,MAAA,EAAO;AAAA,EACtC;AAEA,EAAA,SAAS,KAAK,QAAA,EAAkB;AAC9B,IAAA,IAAI,QAAA,EAAU;AACd,IAAA,MAAM,OAAA,GAAU,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,GAAA,CAAI,QAAA,EAAU,QAAQ,CAAC,CAAA;AACxD,IAAA,IAAI,cAAA,EAAgB;AAClB,MAAA,cAAA,CAAe,KAAK,OAAO,CAAA;AAAA,IAC7B,CAAA,MAAO;AACL,MAAA,WAAA,GAAc,OAAA;AAAA,IAChB;AACA,IAAA,OAAA,CAAQ,IAAA,CAAK,MAAA,EAAQ,EAAE,QAAA,EAAU,SAAS,CAAA;AAAA,EAC5C;AAEA,EAAA,SAAS,IAAA,GAAO;AACd,IAAA,IAAI,KAAA,KAAU,aAAa,QAAA,EAAU;AACrC,IAAA,KAAA,GAAQ,SAAA;AACR,IAAA,cAAA,EAAgB,IAAA,EAAK;AACrB,IAAA,SAAA,EAAU;AACV,IAAA,OAAA,CAAQ,IAAA,CAAK,aAAA,EAAe,EAAE,KAAA,EAAO,WAAW,CAAA;AAChD,IAAA,OAAA,CAAQ,IAAA,CAAK,QAAQ,MAAkB,CAAA;AAAA,EACzC;AAEA,EAAA,SAAS,gBAAgB,IAAA,EAAc;AACrC,IAAA,WAAA,GAAc,IAAA;AACd,IAAA,IAAI,cAAA,EAAgB;AAClB,MAAA,cAAA,CAAe,SAAS,IAAI,CAAA;AAAA,IAC9B;AAAA,EACF;AAEA,EAAA,SAAS,QAAQ,KAAA,EAAgB;AAC/B,IAAA,SAAA,GAAY,KAAA;AACZ,IAAA,cAAA,EAAgB,QAAQ,KAAK,CAAA;AAAA,EAC/B;AAEA,EAAA,SAAS,OAAA,GAAU;AACjB,IAAA,IAAI,QAAA,EAAU;AACd,IAAA,QAAA,GAAW,IAAA;AACX,IAAA,SAAA,EAAU;AACV,IAAA,cAAA,EAAgB,OAAA,EAAQ;AACxB,IAAA,OAAA,CAAQ,KAAA,EAAM;AAAA,EAChB;AAEA,EAAA,SAAS,qBAAA,GAA2D;AAClE,IAAA,IAAI,CAAC,gBAAgB,OAAO,IAAA;AAC5B,IAAA,OAAO,eAAe,WAAA,EAAY;AAAA,EACpC;AAEA,EAAA,MAAM,QAAA,GAEF;AAAA,IACF,UAAU,MAAM,KAAA;AAAA,IAChB,cAAA;AAAA,IACA,aAAa,MAAM,QAAA;AAAA,IACnB,aAAa,MAAO,QAAA,GAAW,CAAA,GAAI,cAAA,KAAmB,QAAA,GAAW,CAAA;AAAA,IACjE,KAAA;AAAA,IACA,MAAA;AAAA,IACA,eAAA;AAAA,IACA,IAAA;AAAA,IACA,IAAA;AAAA,IACA,eAAA;AAAA,IACA,OAAA;AAAA,IACA,EAAA,EAAI,OAAA,CAAQ,EAAA,CAAG,IAAA,CAAK,OAAO,CAAA;AAAA,IAC3B,GAAA,EAAK,OAAA,CAAQ,GAAA,CAAI,IAAA,CAAK,OAAO,CAAA;AAAA,IAC7B,OAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,OAAO,QAAA;AACT","file":"chunk-X4IFO7U7.js","sourcesContent":["// ---------------------------------------------------------------------------\n// M3: Playback engine\n// ---------------------------------------------------------------------------\n\nimport { createEmitter } from \"./emitter.js\";\nimport type {\n Playback,\n PlaybackEventMap,\n PlaybackState,\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(\n ctx: AudioContext,\n buffer: AudioBuffer,\n options?: PlayOptions,\n): 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 state: PlaybackState = \"stopped\";\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;\n let isLooping = loop;\n let timerId: ReturnType<typeof setInterval> | null = null;\n let disposed = false;\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 (state !== \"playing\") return;\n if (isLooping) {\n emitter.emit(\"loop\", undefined as never);\n return;\n }\n setState(\"stopped\");\n pausedAt = 0;\n stopTimer();\n emitter.emit(\"ended\", undefined as never);\n }\n\n function setState(next: PlaybackState) {\n if (state === next) return;\n state = next;\n emitter.emit(\"statechange\", { state: next });\n }\n\n function startTimer() {\n if (timerId !== null) return;\n timerId = setInterval(() => {\n if (state !== \"playing\") return;\n emitter.emit(\"timeupdate\", {\n position: getCurrentTime(),\n duration,\n });\n }, timeupdateInterval);\n }\n\n function stopTimer() {\n if (timerId !== null) {\n clearInterval(timerId);\n timerId = null;\n }\n }\n\n // ----- public API -----\n\n function getCurrentTime(): number {\n if (state === \"playing\") {\n const elapsed = (ctx.currentTime - startedAt) * currentRate;\n if (isLooping) {\n const loopDur =\n (loopEnd ?? duration) - (loopStart ?? 0);\n return ((elapsed - (loopStart ?? 0)) % loopDur) + (loopStart ?? 0);\n }\n return Math.min(elapsed, duration);\n }\n if (state === \"paused\") return pausedAt;\n return 0;\n }\n\n function pause() {\n if (state !== \"playing\" || disposed) return;\n pausedAt = getCurrentTime();\n stopSource();\n stopTimer();\n setState(\"paused\");\n emitter.emit(\"pause\", undefined as never);\n }\n\n function resume() {\n if (state !== \"paused\" || disposed) return;\n startSource(pausedAt);\n setState(\"playing\");\n startTimer();\n emitter.emit(\"resume\", undefined as never);\n }\n\n function togglePlayPause() {\n if (state === \"playing\") pause();\n else if (state === \"paused\") resume();\n }\n\n function seek(position: number) {\n if (disposed) return;\n const clamped = Math.max(0, Math.min(position, duration));\n const wasPlaying = state === \"playing\";\n\n stopSource();\n stopTimer();\n\n pausedAt = clamped;\n\n if (wasPlaying) {\n startSource(clamped);\n startTimer();\n }\n\n emitter.emit(\"seek\", { position: clamped });\n }\n\n function stop() {\n if (state === \"stopped\" || disposed) return;\n stopSource();\n stopTimer();\n pausedAt = 0;\n setState(\"stopped\");\n emitter.emit(\"stop\", undefined as never);\n }\n\n function setPlaybackRate(rate: number) {\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 (disposed) return;\n disposed = true;\n stopSource();\n stopTimer();\n emitter.clear();\n }\n\n // ----- kick off initial playback -----\n\n startSource(initialOffset);\n setState(\"playing\");\n startTimer();\n emitter.emit(\"play\", undefined as never);\n\n return {\n getState: () => state,\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 state: PlaybackState = \"playing\";\n let engineInstance: import(\"./stretcher/types.js\").StretcherEngine | null =\n null;\n let timerId: ReturnType<typeof setInterval> | null = null;\n let disposed = false;\n let currentRate = initialRate;\n let isLooping = loop;\n let pendingSeek: number | null = null;\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\").then(({ createStretcherEngine }) => {\n if (disposed) 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 (disposed) return;\n emitter.emit(\"buffering\", data);\n });\n\n engineInstance.on(\"buffered\", (data) => {\n if (disposed) return;\n emitter.emit(\"buffered\", data);\n });\n\n engineInstance.on(\"loop\", () => {\n if (disposed) return;\n emitter.emit(\"loop\", undefined as never);\n });\n\n engineInstance.on(\"ended\", () => {\n if (disposed) return;\n state = \"stopped\";\n stopTimer();\n emitter.emit(\"statechange\", { state: \"stopped\" });\n emitter.emit(\"ended\", undefined as never);\n });\n\n engineInstance.on(\"error\", (data) => {\n if (disposed) return;\n if (data.fatal) {\n state = \"stopped\";\n emitter.emit(\"statechange\", { state: \"stopped\" });\n emitter.emit(\"ended\", undefined as never);\n }\n });\n\n // Start engine and timeupdate timer\n engineInstance.start();\n 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 (state === \"paused\") {\n engineInstance.pause();\n } else if (state === \"stopped\") {\n engineInstance.stop();\n }\n });\n\n function startTimer() {\n if (timerId !== null) return;\n timerId = setInterval(() => {\n if (state !== \"playing\" || disposed) return;\n emitter.emit(\"timeupdate\", {\n position: getCurrentTime(),\n duration,\n });\n }, timeupdateInterval);\n }\n\n function stopTimer() {\n if (timerId !== null) {\n clearInterval(timerId);\n timerId = null;\n }\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 (state !== \"playing\" || disposed) return;\n state = \"paused\";\n engineInstance?.pause();\n stopTimer();\n emitter.emit(\"statechange\", { state: \"paused\" });\n emitter.emit(\"pause\", undefined as never);\n }\n\n function resume() {\n if (state !== \"paused\" || disposed) return;\n state = \"playing\";\n engineInstance?.resume();\n startTimer();\n emitter.emit(\"statechange\", { state: \"playing\" });\n emitter.emit(\"resume\", undefined as never);\n }\n\n function togglePlayPause() {\n if (state === \"playing\") pause();\n else if (state === \"paused\") resume();\n }\n\n function seek(position: number) {\n if (disposed) 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 (state === \"stopped\" || disposed) return;\n state = \"stopped\";\n engineInstance?.stop();\n stopTimer();\n emitter.emit(\"statechange\", { state: \"stopped\" });\n emitter.emit(\"stop\", undefined as never);\n }\n\n function setPlaybackRate(rate: number) {\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 (disposed) return;\n disposed = true;\n stopTimer();\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: () => state,\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"]}
@@ -0,0 +1,148 @@
1
+ 'use strict';
2
+
3
+ var chunkD5CD5KQZ_cjs = require('./chunk-D5CD5KQZ.cjs');
4
+ var chunkQWNV2BZ5_cjs = require('./chunk-QWNV2BZ5.cjs');
5
+ var chunk7S5KWTZ6_cjs = require('./chunk-7S5KWTZ6.cjs');
6
+ var chunk6UTN73HG_cjs = require('./chunk-6UTN73HG.cjs');
7
+ var chunkCPAT75WD_cjs = require('./chunk-CPAT75WD.cjs');
8
+ var chunkCTUCTTIE_cjs = require('./chunk-CTUCTTIE.cjs');
9
+ var chunkM5PDY5EZ_cjs = require('./chunk-M5PDY5EZ.cjs');
10
+ var chunkQFFQQMU4_cjs = require('./chunk-QFFQQMU4.cjs');
11
+ var chunk4LNVRSTM_cjs = require('./chunk-4LNVRSTM.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 chunkCPAT75WD_cjs.loadBuffer(this.ctx, url, options);
37
+ }
38
+ loadFromBlob(blob) {
39
+ return chunkCPAT75WD_cjs.loadBufferFromBlob(this.ctx, blob);
40
+ }
41
+ loadAll(map) {
42
+ return chunkCPAT75WD_cjs.loadBuffers(this.ctx, map);
43
+ }
44
+ getBufferInfo(buffer) {
45
+ return chunkCPAT75WD_cjs.getBufferInfo(buffer);
46
+ }
47
+ // --- Play ---
48
+ play(buffer, options) {
49
+ return chunkCTUCTTIE_cjs.play(this.ctx, buffer, options);
50
+ }
51
+ // --- Nodes ---
52
+ createGain(initialValue) {
53
+ return chunkM5PDY5EZ_cjs.createGain(this.ctx, initialValue);
54
+ }
55
+ createAnalyser(options) {
56
+ return chunkM5PDY5EZ_cjs.createAnalyser(this.ctx, options);
57
+ }
58
+ createFilter(options) {
59
+ return chunkM5PDY5EZ_cjs.createFilter(this.ctx, options);
60
+ }
61
+ createPanner(pan) {
62
+ return chunkM5PDY5EZ_cjs.createPanner(this.ctx, pan);
63
+ }
64
+ createCompressor(options) {
65
+ return chunkM5PDY5EZ_cjs.createCompressor(this.ctx, options);
66
+ }
67
+ rampGain(gain, target, duration) {
68
+ chunkM5PDY5EZ_cjs.rampGain(gain, target, duration);
69
+ }
70
+ getFrequencyData(analyser) {
71
+ return chunkM5PDY5EZ_cjs.getFrequencyData(analyser);
72
+ }
73
+ getFrequencyDataByte(analyser) {
74
+ return chunkM5PDY5EZ_cjs.getFrequencyDataByte(analyser);
75
+ }
76
+ chain(...nodes) {
77
+ chunkM5PDY5EZ_cjs.chain(...nodes);
78
+ }
79
+ disconnectChain(...nodes) {
80
+ chunkM5PDY5EZ_cjs.disconnectChain(...nodes);
81
+ }
82
+ // --- Waveform ---
83
+ extractPeaks(buffer, options) {
84
+ return chunkQFFQQMU4_cjs.extractPeaks(buffer, options);
85
+ }
86
+ extractPeakPairs(buffer, options) {
87
+ return chunkQFFQQMU4_cjs.extractPeakPairs(buffer, options);
88
+ }
89
+ extractRMS(buffer, options) {
90
+ return chunkQFFQQMU4_cjs.extractRMS(buffer, options);
91
+ }
92
+ // --- Fade ---
93
+ fadeIn(gain, target, options) {
94
+ chunk4LNVRSTM_cjs.fadeIn(gain, target, options);
95
+ }
96
+ fadeOut(gain, options) {
97
+ chunk4LNVRSTM_cjs.fadeOut(gain, options);
98
+ }
99
+ crossfade(gainA, gainB, options) {
100
+ chunk4LNVRSTM_cjs.crossfade(gainA, gainB, options);
101
+ }
102
+ autoFade(playback, gain, options) {
103
+ return chunk4LNVRSTM_cjs.autoFade(playback, gain, options);
104
+ }
105
+ // --- Scheduler ---
106
+ createScheduler(options) {
107
+ return chunkD5CD5KQZ_cjs.createScheduler(this.ctx, options);
108
+ }
109
+ createClock(options) {
110
+ return chunkD5CD5KQZ_cjs.createClock(this.ctx, options);
111
+ }
112
+ // --- Synth ---
113
+ createSineBuffer(frequency, duration) {
114
+ return chunkQWNV2BZ5_cjs.createSineBuffer(this.ctx, frequency, duration);
115
+ }
116
+ createNoiseBuffer(duration) {
117
+ return chunkQWNV2BZ5_cjs.createNoiseBuffer(this.ctx, duration);
118
+ }
119
+ createClickBuffer(frequency, duration) {
120
+ return chunkQWNV2BZ5_cjs.createClickBuffer(this.ctx, frequency, duration);
121
+ }
122
+ // --- Adapters ---
123
+ getSnapshot(playback) {
124
+ return chunk7S5KWTZ6_cjs.getSnapshot(playback);
125
+ }
126
+ subscribeSnapshot(playback, callback) {
127
+ return chunk7S5KWTZ6_cjs.subscribeSnapshot(playback, callback);
128
+ }
129
+ onFrame(playback, callback) {
130
+ return chunk7S5KWTZ6_cjs.onFrame(playback, callback);
131
+ }
132
+ whenEnded(playback) {
133
+ return chunk7S5KWTZ6_cjs.whenEnded(playback);
134
+ }
135
+ whenPosition(playback, position) {
136
+ return chunk7S5KWTZ6_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-XZBMBZA3.cjs.map
148
+ //# sourceMappingURL=chunk-XZBMBZA3.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/player.ts"],"names":["createContext","resumeContext","ensureRunning","now","loadBuffer","loadBufferFromBlob","loadBuffers","getBufferInfo","play","createGain","createAnalyser","createFilter","createPanner","createCompressor","rampGain","getFrequencyData","getFrequencyDataByte","chain","disconnectChain","extractPeaks","extractPeakPairs","extractRMS","fadeIn","fadeOut","crossfade","autoFade","createScheduler","createClock","createSineBuffer","createNoiseBuffer","createClickBuffer","getSnapshot","subscribeSnapshot","onFrame","whenEnded","whenPosition"],"mappings":"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","file":"chunk-XZBMBZA3.cjs","sourcesContent":["import { createContext, resumeContext, ensureRunning, now } from \"./context.js\";\nimport {\n loadBuffer,\n loadBufferFromBlob,\n loadBuffers,\n getBufferInfo,\n} from \"./buffer.js\";\nimport { play } from \"./play.js\";\nimport {\n createGain as createGainNode,\n rampGain,\n createAnalyser as createAnalyserNode,\n getFrequencyData,\n getFrequencyDataByte,\n createFilter as createFilterNode,\n createPanner as createPannerNode,\n createCompressor as createCompressorNode,\n chain,\n disconnectChain,\n} from \"./nodes.js\";\nimport { extractPeaks, extractPeakPairs, extractRMS } from \"./waveform.js\";\nimport { fadeIn, fadeOut, crossfade, autoFade } from \"./fade.js\";\nimport { createScheduler, createClock } from \"./scheduler.js\";\nimport {\n createSineBuffer,\n createNoiseBuffer,\n createClickBuffer,\n} from \"./synth.js\";\nimport {\n getSnapshot,\n subscribeSnapshot,\n onFrame,\n whenEnded,\n whenPosition,\n} from \"./adapters.js\";\n\nimport type {\n CreateContextOptions,\n LoadBufferOptions,\n BufferInfo,\n PlayOptions,\n Playback,\n PlaybackSnapshot,\n ExtractPeaksOptions,\n PeakPair,\n FadeOptions,\n CrossfadeOptions,\n AutoFadeOptions,\n SchedulerOptions,\n ClockOptions,\n} from \"./types.js\";\nimport type { Scheduler, Clock } from \"./scheduler.js\";\n\nexport interface WaaPlayerOptions extends CreateContextOptions {}\n\nexport class WaaPlayer {\n readonly ctx: AudioContext;\n private readonly _ownsContext: boolean;\n\n constructor(ctxOrOptions?: AudioContext | WaaPlayerOptions) {\n if (\n ctxOrOptions &&\n typeof (ctxOrOptions as AudioContext).createGain === \"function\"\n ) {\n this.ctx = ctxOrOptions as AudioContext;\n this._ownsContext = false;\n } else {\n this.ctx = createContext(ctxOrOptions as WaaPlayerOptions | undefined);\n this._ownsContext = true;\n }\n }\n\n // --- Context ---\n\n resume(): Promise<void> {\n return resumeContext(this.ctx);\n }\n\n ensureRunning(): Promise<void> {\n return ensureRunning(this.ctx);\n }\n\n now(): number {\n return now(this.ctx);\n }\n\n // --- Buffer ---\n\n load(url: string, options?: LoadBufferOptions): Promise<AudioBuffer> {\n return loadBuffer(this.ctx, url, options);\n }\n\n loadFromBlob(blob: Blob): Promise<AudioBuffer> {\n return loadBufferFromBlob(this.ctx, blob);\n }\n\n loadAll(map: Record<string, string>): Promise<Map<string, AudioBuffer>> {\n return loadBuffers(this.ctx, map);\n }\n\n getBufferInfo(buffer: AudioBuffer): BufferInfo {\n return getBufferInfo(buffer);\n }\n\n // --- Play ---\n\n play(buffer: AudioBuffer, options?: PlayOptions): Playback {\n return play(this.ctx, buffer, options);\n }\n\n // --- Nodes ---\n\n createGain(initialValue?: number): GainNode {\n return createGainNode(this.ctx, initialValue);\n }\n\n createAnalyser(options?: {\n fftSize?: number;\n smoothingTimeConstant?: number;\n }): AnalyserNode {\n return createAnalyserNode(this.ctx, options);\n }\n\n createFilter(options?: {\n type?: BiquadFilterType;\n frequency?: number;\n Q?: number;\n gain?: number;\n }): BiquadFilterNode {\n return createFilterNode(this.ctx, options);\n }\n\n createPanner(pan?: number): StereoPannerNode {\n return createPannerNode(this.ctx, pan);\n }\n\n createCompressor(options?: {\n threshold?: number;\n knee?: number;\n ratio?: number;\n attack?: number;\n release?: number;\n }): DynamicsCompressorNode {\n return createCompressorNode(this.ctx, options);\n }\n\n rampGain(gain: GainNode, target: number, duration: number): void {\n rampGain(gain, target, duration);\n }\n\n getFrequencyData(analyser: AnalyserNode): Float32Array {\n return getFrequencyData(analyser);\n }\n\n getFrequencyDataByte(analyser: AnalyserNode): Uint8Array {\n return getFrequencyDataByte(analyser);\n }\n\n chain(...nodes: AudioNode[]): void {\n chain(...nodes);\n }\n\n disconnectChain(...nodes: AudioNode[]): void {\n disconnectChain(...nodes);\n }\n\n // --- Waveform ---\n\n extractPeaks(buffer: AudioBuffer, options?: ExtractPeaksOptions): number[] {\n return extractPeaks(buffer, options);\n }\n\n extractPeakPairs(\n buffer: AudioBuffer,\n options?: ExtractPeaksOptions,\n ): PeakPair[] {\n return extractPeakPairs(buffer, options);\n }\n\n extractRMS(\n buffer: AudioBuffer,\n options?: ExtractPeaksOptions & { channel?: number },\n ): number[] {\n return extractRMS(buffer, options);\n }\n\n // --- Fade ---\n\n fadeIn(gain: GainNode, target: number, options?: FadeOptions): void {\n fadeIn(gain, target, options);\n }\n\n fadeOut(gain: GainNode, options?: FadeOptions): void {\n fadeOut(gain, options);\n }\n\n crossfade(\n gainA: GainNode,\n gainB: GainNode,\n options?: CrossfadeOptions,\n ): void {\n crossfade(gainA, gainB, options);\n }\n\n autoFade(\n playback: Playback,\n gain: GainNode,\n options?: AutoFadeOptions,\n ): () => void {\n return autoFade(playback, gain, options);\n }\n\n // --- Scheduler ---\n\n createScheduler(options?: SchedulerOptions): Scheduler {\n return createScheduler(this.ctx, options);\n }\n\n createClock(options?: ClockOptions): Clock {\n return createClock(this.ctx, options);\n }\n\n // --- Synth ---\n\n createSineBuffer(frequency: number, duration: number): AudioBuffer {\n return createSineBuffer(this.ctx, frequency, duration);\n }\n\n createNoiseBuffer(duration: number): AudioBuffer {\n return createNoiseBuffer(this.ctx, duration);\n }\n\n createClickBuffer(frequency: number, duration: number): AudioBuffer {\n return createClickBuffer(this.ctx, frequency, duration);\n }\n\n // --- Adapters ---\n\n getSnapshot(playback: Playback): PlaybackSnapshot {\n return getSnapshot(playback);\n }\n\n subscribeSnapshot(playback: Playback, callback: () => void): () => void {\n return subscribeSnapshot(playback, callback);\n }\n\n onFrame(\n playback: Playback,\n callback: (snapshot: PlaybackSnapshot) => void,\n ): () => void {\n return onFrame(playback, callback);\n }\n\n whenEnded(playback: Playback): Promise<void> {\n return whenEnded(playback);\n }\n\n whenPosition(playback: Playback, position: number): Promise<void> {\n return whenPosition(playback, position);\n }\n\n // --- Lifecycle ---\n\n dispose(): void {\n if (this._ownsContext) {\n this.ctx.close();\n }\n }\n}\n"]}
@@ -0,0 +1,13 @@
1
+ 'use strict';
2
+
3
+ var chunkSIMLANWE_cjs = require('./chunk-SIMLANWE.cjs');
4
+ require('./chunk-5J7S6QV3.cjs');
5
+
6
+
7
+
8
+ Object.defineProperty(exports, "createStretcherEngine", {
9
+ enumerable: true,
10
+ get: function () { return chunkSIMLANWE_cjs.createStretcherEngine; }
11
+ });
12
+ //# sourceMappingURL=engine-QUMYW73L.cjs.map
13
+ //# sourceMappingURL=engine-QUMYW73L.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"engine-5JK2FCNL.cjs"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"engine-QUMYW73L.cjs"}
@@ -0,0 +1,4 @@
1
+ export { createStretcherEngine } from './chunk-2FFORBOP.js';
2
+ import './chunk-GYH2JSCY.js';
3
+ //# sourceMappingURL=engine-TYI7OX7O.js.map
4
+ //# sourceMappingURL=engine-TYI7OX7O.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"engine-M2U4LE3F.js"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"engine-TYI7OX7O.js"}
package/dist/index.cjs CHANGED
@@ -1,11 +1,12 @@
1
1
  'use strict';
2
2
 
3
+ var chunkXZBMBZA3_cjs = require('./chunk-XZBMBZA3.cjs');
3
4
  var chunkD5CD5KQZ_cjs = require('./chunk-D5CD5KQZ.cjs');
4
5
  var chunkQWNV2BZ5_cjs = require('./chunk-QWNV2BZ5.cjs');
5
- var chunkHTGOHC73_cjs = require('./chunk-HTGOHC73.cjs');
6
+ var chunk7S5KWTZ6_cjs = require('./chunk-7S5KWTZ6.cjs');
6
7
  var chunk6UTN73HG_cjs = require('./chunk-6UTN73HG.cjs');
7
8
  var chunkCPAT75WD_cjs = require('./chunk-CPAT75WD.cjs');
8
- var chunkPZE6HTZR_cjs = require('./chunk-PZE6HTZR.cjs');
9
+ var chunkCTUCTTIE_cjs = require('./chunk-CTUCTTIE.cjs');
9
10
  var chunk5J7S6QV3_cjs = require('./chunk-5J7S6QV3.cjs');
10
11
  var chunkM5PDY5EZ_cjs = require('./chunk-M5PDY5EZ.cjs');
11
12
  var chunkQFFQQMU4_cjs = require('./chunk-QFFQQMU4.cjs');
@@ -13,6 +14,10 @@ var chunk4LNVRSTM_cjs = require('./chunk-4LNVRSTM.cjs');
13
14
 
14
15
 
15
16
 
17
+ Object.defineProperty(exports, "WaaPlayer", {
18
+ enumerable: true,
19
+ get: function () { return chunkXZBMBZA3_cjs.WaaPlayer; }
20
+ });
16
21
  Object.defineProperty(exports, "createClock", {
17
22
  enumerable: true,
18
23
  get: function () { return chunkD5CD5KQZ_cjs.createClock; }
@@ -35,23 +40,23 @@ Object.defineProperty(exports, "createSineBuffer", {
35
40
  });
36
41
  Object.defineProperty(exports, "getSnapshot", {
37
42
  enumerable: true,
38
- get: function () { return chunkHTGOHC73_cjs.getSnapshot; }
43
+ get: function () { return chunk7S5KWTZ6_cjs.getSnapshot; }
39
44
  });
40
45
  Object.defineProperty(exports, "onFrame", {
41
46
  enumerable: true,
42
- get: function () { return chunkHTGOHC73_cjs.onFrame; }
47
+ get: function () { return chunk7S5KWTZ6_cjs.onFrame; }
43
48
  });
44
49
  Object.defineProperty(exports, "subscribeSnapshot", {
45
50
  enumerable: true,
46
- get: function () { return chunkHTGOHC73_cjs.subscribeSnapshot; }
51
+ get: function () { return chunk7S5KWTZ6_cjs.subscribeSnapshot; }
47
52
  });
48
53
  Object.defineProperty(exports, "whenEnded", {
49
54
  enumerable: true,
50
- get: function () { return chunkHTGOHC73_cjs.whenEnded; }
55
+ get: function () { return chunk7S5KWTZ6_cjs.whenEnded; }
51
56
  });
52
57
  Object.defineProperty(exports, "whenPosition", {
53
58
  enumerable: true,
54
- get: function () { return chunkHTGOHC73_cjs.whenPosition; }
59
+ get: function () { return chunk7S5KWTZ6_cjs.whenPosition; }
55
60
  });
56
61
  Object.defineProperty(exports, "createContext", {
57
62
  enumerable: true,
@@ -87,7 +92,7 @@ Object.defineProperty(exports, "loadBuffers", {
87
92
  });
88
93
  Object.defineProperty(exports, "play", {
89
94
  enumerable: true,
90
- get: function () { return chunkPZE6HTZR_cjs.play; }
95
+ get: function () { return chunkCTUCTTIE_cjs.play; }
91
96
  });
92
97
  Object.defineProperty(exports, "createEmitter", {
93
98
  enumerable: true,
package/dist/index.d.cts CHANGED
@@ -9,3 +9,4 @@ export { autoFade, crossfade, fadeIn, fadeOut } from './fade.cjs';
9
9
  export { Clock, Scheduler, createClock, createScheduler } from './scheduler.cjs';
10
10
  export { createClickBuffer, createNoiseBuffer, createSineBuffer } from './synth.cjs';
11
11
  export { getSnapshot, onFrame, subscribeSnapshot, whenEnded, whenPosition } from './adapters.cjs';
12
+ export { WaaPlayer, WaaPlayerOptions } from './player.cjs';
package/dist/index.d.ts CHANGED
@@ -9,3 +9,4 @@ export { autoFade, crossfade, fadeIn, fadeOut } from './fade.js';
9
9
  export { Clock, Scheduler, createClock, createScheduler } from './scheduler.js';
10
10
  export { createClickBuffer, createNoiseBuffer, createSineBuffer } from './synth.js';
11
11
  export { getSnapshot, onFrame, subscribeSnapshot, whenEnded, whenPosition } from './adapters.js';
12
+ export { WaaPlayer, WaaPlayerOptions } from './player.js';
package/dist/index.js CHANGED
@@ -1,9 +1,10 @@
1
+ export { WaaPlayer } from './chunk-IMNRPYBM.js';
1
2
  export { createClock, createScheduler } from './chunk-2DL7CAEP.js';
2
3
  export { createClickBuffer, createNoiseBuffer, createSineBuffer } from './chunk-LETS7FKB.js';
3
- export { getSnapshot, onFrame, subscribeSnapshot, whenEnded, whenPosition } from './chunk-AGP2IRC6.js';
4
+ export { getSnapshot, onFrame, subscribeSnapshot, whenEnded, whenPosition } from './chunk-VKT7YCWK.js';
4
5
  export { createContext, ensureRunning, now, resumeContext } from './chunk-37CPPRLV.js';
5
6
  export { getBufferInfo, loadBuffer, loadBufferFromBlob, loadBuffers } from './chunk-T74FBKTY.js';
6
- export { play } from './chunk-RWJ4EWJT.js';
7
+ export { play } from './chunk-X4IFO7U7.js';
7
8
  export { createEmitter } from './chunk-GYH2JSCY.js';
8
9
  export { chain, createAnalyser, createCompressor, createFilter, createGain, createPanner, disconnectChain, getFrequencyData, getFrequencyDataByte, rampGain } from './chunk-CJJC6ASU.js';
9
10
  export { extractPeakPairs, extractPeaks, extractRMS } from './chunk-CRODJ4KS.js';
package/dist/play.cjs CHANGED
@@ -1,13 +1,13 @@
1
1
  'use strict';
2
2
 
3
- var chunkPZE6HTZR_cjs = require('./chunk-PZE6HTZR.cjs');
3
+ var chunkCTUCTTIE_cjs = require('./chunk-CTUCTTIE.cjs');
4
4
  require('./chunk-5J7S6QV3.cjs');
5
5
 
6
6
 
7
7
 
8
8
  Object.defineProperty(exports, "play", {
9
9
  enumerable: true,
10
- get: function () { return chunkPZE6HTZR_cjs.play; }
10
+ get: function () { return chunkCTUCTTIE_cjs.play; }
11
11
  });
12
12
  //# sourceMappingURL=play.cjs.map
13
13
  //# sourceMappingURL=play.cjs.map
package/dist/play.js CHANGED
@@ -1,4 +1,4 @@
1
- export { play } from './chunk-RWJ4EWJT.js';
1
+ export { play } from './chunk-X4IFO7U7.js';
2
2
  import './chunk-GYH2JSCY.js';
3
3
  //# sourceMappingURL=play.js.map
4
4
  //# sourceMappingURL=play.js.map
@@ -0,0 +1,22 @@
1
+ 'use strict';
2
+
3
+ var chunkXZBMBZA3_cjs = require('./chunk-XZBMBZA3.cjs');
4
+ require('./chunk-D5CD5KQZ.cjs');
5
+ require('./chunk-QWNV2BZ5.cjs');
6
+ require('./chunk-7S5KWTZ6.cjs');
7
+ require('./chunk-6UTN73HG.cjs');
8
+ require('./chunk-CPAT75WD.cjs');
9
+ require('./chunk-CTUCTTIE.cjs');
10
+ require('./chunk-5J7S6QV3.cjs');
11
+ require('./chunk-M5PDY5EZ.cjs');
12
+ require('./chunk-QFFQQMU4.cjs');
13
+ require('./chunk-4LNVRSTM.cjs');
14
+
15
+
16
+
17
+ Object.defineProperty(exports, "WaaPlayer", {
18
+ enumerable: true,
19
+ get: function () { return chunkXZBMBZA3_cjs.WaaPlayer; }
20
+ });
21
+ //# sourceMappingURL=player.cjs.map
22
+ //# sourceMappingURL=player.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"player.cjs"}
@@ -0,0 +1,64 @@
1
+ import { a as CreateContextOptions, L as LoadBufferOptions, B as BufferInfo, d as PlayOptions, e as Playback, E as ExtractPeaksOptions, P as PeakPair, c as FadeOptions, b as CrossfadeOptions, A as AutoFadeOptions, i as SchedulerOptions, C as ClockOptions, g as PlaybackSnapshot } from './types-DUrbEbPl.cjs';
2
+ import { Scheduler, Clock } from './scheduler.cjs';
3
+
4
+ interface WaaPlayerOptions extends CreateContextOptions {
5
+ }
6
+ declare class WaaPlayer {
7
+ readonly ctx: AudioContext;
8
+ private readonly _ownsContext;
9
+ constructor(ctxOrOptions?: AudioContext | WaaPlayerOptions);
10
+ resume(): Promise<void>;
11
+ ensureRunning(): Promise<void>;
12
+ now(): number;
13
+ load(url: string, options?: LoadBufferOptions): Promise<AudioBuffer>;
14
+ loadFromBlob(blob: Blob): Promise<AudioBuffer>;
15
+ loadAll(map: Record<string, string>): Promise<Map<string, AudioBuffer>>;
16
+ getBufferInfo(buffer: AudioBuffer): BufferInfo;
17
+ play(buffer: AudioBuffer, options?: PlayOptions): Playback;
18
+ createGain(initialValue?: number): GainNode;
19
+ createAnalyser(options?: {
20
+ fftSize?: number;
21
+ smoothingTimeConstant?: number;
22
+ }): AnalyserNode;
23
+ createFilter(options?: {
24
+ type?: BiquadFilterType;
25
+ frequency?: number;
26
+ Q?: number;
27
+ gain?: number;
28
+ }): BiquadFilterNode;
29
+ createPanner(pan?: number): StereoPannerNode;
30
+ createCompressor(options?: {
31
+ threshold?: number;
32
+ knee?: number;
33
+ ratio?: number;
34
+ attack?: number;
35
+ release?: number;
36
+ }): DynamicsCompressorNode;
37
+ rampGain(gain: GainNode, target: number, duration: number): void;
38
+ getFrequencyData(analyser: AnalyserNode): Float32Array;
39
+ getFrequencyDataByte(analyser: AnalyserNode): Uint8Array;
40
+ chain(...nodes: AudioNode[]): void;
41
+ disconnectChain(...nodes: AudioNode[]): void;
42
+ extractPeaks(buffer: AudioBuffer, options?: ExtractPeaksOptions): number[];
43
+ extractPeakPairs(buffer: AudioBuffer, options?: ExtractPeaksOptions): PeakPair[];
44
+ extractRMS(buffer: AudioBuffer, options?: ExtractPeaksOptions & {
45
+ channel?: number;
46
+ }): number[];
47
+ fadeIn(gain: GainNode, target: number, options?: FadeOptions): void;
48
+ fadeOut(gain: GainNode, options?: FadeOptions): void;
49
+ crossfade(gainA: GainNode, gainB: GainNode, options?: CrossfadeOptions): void;
50
+ autoFade(playback: Playback, gain: GainNode, options?: AutoFadeOptions): () => void;
51
+ createScheduler(options?: SchedulerOptions): Scheduler;
52
+ createClock(options?: ClockOptions): Clock;
53
+ createSineBuffer(frequency: number, duration: number): AudioBuffer;
54
+ createNoiseBuffer(duration: number): AudioBuffer;
55
+ createClickBuffer(frequency: number, duration: number): AudioBuffer;
56
+ getSnapshot(playback: Playback): PlaybackSnapshot;
57
+ subscribeSnapshot(playback: Playback, callback: () => void): () => void;
58
+ onFrame(playback: Playback, callback: (snapshot: PlaybackSnapshot) => void): () => void;
59
+ whenEnded(playback: Playback): Promise<void>;
60
+ whenPosition(playback: Playback, position: number): Promise<void>;
61
+ dispose(): void;
62
+ }
63
+
64
+ export { WaaPlayer, type WaaPlayerOptions };
@@ -0,0 +1,64 @@
1
+ import { a as CreateContextOptions, L as LoadBufferOptions, B as BufferInfo, d as PlayOptions, e as Playback, E as ExtractPeaksOptions, P as PeakPair, c as FadeOptions, b as CrossfadeOptions, A as AutoFadeOptions, i as SchedulerOptions, C as ClockOptions, g as PlaybackSnapshot } from './types-DUrbEbPl.js';
2
+ import { Scheduler, Clock } from './scheduler.js';
3
+
4
+ interface WaaPlayerOptions extends CreateContextOptions {
5
+ }
6
+ declare class WaaPlayer {
7
+ readonly ctx: AudioContext;
8
+ private readonly _ownsContext;
9
+ constructor(ctxOrOptions?: AudioContext | WaaPlayerOptions);
10
+ resume(): Promise<void>;
11
+ ensureRunning(): Promise<void>;
12
+ now(): number;
13
+ load(url: string, options?: LoadBufferOptions): Promise<AudioBuffer>;
14
+ loadFromBlob(blob: Blob): Promise<AudioBuffer>;
15
+ loadAll(map: Record<string, string>): Promise<Map<string, AudioBuffer>>;
16
+ getBufferInfo(buffer: AudioBuffer): BufferInfo;
17
+ play(buffer: AudioBuffer, options?: PlayOptions): Playback;
18
+ createGain(initialValue?: number): GainNode;
19
+ createAnalyser(options?: {
20
+ fftSize?: number;
21
+ smoothingTimeConstant?: number;
22
+ }): AnalyserNode;
23
+ createFilter(options?: {
24
+ type?: BiquadFilterType;
25
+ frequency?: number;
26
+ Q?: number;
27
+ gain?: number;
28
+ }): BiquadFilterNode;
29
+ createPanner(pan?: number): StereoPannerNode;
30
+ createCompressor(options?: {
31
+ threshold?: number;
32
+ knee?: number;
33
+ ratio?: number;
34
+ attack?: number;
35
+ release?: number;
36
+ }): DynamicsCompressorNode;
37
+ rampGain(gain: GainNode, target: number, duration: number): void;
38
+ getFrequencyData(analyser: AnalyserNode): Float32Array;
39
+ getFrequencyDataByte(analyser: AnalyserNode): Uint8Array;
40
+ chain(...nodes: AudioNode[]): void;
41
+ disconnectChain(...nodes: AudioNode[]): void;
42
+ extractPeaks(buffer: AudioBuffer, options?: ExtractPeaksOptions): number[];
43
+ extractPeakPairs(buffer: AudioBuffer, options?: ExtractPeaksOptions): PeakPair[];
44
+ extractRMS(buffer: AudioBuffer, options?: ExtractPeaksOptions & {
45
+ channel?: number;
46
+ }): number[];
47
+ fadeIn(gain: GainNode, target: number, options?: FadeOptions): void;
48
+ fadeOut(gain: GainNode, options?: FadeOptions): void;
49
+ crossfade(gainA: GainNode, gainB: GainNode, options?: CrossfadeOptions): void;
50
+ autoFade(playback: Playback, gain: GainNode, options?: AutoFadeOptions): () => void;
51
+ createScheduler(options?: SchedulerOptions): Scheduler;
52
+ createClock(options?: ClockOptions): Clock;
53
+ createSineBuffer(frequency: number, duration: number): AudioBuffer;
54
+ createNoiseBuffer(duration: number): AudioBuffer;
55
+ createClickBuffer(frequency: number, duration: number): AudioBuffer;
56
+ getSnapshot(playback: Playback): PlaybackSnapshot;
57
+ subscribeSnapshot(playback: Playback, callback: () => void): () => void;
58
+ onFrame(playback: Playback, callback: (snapshot: PlaybackSnapshot) => void): () => void;
59
+ whenEnded(playback: Playback): Promise<void>;
60
+ whenPosition(playback: Playback, position: number): Promise<void>;
61
+ dispose(): void;
62
+ }
63
+
64
+ export { WaaPlayer, type WaaPlayerOptions };
package/dist/player.js ADDED
@@ -0,0 +1,13 @@
1
+ export { WaaPlayer } from './chunk-IMNRPYBM.js';
2
+ import './chunk-2DL7CAEP.js';
3
+ import './chunk-LETS7FKB.js';
4
+ import './chunk-VKT7YCWK.js';
5
+ import './chunk-37CPPRLV.js';
6
+ import './chunk-T74FBKTY.js';
7
+ import './chunk-X4IFO7U7.js';
8
+ import './chunk-GYH2JSCY.js';
9
+ import './chunk-CJJC6ASU.js';
10
+ import './chunk-CRODJ4KS.js';
11
+ import './chunk-C2ASIYN5.js';
12
+ //# sourceMappingURL=player.js.map
13
+ //# sourceMappingURL=player.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"player.js"}
@@ -1,13 +1,13 @@
1
1
  'use strict';
2
2
 
3
- var chunkTULV7V5M_cjs = require('./chunk-TULV7V5M.cjs');
3
+ var chunkSIMLANWE_cjs = require('./chunk-SIMLANWE.cjs');
4
4
  require('./chunk-5J7S6QV3.cjs');
5
5
 
6
6
 
7
7
 
8
8
  Object.defineProperty(exports, "createStretcherEngine", {
9
9
  enumerable: true,
10
- get: function () { return chunkTULV7V5M_cjs.createStretcherEngine; }
10
+ get: function () { return chunkSIMLANWE_cjs.createStretcherEngine; }
11
11
  });
12
12
  //# sourceMappingURL=stretcher.cjs.map
13
13
  //# sourceMappingURL=stretcher.cjs.map