timed-audio-buffer-source-node-audio-worklet 1.0.17 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/build/es2019/factories/convert-to-context-frame.d.ts +4 -0
  2. package/build/es2019/factories/convert-to-context-frame.d.ts.map +1 -0
  3. package/build/es2019/factories/convert-to-context-frame.js +7 -0
  4. package/build/es2019/factories/convert-to-context-frame.js.map +1 -0
  5. package/build/es2019/factories/performance.d.ts +2 -0
  6. package/build/es2019/factories/performance.d.ts.map +1 -0
  7. package/build/es2019/factories/performance.js +2 -0
  8. package/build/es2019/factories/performance.js.map +1 -0
  9. package/build/es2019/factories/schedule-audio-buffer-source-node.d.ts +5 -0
  10. package/build/es2019/factories/schedule-audio-buffer-source-node.d.ts.map +1 -0
  11. package/build/es2019/factories/schedule-audio-buffer-source-node.js +12 -0
  12. package/build/es2019/factories/schedule-audio-buffer-source-node.js.map +1 -0
  13. package/build/es2019/factories/subscribe-to-timing-object.d.ts +5 -0
  14. package/build/es2019/factories/subscribe-to-timing-object.d.ts.map +1 -0
  15. package/build/es2019/factories/subscribe-to-timing-object.js +27 -0
  16. package/build/es2019/factories/subscribe-to-timing-object.js.map +1 -0
  17. package/build/es2019/interfaces/timed-audio-buffer-source-node-audio-worklet-node.d.ts +2 -0
  18. package/build/es2019/interfaces/timed-audio-buffer-source-node-audio-worklet-node.d.ts.map +1 -1
  19. package/build/es2019/module.d.ts +2 -2
  20. package/build/es2019/module.d.ts.map +1 -1
  21. package/build/es2019/module.js +30 -5
  22. package/build/es2019/module.js.map +1 -1
  23. package/build/es2019/types/native-timed-audio-buffer-source-node-audio-worklet-node.d.ts +4 -1
  24. package/build/es2019/types/native-timed-audio-buffer-source-node-audio-worklet-node.d.ts.map +1 -1
  25. package/build/es2019/worklet/worklet.d.ts +1 -1
  26. package/build/es2019/worklet/worklet.d.ts.map +1 -1
  27. package/build/es2019/worklet/worklet.js +1 -1
  28. package/build/es2019/worklet/worklet.js.map +1 -1
  29. package/build/es5/bundle.js +100 -9
  30. package/package.json +2 -2
  31. package/src/factories/convert-to-context-frame.ts +11 -0
  32. package/src/factories/performance.ts +2 -0
  33. package/src/factories/schedule-audio-buffer-source-node.ts +36 -0
  34. package/src/factories/subscribe-to-timing-object.ts +49 -0
  35. package/src/interfaces/timed-audio-buffer-source-node-audio-worklet-node.ts +4 -1
  36. package/src/module.ts +39 -4
  37. package/src/types/native-timed-audio-buffer-source-node-audio-worklet-node.ts +4 -1
  38. package/src/worklet/worklet.ts +1 -1
@@ -0,0 +1,4 @@
1
+ import { TContext, TNativeContext } from 'standardized-audio-context';
2
+ import type { createPerformance } from './performance';
3
+ export declare const createConvertToContextFrame: (performance: ReturnType<typeof createPerformance>) => (context: TContext | TNativeContext, timestamp: number) => number;
4
+ //# sourceMappingURL=convert-to-context-frame.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"convert-to-context-frame.d.ts","sourceRoot":"","sources":["../../../src/factories/convert-to-context-frame.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEvD,eAAO,MAAM,2BAA2B,gBACtB,WAAW,wBAAwB,CAAC,eAAe,QAAQ,GAAG,cAAc,aAAa,MAAM,WAM5G,CAAC"}
@@ -0,0 +1,7 @@
1
+ export const createConvertToContextFrame = (performance) => (context, timestamp) => {
2
+ if (performance === null) {
3
+ throw new Error('Performance is not available.');
4
+ }
5
+ return Math.round((context.currentTime - performance.now() / 1000 + timestamp) * context.sampleRate);
6
+ };
7
+ //# sourceMappingURL=convert-to-context-frame.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"convert-to-context-frame.js","sourceRoot":"","sources":["../../../src/factories/convert-to-context-frame.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,2BAA2B,GACpC,CAAC,WAAiD,EAAE,EAAE,CAAC,CAAC,OAAkC,EAAE,SAAiB,EAAE,EAAE;IAC7G,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACrD,CAAC;IAED,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,WAAW,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,IAAI,GAAG,SAAS,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AACzG,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const createPerformance: () => Performance | null;
2
+ //# sourceMappingURL=performance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"performance.d.ts","sourceRoot":"","sources":["../../../src/factories/performance.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,0BACkF,CAAC"}
@@ -0,0 +1,2 @@
1
+ export const createPerformance = () => typeof window === 'undefined' ? null : typeof window.performance === 'undefined' ? null : window.performance;
2
+ //# sourceMappingURL=performance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"performance.js","sourceRoot":"","sources":["../../../src/factories/performance.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,EAAE,CAClC,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,MAAM,CAAC,WAAW,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { IAudioBufferSourceNode, IAudioWorkletNode, TContext, TNativeAudioBufferSourceNode, TNativeAudioWorkletNode, TNativeContext } from 'standardized-audio-context';
2
+ import { ITimingObject } from 'timing-object';
3
+ import type { createConvertToContextFrame } from './convert-to-context-frame';
4
+ export declare const createScheduleAudioBufferSourceNode: (convertToContextFrame: ReturnType<typeof createConvertToContextFrame>) => <T extends TContext | TNativeContext>(audioWorkletNode: T extends TContext ? IAudioWorkletNode<T> : AudioWorkletNode, context: T, createAudioBufferSourceNode: T extends TContext ? (context: TContext) => IAudioBufferSourceNode<TContext> : (context: TNativeContext) => TNativeAudioBufferSourceNode, timingObject: ITimingObject) => Promise<void>;
5
+ //# sourceMappingURL=schedule-audio-buffer-source-node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedule-audio-buffer-source-node.d.ts","sourceRoot":"","sources":["../../../src/factories/schedule-audio-buffer-source-node.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,sBAAsB,EACtB,iBAAiB,EACjB,QAAQ,EACR,4BAA4B,EAC5B,uBAAuB,EACvB,cAAc,EACjB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AAE9E,eAAO,MAAM,mCAAmC,0BACpB,WAAW,kCAAkC,CAAC,mMAKlD,QAAQ,KAAK,uBAAuB,QAAQ,CAAC,aAC7C,cAAc,KAAK,4BAA4B,gBACjD,aAAa,KAC5B,QAAQ,IAAI,CAed,CAAC"}
@@ -0,0 +1,12 @@
1
+ export const createScheduleAudioBufferSourceNode = (convertToContextFrame) => (audioWorkletNode, context, createAudioBufferSourceNode, timingObject) => {
2
+ const audioBuffer = new AudioBuffer({ length: 3, sampleRate: context.sampleRate });
3
+ const audioBufferSourceNode = createAudioBufferSourceNode(context);
4
+ const { position, timestamp, velocity } = timingObject.query();
5
+ audioBuffer.copyToChannel(new Float32Array([position, convertToContextFrame(context, timestamp), velocity]), 0);
6
+ audioBufferSourceNode.buffer = audioBuffer;
7
+ const promise = new Promise((resolve) => audioBufferSourceNode.addEventListener('ended', () => resolve(), { once: true }));
8
+ audioBufferSourceNode.connect(audioWorkletNode);
9
+ audioBufferSourceNode.start();
10
+ return promise;
11
+ };
12
+ //# sourceMappingURL=schedule-audio-buffer-source-node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedule-audio-buffer-source-node.js","sourceRoot":"","sources":["../../../src/factories/schedule-audio-buffer-source-node.ts"],"names":[],"mappings":"AAWA,MAAM,CAAC,MAAM,mCAAmC,GAC5C,CAAC,qBAAqE,EAAE,EAAE,CAC1E,CACI,gBAAqF,EACrF,OAAU,EACV,2BAE+D,EAC/D,YAA2B,EACd,EAAE;IACf,MAAM,WAAW,GAAG,IAAI,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IACnF,MAAM,qBAAqB,GAAG,2BAA2B,CAAM,OAAO,CAAC,CAAC;IACxE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,YAAY,CAAC,KAAK,EAAE,CAAC;IAE/D,WAAW,CAAC,aAAa,CAAC,IAAI,YAAY,CAAC,CAAC,QAAQ,EAAE,qBAAqB,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAEhH,qBAAqB,CAAC,MAAM,GAAG,WAAW,CAAC;IAE3C,MAAM,OAAO,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,qBAAqB,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAEjI,qBAAqB,CAAC,OAAO,CAAM,gBAAgB,CAAC,CAAC;IACrD,qBAAqB,CAAC,KAAK,EAAE,CAAC;IAE9B,OAAO,OAAO,CAAC;AACnB,CAAC,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { IAudioBufferSourceNode, IAudioWorkletNode, TContext, TNativeAudioBufferSourceNode, TNativeAudioWorkletNode, TNativeContext } from 'standardized-audio-context';
2
+ import { ITimingObject } from 'timing-object';
3
+ import type { createScheduleAudioBufferSourceNode } from './schedule-audio-buffer-source-node';
4
+ export declare const createSubscribeToTimingObject: (scheduleAudioBufferSourceNode: ReturnType<typeof createScheduleAudioBufferSourceNode>) => <T extends TContext | TNativeContext>(audioWorkletNode: T extends TContext ? IAudioWorkletNode<T> : AudioWorkletNode, context: T, createAudioBufferSourceNode: T extends TContext ? (context: TContext) => IAudioBufferSourceNode<TContext> : (context: TNativeContext) => TNativeAudioBufferSourceNode, timingObject: ITimingObject) => () => void;
5
+ //# sourceMappingURL=subscribe-to-timing-object.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscribe-to-timing-object.d.ts","sourceRoot":"","sources":["../../../src/factories/subscribe-to-timing-object.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,sBAAsB,EACtB,iBAAiB,EACjB,QAAQ,EACR,4BAA4B,EAC5B,uBAAuB,EACvB,cAAc,EACjB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAE,mCAAmC,EAAE,MAAM,qCAAqC,CAAC;AAE/F,eAAO,MAAM,6BAA6B,kCACN,WAAW,0CAA0C,CAAC,mMAKlE,QAAQ,KAAK,uBAAuB,QAAQ,CAAC,aAC7C,cAAc,KAAK,4BAA4B,gBACjD,aAAa,eA6B9B,CAAC"}
@@ -0,0 +1,27 @@
1
+ export const createSubscribeToTimingObject = (scheduleAudioBufferSourceNode) => (audioWorkletNode, context, createAudioBufferSourceNode, timingObject) => {
2
+ let hasPendingUpdate = false;
3
+ let isSendingUpdate = false;
4
+ const scheduleUpdate = () => {
5
+ hasPendingUpdate = false;
6
+ scheduleAudioBufferSourceNode(audioWorkletNode, context, createAudioBufferSourceNode, timingObject).then(() => {
7
+ if (hasPendingUpdate) {
8
+ scheduleUpdate();
9
+ }
10
+ else {
11
+ isSendingUpdate = false;
12
+ }
13
+ });
14
+ };
15
+ const listener = () => {
16
+ if (isSendingUpdate) {
17
+ hasPendingUpdate = true;
18
+ }
19
+ else {
20
+ isSendingUpdate = true;
21
+ scheduleUpdate();
22
+ }
23
+ };
24
+ timingObject.addEventListener('change', listener);
25
+ return () => timingObject.removeEventListener('change', listener);
26
+ };
27
+ //# sourceMappingURL=subscribe-to-timing-object.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscribe-to-timing-object.js","sourceRoot":"","sources":["../../../src/factories/subscribe-to-timing-object.ts"],"names":[],"mappings":"AAWA,MAAM,CAAC,MAAM,6BAA6B,GACtC,CAAC,6BAAqF,EAAE,EAAE,CAC1F,CACI,gBAAqF,EACrF,OAAU,EACV,2BAE+D,EAC/D,YAA2B,EAC7B,EAAE;IACA,IAAI,gBAAgB,GAAG,KAAK,CAAC;IAC7B,IAAI,eAAe,GAAG,KAAK,CAAC;IAE5B,MAAM,cAAc,GAAG,GAAG,EAAE;QACxB,gBAAgB,GAAG,KAAK,CAAC;QAEzB,6BAA6B,CAAC,gBAAgB,EAAE,OAAO,EAAE,2BAA2B,EAAE,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE;YAC1G,IAAI,gBAAgB,EAAE,CAAC;gBACnB,cAAc,EAAE,CAAC;YACrB,CAAC;iBAAM,CAAC;gBACJ,eAAe,GAAG,KAAK,CAAC;YAC5B,CAAC;QACL,CAAC,CAAC,CAAC;IACP,CAAC,CAAC;IACF,MAAM,QAAQ,GAAG,GAAG,EAAE;QAClB,IAAI,eAAe,EAAE,CAAC;YAClB,gBAAgB,GAAG,IAAI,CAAC;QAC5B,CAAC;aAAM,CAAC;YACJ,eAAe,GAAG,IAAI,CAAC;YAEvB,cAAc,EAAE,CAAC;QACrB,CAAC;IACL,CAAC,CAAC;IAEF,YAAY,CAAC,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAElD,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;AACtE,CAAC,CAAC"}
@@ -1,4 +1,6 @@
1
1
  import { IAudioWorkletNode, TContext } from 'standardized-audio-context';
2
+ import { ITimingObject } from 'timing-object';
2
3
  export interface ITimedAudioBufferSourceNodeAudioWorkletNode<T extends TContext> extends IAudioWorkletNode<T> {
4
+ timingObject: null | ITimingObject;
3
5
  }
4
6
  //# sourceMappingURL=timed-audio-buffer-source-node-audio-worklet-node.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"timed-audio-buffer-source-node-audio-worklet-node.d.ts","sourceRoot":"","sources":["../../../src/interfaces/timed-audio-buffer-source-node-audio-worklet-node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAEzE,MAAM,WAAW,2CAA2C,CAAC,CAAC,SAAS,QAAQ,CAAE,SAAQ,iBAAiB,CAAC,CAAC,CAAC;CAAG"}
1
+ {"version":3,"file":"timed-audio-buffer-source-node-audio-worklet-node.d.ts","sourceRoot":"","sources":["../../../src/interfaces/timed-audio-buffer-source-node-audio-worklet-node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,MAAM,WAAW,2CAA2C,CAAC,CAAC,SAAS,QAAQ,CAAE,SAAQ,iBAAiB,CAAC,CAAC,CAAC;IACzG,YAAY,EAAE,IAAI,GAAG,aAAa,CAAC;CACtC"}
@@ -1,8 +1,8 @@
1
- import { TAudioWorkletNodeConstructor, TContext, TNativeAudioWorkletNodeConstructor, TNativeContext } from 'standardized-audio-context';
1
+ import { IAudioBufferSourceNode, TAudioWorkletNodeConstructor, TContext, TNativeAudioBufferSourceNode, TNativeAudioWorkletNodeConstructor, TNativeContext } from 'standardized-audio-context';
2
2
  import { ITimedAudioBufferSourceNodeAudioWorkletNode } from './interfaces';
3
3
  import { TAnyTimedAudioBufferSourceNodeAudioWorkletNodeOptions, TNativeTimedAudioBufferSourceNodeAudioWorkletNode } from './types';
4
4
  export * from './interfaces/index';
5
5
  export * from './types/index';
6
6
  export declare const addTimedAudioBufferSourceNodeAudioWorkletModule: (addAudioWorkletModule: (url: string) => Promise<void>) => Promise<void>;
7
- export declare function createTimedAudioBufferSourceNodeAudioWorkletNode<T extends TContext | TNativeContext>(audioWorkletNodeConstructor: T extends TContext ? TAudioWorkletNodeConstructor : TNativeAudioWorkletNodeConstructor, context: T, options?: Partial<TAnyTimedAudioBufferSourceNodeAudioWorkletNodeOptions<T>>): T extends TContext ? ITimedAudioBufferSourceNodeAudioWorkletNode<T> : TNativeTimedAudioBufferSourceNodeAudioWorkletNode;
7
+ export declare function createTimedAudioBufferSourceNodeAudioWorkletNode<T extends TContext | TNativeContext>(audioWorkletNodeConstructor: T extends TContext ? TAudioWorkletNodeConstructor : TNativeAudioWorkletNodeConstructor, context: T, createAudioBufferSourceNode: T extends TContext ? (context: TContext) => IAudioBufferSourceNode<TContext> : (context: TNativeContext) => TNativeAudioBufferSourceNode, options?: Partial<TAnyTimedAudioBufferSourceNodeAudioWorkletNodeOptions<T>>): T extends TContext ? ITimedAudioBufferSourceNodeAudioWorkletNode<T> : TNativeTimedAudioBufferSourceNodeAudioWorkletNode;
8
8
  //# sourceMappingURL=module.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../src/module.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,4BAA4B,EAC5B,QAAQ,EAER,kCAAkC,EAClC,cAAc,EACjB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,2CAA2C,EAAE,MAAM,cAAc,CAAC;AAC3E,OAAO,EAAE,qDAAqD,EAAE,iDAAiD,EAAE,MAAM,SAAS,CAAC;AAOnI,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAI9B,eAAO,MAAM,+CAA+C,gCAAuC,MAAM,KAAK,QAAQ,IAAI,CAAC,kBAQ1H,CAAC;AAEF,wBAAgB,gDAAgD,CAAC,CAAC,SAAS,QAAQ,GAAG,cAAc,EAChG,2BAA2B,EAAE,CAAC,SAAS,QAAQ,GAAG,4BAA4B,GAAG,kCAAkC,EACnH,OAAO,EAAE,CAAC,EACV,OAAO,GAAE,OAAO,CAAC,qDAAqD,CAAC,CAAC,CAAC,CAAM,GAChF,CAAC,SAAS,QAAQ,GAAG,2CAA2C,CAAC,CAAC,CAAC,GAAG,iDAAiD,CAwCzH"}
1
+ {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../src/module.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,sBAAsB,EAEtB,4BAA4B,EAC5B,QAAQ,EACR,4BAA4B,EAE5B,kCAAkC,EAClC,cAAc,EACjB,MAAM,4BAA4B,CAAC;AAKpC,OAAO,EAAE,2CAA2C,EAAE,MAAM,cAAc,CAAC;AAC3E,OAAO,EAAE,qDAAqD,EAAE,iDAAiD,EAAE,MAAM,SAAS,CAAC;AAOnI,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAI9B,eAAO,MAAM,+CAA+C,gCAAuC,MAAM,KAAK,QAAQ,IAAI,CAAC,kBAQ1H,CAAC;AAKF,wBAAgB,gDAAgD,CAAC,CAAC,SAAS,QAAQ,GAAG,cAAc,EAChG,2BAA2B,EAAE,CAAC,SAAS,QAAQ,GAAG,4BAA4B,GAAG,kCAAkC,EACnH,OAAO,EAAE,CAAC,EACV,2BAA2B,EAAE,CAAC,SAAS,QAAQ,GACzC,CAAC,OAAO,EAAE,QAAQ,KAAK,sBAAsB,CAAC,QAAQ,CAAC,GACvD,CAAC,OAAO,EAAE,cAAc,KAAK,4BAA4B,EAC/D,OAAO,GAAE,OAAO,CAAC,qDAAqD,CAAC,CAAC,CAAC,CAAM,GAChF,CAAC,SAAS,QAAQ,GAAG,2CAA2C,CAAC,CAAC,CAAC,GAAG,iDAAiD,CA+DzH"}
@@ -1,3 +1,7 @@
1
+ import { createConvertToContextFrame } from './factories/convert-to-context-frame';
2
+ import { createPerformance } from './factories/performance';
3
+ import { createScheduleAudioBufferSourceNode } from './factories/schedule-audio-buffer-source-node';
4
+ import { createSubscribeToTimingObject } from './factories/subscribe-to-timing-object';
1
5
  import { worklet } from './worklet/worklet';
2
6
  /*
3
7
  * @todo Explicitly referencing the barrel file seems to be necessary when enabling the
@@ -15,15 +19,18 @@ export const addTimedAudioBufferSourceNodeAudioWorkletModule = async (addAudioWo
15
19
  URL.revokeObjectURL(url);
16
20
  }
17
21
  };
18
- export function createTimedAudioBufferSourceNodeAudioWorkletNode(audioWorkletNodeConstructor, context, options = {}) {
22
+ const convertToContextFrame = createConvertToContextFrame(createPerformance());
23
+ const subscribeToTimingObject = createSubscribeToTimingObject(createScheduleAudioBufferSourceNode(convertToContextFrame));
24
+ export function createTimedAudioBufferSourceNodeAudioWorkletNode(audioWorkletNodeConstructor, context, createAudioBufferSourceNode, options = {}) {
19
25
  var _a, _b;
20
- const { buffer = null, timingObject = null } = options;
26
+ const { buffer = null } = options;
21
27
  if (buffer instanceof AudioBuffer && buffer.sampleRate !== context.sampleRate) {
22
28
  throw new TypeError('The AudioBuffer must have the same sampleRate as the AudioContext.');
23
29
  }
24
- const { position = 0, timestamp = 0 } = (_a = timingObject === null || timingObject === void 0 ? void 0 : timingObject.query()) !== null && _a !== void 0 ? _a : {};
30
+ let { timingObject = null } = options;
31
+ const { position = 0, timestamp = 0, velocity = 0 } = (_a = timingObject === null || timingObject === void 0 ? void 0 : timingObject.query()) !== null && _a !== void 0 ? _a : {};
25
32
  const audioWorkletNode = new audioWorkletNodeConstructor(context, 'timed-audio-buffer-source-node-audio-worklet-processor', {
26
- numberOfInputs: 0,
33
+ numberOfInputs: 1,
27
34
  numberOfOutputs: 1,
28
35
  outputChannelCount: [(_b = buffer === null || buffer === void 0 ? void 0 : buffer.numberOfChannels) !== null && _b !== void 0 ? _b : 1],
29
36
  processorOptions: {
@@ -31,16 +38,34 @@ export function createTimedAudioBufferSourceNodeAudioWorkletNode(audioWorkletNod
31
38
  ? Array.from({ length: buffer.numberOfChannels }, (_, channel) => buffer.getChannelData(channel))
32
39
  : null,
33
40
  position,
34
- timestamp
41
+ timestamp: convertToContextFrame(context, timestamp),
42
+ velocity
35
43
  }
36
44
  });
45
+ let removeListener = null;
37
46
  Object.defineProperties(audioWorkletNode, {
38
47
  port: {
39
48
  get() {
40
49
  throw new Error("The port of a TimedAudioBufferSourceNodeAudioWorkletNode can't be accessed.");
41
50
  }
51
+ },
52
+ timingObject: {
53
+ get: () => timingObject,
54
+ set: (value) => {
55
+ removeListener === null || removeListener === void 0 ? void 0 : removeListener();
56
+ removeListener = null;
57
+ if (value === null) {
58
+ timingObject = value;
59
+ }
60
+ else {
61
+ throw new TypeError('A TimingObject can only be set in the constructor.');
62
+ }
63
+ }
42
64
  }
43
65
  });
66
+ if (timingObject !== null) {
67
+ removeListener = subscribeToTimingObject(audioWorkletNode, context, createAudioBufferSourceNode, timingObject);
68
+ }
44
69
  return audioWorkletNode;
45
70
  }
46
71
  //# sourceMappingURL=module.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"module.js","sourceRoot":"","sources":["../../src/module.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAE5C;;;GAGG;AACH,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAE9B,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,uCAAuC,EAAE,CAAC,CAAC;AAEpF,MAAM,CAAC,MAAM,+CAA+C,GAAG,KAAK,EAAE,qBAAqD,EAAE,EAAE;IAC3H,MAAM,GAAG,GAAG,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IAEtC,IAAI,CAAC;QACD,MAAM,qBAAqB,CAAC,GAAG,CAAC,CAAC;IACrC,CAAC;YAAS,CAAC;QACP,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,UAAU,gDAAgD,CAC5D,2BAAmH,EACnH,OAAU,EACV,UAA6E,EAAE;;IAO/E,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,YAAY,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IAEvD,IAAI,MAAM,YAAY,WAAW,IAAI,MAAM,CAAC,UAAU,KAAK,OAAO,CAAC,UAAU,EAAE,CAAC;QAC5E,MAAM,IAAI,SAAS,CAAC,oEAAoE,CAAC,CAAC;IAC9F,CAAC;IAED,MAAM,EAAE,QAAQ,GAAG,CAAC,EAAE,SAAS,GAAG,CAAC,EAAE,GAAG,MAAA,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAE,KAAK,EAAE,mCAAI,EAAE,CAAC;IACpE,MAAM,gBAAgB,GAAyB,IAAU,2BAA4B,CACjF,OAAO,EACP,wDAAwD,EACxD;QACI,cAAc,EAAE,CAAC;QACjB,eAAe,EAAE,CAAC;QAClB,kBAAkB,EAAE,CAAC,MAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,gBAAgB,mCAAI,CAAC,CAAC;QACnD,gBAAgB,EAAE;YACd,MAAM,EACF,MAAM,YAAY,WAAW;gBACzB,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;gBACjG,CAAC,CAAC,IAAI;YACd,QAAQ;YACR,SAAS;SACZ;KACJ,CACJ,CAAC;IAEF,MAAM,CAAC,gBAAgB,CAAC,gBAAgB,EAAE;QACtC,IAAI,EAAE;YACF,GAAG;gBACC,MAAM,IAAI,KAAK,CAAC,6EAA6E,CAAC,CAAC;YACnG,CAAC;SACJ;KACJ,CAAC,CAAC;IAEH,OAAuD,gBAAgB,CAAC;AAC5E,CAAC"}
1
+ {"version":3,"file":"module.js","sourceRoot":"","sources":["../../src/module.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,2BAA2B,EAAE,MAAM,sCAAsC,CAAC;AACnF,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,mCAAmC,EAAE,MAAM,+CAA+C,CAAC;AACpG,OAAO,EAAE,6BAA6B,EAAE,MAAM,wCAAwC,CAAC;AAGvF,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAE5C;;;GAGG;AACH,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAE9B,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,uCAAuC,EAAE,CAAC,CAAC;AAEpF,MAAM,CAAC,MAAM,+CAA+C,GAAG,KAAK,EAAE,qBAAqD,EAAE,EAAE;IAC3H,MAAM,GAAG,GAAG,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IAEtC,IAAI,CAAC;QACD,MAAM,qBAAqB,CAAC,GAAG,CAAC,CAAC;IACrC,CAAC;YAAS,CAAC;QACP,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,qBAAqB,GAAG,2BAA2B,CAAC,iBAAiB,EAAE,CAAC,CAAC;AAC/E,MAAM,uBAAuB,GAAG,6BAA6B,CAAC,mCAAmC,CAAC,qBAAqB,CAAC,CAAC,CAAC;AAE1H,MAAM,UAAU,gDAAgD,CAC5D,2BAAmH,EACnH,OAAU,EACV,2BAE+D,EAC/D,UAA6E,EAAE;;IAO/E,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IAElC,IAAI,MAAM,YAAY,WAAW,IAAI,MAAM,CAAC,UAAU,KAAK,OAAO,CAAC,UAAU,EAAE,CAAC;QAC5E,MAAM,IAAI,SAAS,CAAC,oEAAoE,CAAC,CAAC;IAC9F,CAAC;IAED,IAAI,EAAE,YAAY,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IAEtC,MAAM,EAAE,QAAQ,GAAG,CAAC,EAAE,SAAS,GAAG,CAAC,EAAE,QAAQ,GAAG,CAAC,EAAE,GAAG,MAAA,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAE,KAAK,EAAE,mCAAI,EAAE,CAAC;IAClF,MAAM,gBAAgB,GAAyB,IAAU,2BAA4B,CACjF,OAAO,EACP,wDAAwD,EACxD;QACI,cAAc,EAAE,CAAC;QACjB,eAAe,EAAE,CAAC;QAClB,kBAAkB,EAAE,CAAC,MAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,gBAAgB,mCAAI,CAAC,CAAC;QACnD,gBAAgB,EAAE;YACd,MAAM,EACF,MAAM,YAAY,WAAW;gBACzB,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;gBACjG,CAAC,CAAC,IAAI;YACd,QAAQ;YACR,SAAS,EAAE,qBAAqB,CAAC,OAAO,EAAE,SAAS,CAAC;YACpD,QAAQ;SACX;KACJ,CACJ,CAAC;IAEF,IAAI,cAAc,GAAwB,IAAI,CAAC;IAE/C,MAAM,CAAC,gBAAgB,CAAC,gBAAgB,EAAE;QACtC,IAAI,EAAE;YACF,GAAG;gBACC,MAAM,IAAI,KAAK,CAAC,6EAA6E,CAAC,CAAC;YACnG,CAAC;SACJ;QACD,YAAY,EAAE;YACV,GAAG,EAAE,GAAG,EAAE,CAAC,YAAY;YACvB,GAAG,EAAE,CAAC,KAAqE,EAAE,EAAE;gBAC3E,cAAc,aAAd,cAAc,uBAAd,cAAc,EAAI,CAAC;gBAEnB,cAAc,GAAG,IAAI,CAAC;gBAEtB,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;oBACjB,YAAY,GAAG,KAAK,CAAC;gBACzB,CAAC;qBAAM,CAAC;oBACJ,MAAM,IAAI,SAAS,CAAC,oDAAoD,CAAC,CAAC;gBAC9E,CAAC;YACL,CAAC;SACJ;KACJ,CAAC,CAAC;IAEH,IAAI,YAAY,KAAK,IAAI,EAAE,CAAC;QACxB,cAAc,GAAG,uBAAuB,CAAC,gBAAgB,EAAE,OAAO,EAAE,2BAA2B,EAAE,YAAY,CAAC,CAAC;IACnH,CAAC;IAED,OAAuD,gBAAgB,CAAC;AAC5E,CAAC"}
@@ -1,3 +1,6 @@
1
1
  import { TNativeAudioWorkletNode } from 'standardized-audio-context';
2
- export type TNativeTimedAudioBufferSourceNodeAudioWorkletNode = TNativeAudioWorkletNode;
2
+ import { ITimingObject } from 'timing-object';
3
+ export type TNativeTimedAudioBufferSourceNodeAudioWorkletNode = TNativeAudioWorkletNode & {
4
+ timingObject: null | ITimingObject;
5
+ };
3
6
  //# sourceMappingURL=native-timed-audio-buffer-source-node-audio-worklet-node.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"native-timed-audio-buffer-source-node-audio-worklet-node.d.ts","sourceRoot":"","sources":["../../../src/types/native-timed-audio-buffer-source-node-audio-worklet-node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAErE,MAAM,MAAM,iDAAiD,GAAG,uBAAuB,CAAC"}
1
+ {"version":3,"file":"native-timed-audio-buffer-source-node-audio-worklet-node.d.ts","sourceRoot":"","sources":["../../../src/types/native-timed-audio-buffer-source-node-audio-worklet-node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,MAAM,MAAM,iDAAiD,GAAG,uBAAuB,GAAG;IACtF,YAAY,EAAE,IAAI,GAAG,aAAa,CAAC;CACtC,CAAC"}
@@ -1,2 +1,2 @@
1
- export declare const worklet = "(()=>{\"use strict\";class e extends AudioWorkletProcessor{constructor(e){let{numberOfInputs:t,numberOfOutputs:r,outputChannelCount:o,processorOptions:n}=e;var s;const u=\"object\"==typeof n&&null!==n&&\"buffer\"in n?n.buffer:null;if(!(null===u||Array.isArray(u)&&u.every((e=>e instanceof Float32Array))))throw new Error(\"The buffer needs to be either null or an array with where each element is a Float32Array.\");if(0!==t)throw new Error(\"The numberOfInputs must be 0.\");if(1!==r)throw new Error(\"The numberOfOutputs must be 1.\");const i=null!==(s=null==u?void 0:u.length)&&void 0!==s?s:1;if(void 0===o||1!==o.length||i!==o[0])throw new Error(\"The outputChannelCount must match the number of channels of the buffer.\");const f=\"object\"==typeof n&&null!==n&&\"position\"in n?n.position:0;if(\"number\"!=typeof f)throw new Error('The position needs to be of type \"number\".');const l=\"object\"==typeof n&&null!==n&&\"timestamp\"in n?n.timestamp:0;if(\"number\"!=typeof l)throw new Error('The timestamp needs to be of type \"number\".');super(),this._buffer=u,this._position=f,this._timestamp=l}process(e,t){let[r]=t;if(null!==this._buffer){const e=this._buffer.length;for(let t=0;t<e;t+=1){const e=this._buffer[t],o=r[t];for(let t=0;t<128;t+=1){const r=this._position+currentFrame-this._timestamp+t;r>=0&&r<e.length&&(o[t]=e[r])}}}return!0}}e.parameterDescriptors=[],registerProcessor(\"timed-audio-buffer-source-node-audio-worklet-processor\",e)})();";
1
+ export declare const worklet = "(()=>{\"use strict\";class e extends AudioWorkletProcessor{constructor(e){let{numberOfInputs:t,numberOfOutputs:o,outputChannelCount:r,processorOptions:n}=e;var s;const i=\"object\"==typeof n&&null!==n&&\"buffer\"in n?n.buffer:null;if(!(null===i||Array.isArray(i)&&i.every((e=>e instanceof Float32Array))))throw new Error(\"The buffer needs to be either null or an array with where each element is a Float32Array.\");if(1!==t)throw new Error(\"The numberOfInputs must be 1.\");if(1!==o)throw new Error(\"The numberOfOutputs must be 1.\");const u=null!==(s=null==i?void 0:i.length)&&void 0!==s?s:1;if(void 0===r||1!==r.length||u!==r[0])throw new Error(\"The outputChannelCount must match the number of channels of the buffer.\");const l=\"object\"==typeof n&&null!==n&&\"position\"in n?n.position:0;if(\"number\"!=typeof l)throw new Error('The position needs to be of type \"number\".');const h=\"object\"==typeof n&&null!==n&&\"timestamp\"in n?n.timestamp:0;if(\"number\"!=typeof h)throw new Error('The timestamp needs to be of type \"number\".');const f=\"object\"==typeof n&&null!==n&&\"velocity\"in n?n.velocity:0;if(![0,1].includes(f))throw new Error(\"The velocity needs to be either 0 or 1.\");super(),this._buffer=i,this._position=l,this._timestamp=h,this._velocity=f}process(e,t){let[o]=e,[r]=t;if((null==o?void 0:o.length)>0){const[e]=o;e.length>1&&(this._position=Math.round(e[0]),this._timestamp=Math.round(e[1]),this._velocity=Math.round(e[2]))}if(null!==this._buffer){const e=this._buffer.length;for(let t=0;t<e;t+=1){const e=this._buffer[t],o=r[t];for(let t=0;t<128;t+=1){const r=this._position+(currentFrame-this._timestamp+t)*this._velocity;r>=0&&r<e.length&&(o[t]=e[r])}}}return!0}}e.parameterDescriptors=[],registerProcessor(\"timed-audio-buffer-source-node-audio-worklet-processor\",e)})();";
2
2
  //# sourceMappingURL=worklet.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"worklet.d.ts","sourceRoot":"","sources":["../../../src/worklet/worklet.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,OAAO,07CAA05C,CAAC"}
1
+ {"version":3,"file":"worklet.d.ts","sourceRoot":"","sources":["../../../src/worklet/worklet.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,OAAO,qxDAA+uD,CAAC"}
@@ -1,3 +1,3 @@
1
1
  // This is the minified and stringified code of the timed-audio-buffer-source-node-audio-worklet-processor package.
2
- export const worklet = `(()=>{"use strict";class e extends AudioWorkletProcessor{constructor(e){let{numberOfInputs:t,numberOfOutputs:r,outputChannelCount:o,processorOptions:n}=e;var s;const u="object"==typeof n&&null!==n&&"buffer"in n?n.buffer:null;if(!(null===u||Array.isArray(u)&&u.every((e=>e instanceof Float32Array))))throw new Error("The buffer needs to be either null or an array with where each element is a Float32Array.");if(0!==t)throw new Error("The numberOfInputs must be 0.");if(1!==r)throw new Error("The numberOfOutputs must be 1.");const i=null!==(s=null==u?void 0:u.length)&&void 0!==s?s:1;if(void 0===o||1!==o.length||i!==o[0])throw new Error("The outputChannelCount must match the number of channels of the buffer.");const f="object"==typeof n&&null!==n&&"position"in n?n.position:0;if("number"!=typeof f)throw new Error('The position needs to be of type "number".');const l="object"==typeof n&&null!==n&&"timestamp"in n?n.timestamp:0;if("number"!=typeof l)throw new Error('The timestamp needs to be of type "number".');super(),this._buffer=u,this._position=f,this._timestamp=l}process(e,t){let[r]=t;if(null!==this._buffer){const e=this._buffer.length;for(let t=0;t<e;t+=1){const e=this._buffer[t],o=r[t];for(let t=0;t<128;t+=1){const r=this._position+currentFrame-this._timestamp+t;r>=0&&r<e.length&&(o[t]=e[r])}}}return!0}}e.parameterDescriptors=[],registerProcessor("timed-audio-buffer-source-node-audio-worklet-processor",e)})();`; // tslint:disable-line:max-line-length
2
+ export const worklet = `(()=>{"use strict";class e extends AudioWorkletProcessor{constructor(e){let{numberOfInputs:t,numberOfOutputs:o,outputChannelCount:r,processorOptions:n}=e;var s;const i="object"==typeof n&&null!==n&&"buffer"in n?n.buffer:null;if(!(null===i||Array.isArray(i)&&i.every((e=>e instanceof Float32Array))))throw new Error("The buffer needs to be either null or an array with where each element is a Float32Array.");if(1!==t)throw new Error("The numberOfInputs must be 1.");if(1!==o)throw new Error("The numberOfOutputs must be 1.");const u=null!==(s=null==i?void 0:i.length)&&void 0!==s?s:1;if(void 0===r||1!==r.length||u!==r[0])throw new Error("The outputChannelCount must match the number of channels of the buffer.");const l="object"==typeof n&&null!==n&&"position"in n?n.position:0;if("number"!=typeof l)throw new Error('The position needs to be of type "number".');const h="object"==typeof n&&null!==n&&"timestamp"in n?n.timestamp:0;if("number"!=typeof h)throw new Error('The timestamp needs to be of type "number".');const f="object"==typeof n&&null!==n&&"velocity"in n?n.velocity:0;if(![0,1].includes(f))throw new Error("The velocity needs to be either 0 or 1.");super(),this._buffer=i,this._position=l,this._timestamp=h,this._velocity=f}process(e,t){let[o]=e,[r]=t;if((null==o?void 0:o.length)>0){const[e]=o;e.length>1&&(this._position=Math.round(e[0]),this._timestamp=Math.round(e[1]),this._velocity=Math.round(e[2]))}if(null!==this._buffer){const e=this._buffer.length;for(let t=0;t<e;t+=1){const e=this._buffer[t],o=r[t];for(let t=0;t<128;t+=1){const r=this._position+(currentFrame-this._timestamp+t)*this._velocity;r>=0&&r<e.length&&(o[t]=e[r])}}}return!0}}e.parameterDescriptors=[],registerProcessor("timed-audio-buffer-source-node-audio-worklet-processor",e)})();`; // tslint:disable-line:max-line-length
3
3
  //# sourceMappingURL=worklet.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"worklet.js","sourceRoot":"","sources":["../../../src/worklet/worklet.ts"],"names":[],"mappings":"AAAA,mHAAmH;AACnH,MAAM,CAAC,MAAM,OAAO,GAAG,u5CAAu5C,CAAC,CAAC,sCAAsC"}
1
+ {"version":3,"file":"worklet.js","sourceRoot":"","sources":["../../../src/worklet/worklet.ts"],"names":[],"mappings":"AAAA,mHAAmH;AACnH,MAAM,CAAC,MAAM,OAAO,GAAG,4uDAA4uD,CAAC,CAAC,sCAAsC"}
@@ -4,8 +4,76 @@
4
4
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.timedAudioBufferSourceNodeAudioWorklet = {}, global._asyncToGenerator, global._regeneratorRuntime));
5
5
  })(this, (function (exports, _asyncToGenerator, _regeneratorRuntime) { 'use strict';
6
6
 
7
+ var createConvertToContextFrame = function createConvertToContextFrame(performance) {
8
+ return function (context, timestamp) {
9
+ if (performance === null) {
10
+ throw new Error('Performance is not available.');
11
+ }
12
+ return Math.round((context.currentTime - performance.now() / 1000 + timestamp) * context.sampleRate);
13
+ };
14
+ };
15
+
16
+ var createPerformance = function createPerformance() {
17
+ return typeof window === 'undefined' ? null : typeof window.performance === 'undefined' ? null : window.performance;
18
+ };
19
+
20
+ var createScheduleAudioBufferSourceNode = function createScheduleAudioBufferSourceNode(convertToContextFrame) {
21
+ return function (audioWorkletNode, context, createAudioBufferSourceNode, timingObject) {
22
+ var audioBuffer = new AudioBuffer({
23
+ length: 3,
24
+ sampleRate: context.sampleRate
25
+ });
26
+ var audioBufferSourceNode = createAudioBufferSourceNode(context);
27
+ var _timingObject$query = timingObject.query(),
28
+ position = _timingObject$query.position,
29
+ timestamp = _timingObject$query.timestamp,
30
+ velocity = _timingObject$query.velocity;
31
+ audioBuffer.copyToChannel(new Float32Array([position, convertToContextFrame(context, timestamp), velocity]), 0);
32
+ audioBufferSourceNode.buffer = audioBuffer;
33
+ var promise = new Promise(function (resolve) {
34
+ return audioBufferSourceNode.addEventListener('ended', function () {
35
+ return resolve();
36
+ }, {
37
+ once: true
38
+ });
39
+ });
40
+ audioBufferSourceNode.connect(audioWorkletNode);
41
+ audioBufferSourceNode.start();
42
+ return promise;
43
+ };
44
+ };
45
+
46
+ var createSubscribeToTimingObject = function createSubscribeToTimingObject(scheduleAudioBufferSourceNode) {
47
+ return function (audioWorkletNode, context, createAudioBufferSourceNode, timingObject) {
48
+ var hasPendingUpdate = false;
49
+ var isSendingUpdate = false;
50
+ var scheduleUpdate = function scheduleUpdate() {
51
+ hasPendingUpdate = false;
52
+ scheduleAudioBufferSourceNode(audioWorkletNode, context, createAudioBufferSourceNode, timingObject).then(function () {
53
+ if (hasPendingUpdate) {
54
+ scheduleUpdate();
55
+ } else {
56
+ isSendingUpdate = false;
57
+ }
58
+ });
59
+ };
60
+ var listener = function listener() {
61
+ if (isSendingUpdate) {
62
+ hasPendingUpdate = true;
63
+ } else {
64
+ isSendingUpdate = true;
65
+ scheduleUpdate();
66
+ }
67
+ };
68
+ timingObject.addEventListener('change', listener);
69
+ return function () {
70
+ return timingObject.removeEventListener('change', listener);
71
+ };
72
+ };
73
+ };
74
+
7
75
  // This is the minified and stringified code of the timed-audio-buffer-source-node-audio-worklet-processor package.
8
- var worklet = "(()=>{var e={31:function(e,t,r){!function(e,t,r,o,n,u,s,p){\"use strict\";function i(e){var t=f();return function(){var r,o=s(e);if(t){var n=s(this).constructor;r=Reflect.construct(o,arguments,n)}else r=o.apply(this,arguments);return u(this,r)}}function f(){if(\"undefined\"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if(\"function\"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(e){return!1}}var l=function(u){n(p,u);var s=i(p);function p(e){var o,n,u=e.numberOfInputs,i=e.numberOfOutputs,f=e.outputChannelCount,l=e.processorOptions;r(this,p);var a=\"object\"===t(l)&&null!==l&&\"buffer\"in l?l.buffer:null;if(!(null===a||Array.isArray(a)&&a.every((function(e){return e instanceof Float32Array}))))throw new Error(\"The buffer needs to be either null or an array with where each element is a Float32Array.\");if(0!==u)throw new Error(\"The numberOfInputs must be 0.\");if(1!==i)throw new Error(\"The numberOfOutputs must be 1.\");var c=null!==(n=null==a?void 0:a.length)&&void 0!==n?n:1;if(void 0===f||1!==f.length||c!==f[0])throw new Error(\"The outputChannelCount must match the number of channels of the buffer.\");var x=\"object\"===t(l)&&null!==l&&\"position\"in l?l.position:0;if(\"number\"!=typeof x)throw new Error('The position needs to be of type \"number\".');var d=\"object\"===t(l)&&null!==l&&\"timestamp\"in l?l.timestamp:0;if(\"number\"!=typeof d)throw new Error('The timestamp needs to be of type \"number\".');return(o=s.call(this))._buffer=a,o._position=x,o._timestamp=d,o}return o(p,[{key:\"process\",value:function(t,r){var o=e(r,1)[0];if(null!==this._buffer)for(var n=this._buffer.length,u=0;u<n;u+=1)for(var s=this._buffer[u],p=o[u],i=0;i<128;i+=1){var f=this._position+currentFrame-this._timestamp+i;f>=0&&f<s.length&&(p[i]=s[f])}return!0}}]),p}(p(AudioWorkletProcessor));l.parameterDescriptors=[],registerProcessor(\"timed-audio-buffer-source-node-audio-worklet-processor\",l)}(r(424),r(698),r(690),r(728),r(655),r(993),r(808),r(496))},897:e=>{e.exports=function(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,o=new Array(t);r<t;r++)o[r]=e[r];return o},e.exports.__esModule=!0,e.exports.default=e.exports},372:e=>{e.exports=function(e){if(Array.isArray(e))return e},e.exports.__esModule=!0,e.exports.default=e.exports},115:e=>{e.exports=function(e){if(void 0===e)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return e},e.exports.__esModule=!0,e.exports.default=e.exports},690:e=>{e.exports=function(e,t){if(!(e instanceof t))throw new TypeError(\"Cannot call a class as a function\")},e.exports.__esModule=!0,e.exports.default=e.exports},515:(e,t,r)=>{var o=r(15),n=r(617);function u(t,r,s){return n()?(e.exports=u=Reflect.construct.bind(),e.exports.__esModule=!0,e.exports.default=e.exports):(e.exports=u=function(e,t,r){var n=[null];n.push.apply(n,t);var u=new(Function.bind.apply(e,n));return r&&o(u,r.prototype),u},e.exports.__esModule=!0,e.exports.default=e.exports),u.apply(null,arguments)}e.exports=u,e.exports.__esModule=!0,e.exports.default=e.exports},728:(e,t,r)=>{var o=r(62);function n(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(e,o(n.key),n)}}e.exports=function(e,t,r){return t&&n(e.prototype,t),r&&n(e,r),Object.defineProperty(e,\"prototype\",{writable:!1}),e},e.exports.__esModule=!0,e.exports.default=e.exports},808:e=>{function t(r){return e.exports=t=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(e){return e.__proto__||Object.getPrototypeOf(e)},e.exports.__esModule=!0,e.exports.default=e.exports,t(r)}e.exports=t,e.exports.__esModule=!0,e.exports.default=e.exports},655:(e,t,r)=>{var o=r(15);e.exports=function(e,t){if(\"function\"!=typeof t&&null!==t)throw new TypeError(\"Super expression must either be null or a function\");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),Object.defineProperty(e,\"prototype\",{writable:!1}),t&&o(e,t)},e.exports.__esModule=!0,e.exports.default=e.exports},35:e=>{e.exports=function(e){try{return-1!==Function.toString.call(e).indexOf(\"[native code]\")}catch(t){return\"function\"==typeof e}},e.exports.__esModule=!0,e.exports.default=e.exports},617:e=>{e.exports=function(){if(\"undefined\"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if(\"function\"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(e){return!1}},e.exports.__esModule=!0,e.exports.default=e.exports},872:e=>{e.exports=function(e,t){var r=null==e?null:\"undefined\"!=typeof Symbol&&e[Symbol.iterator]||e[\"@@iterator\"];if(null!=r){var o,n,u,s,p=[],i=!0,f=!1;try{if(u=(r=r.call(e)).next,0===t){if(Object(r)!==r)return;i=!1}else for(;!(i=(o=u.call(r)).done)&&(p.push(o.value),p.length!==t);i=!0);}catch(e){f=!0,n=e}finally{try{if(!i&&null!=r.return&&(s=r.return(),Object(s)!==s))return}finally{if(f)throw n}}return p}},e.exports.__esModule=!0,e.exports.default=e.exports},218:e=>{e.exports=function(){throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\")},e.exports.__esModule=!0,e.exports.default=e.exports},993:(e,t,r)=>{var o=r(698).default,n=r(115);e.exports=function(e,t){if(t&&(\"object\"===o(t)||\"function\"==typeof t))return t;if(void 0!==t)throw new TypeError(\"Derived constructors may only return object or undefined\");return n(e)},e.exports.__esModule=!0,e.exports.default=e.exports},15:e=>{function t(r,o){return e.exports=t=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},e.exports.__esModule=!0,e.exports.default=e.exports,t(r,o)}e.exports=t,e.exports.__esModule=!0,e.exports.default=e.exports},424:(e,t,r)=>{var o=r(372),n=r(872),u=r(116),s=r(218);e.exports=function(e,t){return o(e)||n(e,t)||u(e,t)||s()},e.exports.__esModule=!0,e.exports.default=e.exports},36:(e,t,r)=>{var o=r(698).default;e.exports=function(e,t){if(\"object\"!=o(e)||!e)return e;var r=e[Symbol.toPrimitive];if(void 0!==r){var n=r.call(e,t||\"default\");if(\"object\"!=o(n))return n;throw new TypeError(\"@@toPrimitive must return a primitive value.\")}return(\"string\"===t?String:Number)(e)},e.exports.__esModule=!0,e.exports.default=e.exports},62:(e,t,r)=>{var o=r(698).default,n=r(36);e.exports=function(e){var t=n(e,\"string\");return\"symbol\"==o(t)?t:String(t)},e.exports.__esModule=!0,e.exports.default=e.exports},698:e=>{function t(r){return e.exports=t=\"function\"==typeof Symbol&&\"symbol\"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&\"function\"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?\"symbol\":typeof e},e.exports.__esModule=!0,e.exports.default=e.exports,t(r)}e.exports=t,e.exports.__esModule=!0,e.exports.default=e.exports},116:(e,t,r)=>{var o=r(897);e.exports=function(e,t){if(e){if(\"string\"==typeof e)return o(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);return\"Object\"===r&&e.constructor&&(r=e.constructor.name),\"Map\"===r||\"Set\"===r?Array.from(e):\"Arguments\"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?o(e,t):void 0}},e.exports.__esModule=!0,e.exports.default=e.exports},496:(e,t,r)=>{var o=r(808),n=r(15),u=r(35),s=r(515);function p(t){var r=\"function\"==typeof Map?new Map:void 0;return e.exports=p=function(e){if(null===e||!u(e))return e;if(\"function\"!=typeof e)throw new TypeError(\"Super expression must either be null or a function\");if(void 0!==r){if(r.has(e))return r.get(e);r.set(e,t)}function t(){return s(e,arguments,o(this).constructor)}return t.prototype=Object.create(e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),n(t,e)},e.exports.__esModule=!0,e.exports.default=e.exports,p(t)}e.exports=p,e.exports.__esModule=!0,e.exports.default=e.exports}},t={};function r(o){var n=t[o];if(void 0!==n)return n.exports;var u=t[o]={exports:{}};return e[o].call(u.exports,u,u.exports,r),u.exports}r.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return r.d(t,{a:t}),t},r.d=(e,t)=>{for(var o in t)r.o(t,o)&&!r.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:t[o]})},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{\"use strict\";r(31)})()})();"; // tslint:disable-line:max-line-length
76
+ var worklet = "(()=>{var e={31:function(e,t,r){!function(e,t,r,o,n,u,s,i){\"use strict\";function p(e){var t=l();return function(){var r,o=s(e);if(t){var n=s(this).constructor;r=Reflect.construct(o,arguments,n)}else r=o.apply(this,arguments);return u(this,r)}}function l(){if(\"undefined\"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if(\"function\"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(e){return!1}}var f=function(u){n(i,u);var s=p(i);function i(e){var o,n,u=e.numberOfInputs,p=e.numberOfOutputs,l=e.outputChannelCount,f=e.processorOptions;r(this,i);var a=\"object\"===t(f)&&null!==f&&\"buffer\"in f?f.buffer:null;if(!(null===a||Array.isArray(a)&&a.every((function(e){return e instanceof Float32Array}))))throw new Error(\"The buffer needs to be either null or an array with where each element is a Float32Array.\");if(1!==u)throw new Error(\"The numberOfInputs must be 1.\");if(1!==p)throw new Error(\"The numberOfOutputs must be 1.\");var c=null!==(n=null==a?void 0:a.length)&&void 0!==n?n:1;if(void 0===l||1!==l.length||c!==l[0])throw new Error(\"The outputChannelCount must match the number of channels of the buffer.\");var x=\"object\"===t(f)&&null!==f&&\"position\"in f?f.position:0;if(\"number\"!=typeof x)throw new Error('The position needs to be of type \"number\".');var d=\"object\"===t(f)&&null!==f&&\"timestamp\"in f?f.timestamp:0;if(\"number\"!=typeof d)throw new Error('The timestamp needs to be of type \"number\".');var y=\"object\"===t(f)&&null!==f&&\"velocity\"in f?f.velocity:0;if(![0,1].includes(y))throw new Error(\"The velocity needs to be either 0 or 1.\");return(o=s.call(this))._buffer=a,o._position=x,o._timestamp=d,o._velocity=y,o}return o(i,[{key:\"process\",value:function(t,r){var o=e(t,1)[0],n=e(r,1)[0];if((null==o?void 0:o.length)>0){var u=e(o,1)[0];u.length>1&&(this._position=Math.round(u[0]),this._timestamp=Math.round(u[1]),this._velocity=Math.round(u[2]))}if(null!==this._buffer)for(var s=this._buffer.length,i=0;i<s;i+=1)for(var p=this._buffer[i],l=n[i],f=0;f<128;f+=1){var a=this._position+(currentFrame-this._timestamp+f)*this._velocity;a>=0&&a<p.length&&(l[f]=p[a])}return!0}}]),i}(i(AudioWorkletProcessor));f.parameterDescriptors=[],registerProcessor(\"timed-audio-buffer-source-node-audio-worklet-processor\",f)}(r(424),r(698),r(690),r(728),r(655),r(993),r(808),r(496))},897:e=>{e.exports=function(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,o=new Array(t);r<t;r++)o[r]=e[r];return o},e.exports.__esModule=!0,e.exports.default=e.exports},372:e=>{e.exports=function(e){if(Array.isArray(e))return e},e.exports.__esModule=!0,e.exports.default=e.exports},115:e=>{e.exports=function(e){if(void 0===e)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return e},e.exports.__esModule=!0,e.exports.default=e.exports},690:e=>{e.exports=function(e,t){if(!(e instanceof t))throw new TypeError(\"Cannot call a class as a function\")},e.exports.__esModule=!0,e.exports.default=e.exports},515:(e,t,r)=>{var o=r(15),n=r(617);function u(t,r,s){return n()?(e.exports=u=Reflect.construct.bind(),e.exports.__esModule=!0,e.exports.default=e.exports):(e.exports=u=function(e,t,r){var n=[null];n.push.apply(n,t);var u=new(Function.bind.apply(e,n));return r&&o(u,r.prototype),u},e.exports.__esModule=!0,e.exports.default=e.exports),u.apply(null,arguments)}e.exports=u,e.exports.__esModule=!0,e.exports.default=e.exports},728:(e,t,r)=>{var o=r(62);function n(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(e,o(n.key),n)}}e.exports=function(e,t,r){return t&&n(e.prototype,t),r&&n(e,r),Object.defineProperty(e,\"prototype\",{writable:!1}),e},e.exports.__esModule=!0,e.exports.default=e.exports},808:e=>{function t(r){return e.exports=t=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(e){return e.__proto__||Object.getPrototypeOf(e)},e.exports.__esModule=!0,e.exports.default=e.exports,t(r)}e.exports=t,e.exports.__esModule=!0,e.exports.default=e.exports},655:(e,t,r)=>{var o=r(15);e.exports=function(e,t){if(\"function\"!=typeof t&&null!==t)throw new TypeError(\"Super expression must either be null or a function\");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),Object.defineProperty(e,\"prototype\",{writable:!1}),t&&o(e,t)},e.exports.__esModule=!0,e.exports.default=e.exports},35:e=>{e.exports=function(e){try{return-1!==Function.toString.call(e).indexOf(\"[native code]\")}catch(t){return\"function\"==typeof e}},e.exports.__esModule=!0,e.exports.default=e.exports},617:e=>{e.exports=function(){if(\"undefined\"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if(\"function\"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(e){return!1}},e.exports.__esModule=!0,e.exports.default=e.exports},872:e=>{e.exports=function(e,t){var r=null==e?null:\"undefined\"!=typeof Symbol&&e[Symbol.iterator]||e[\"@@iterator\"];if(null!=r){var o,n,u,s,i=[],p=!0,l=!1;try{if(u=(r=r.call(e)).next,0===t){if(Object(r)!==r)return;p=!1}else for(;!(p=(o=u.call(r)).done)&&(i.push(o.value),i.length!==t);p=!0);}catch(e){l=!0,n=e}finally{try{if(!p&&null!=r.return&&(s=r.return(),Object(s)!==s))return}finally{if(l)throw n}}return i}},e.exports.__esModule=!0,e.exports.default=e.exports},218:e=>{e.exports=function(){throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\")},e.exports.__esModule=!0,e.exports.default=e.exports},993:(e,t,r)=>{var o=r(698).default,n=r(115);e.exports=function(e,t){if(t&&(\"object\"===o(t)||\"function\"==typeof t))return t;if(void 0!==t)throw new TypeError(\"Derived constructors may only return object or undefined\");return n(e)},e.exports.__esModule=!0,e.exports.default=e.exports},15:e=>{function t(r,o){return e.exports=t=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},e.exports.__esModule=!0,e.exports.default=e.exports,t(r,o)}e.exports=t,e.exports.__esModule=!0,e.exports.default=e.exports},424:(e,t,r)=>{var o=r(372),n=r(872),u=r(116),s=r(218);e.exports=function(e,t){return o(e)||n(e,t)||u(e,t)||s()},e.exports.__esModule=!0,e.exports.default=e.exports},36:(e,t,r)=>{var o=r(698).default;e.exports=function(e,t){if(\"object\"!=o(e)||!e)return e;var r=e[Symbol.toPrimitive];if(void 0!==r){var n=r.call(e,t||\"default\");if(\"object\"!=o(n))return n;throw new TypeError(\"@@toPrimitive must return a primitive value.\")}return(\"string\"===t?String:Number)(e)},e.exports.__esModule=!0,e.exports.default=e.exports},62:(e,t,r)=>{var o=r(698).default,n=r(36);e.exports=function(e){var t=n(e,\"string\");return\"symbol\"==o(t)?t:String(t)},e.exports.__esModule=!0,e.exports.default=e.exports},698:e=>{function t(r){return e.exports=t=\"function\"==typeof Symbol&&\"symbol\"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&\"function\"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?\"symbol\":typeof e},e.exports.__esModule=!0,e.exports.default=e.exports,t(r)}e.exports=t,e.exports.__esModule=!0,e.exports.default=e.exports},116:(e,t,r)=>{var o=r(897);e.exports=function(e,t){if(e){if(\"string\"==typeof e)return o(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);return\"Object\"===r&&e.constructor&&(r=e.constructor.name),\"Map\"===r||\"Set\"===r?Array.from(e):\"Arguments\"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?o(e,t):void 0}},e.exports.__esModule=!0,e.exports.default=e.exports},496:(e,t,r)=>{var o=r(808),n=r(15),u=r(35),s=r(515);function i(t){var r=\"function\"==typeof Map?new Map:void 0;return e.exports=i=function(e){if(null===e||!u(e))return e;if(\"function\"!=typeof e)throw new TypeError(\"Super expression must either be null or a function\");if(void 0!==r){if(r.has(e))return r.get(e);r.set(e,t)}function t(){return s(e,arguments,o(this).constructor)}return t.prototype=Object.create(e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),n(t,e)},e.exports.__esModule=!0,e.exports.default=e.exports,i(t)}e.exports=i,e.exports.__esModule=!0,e.exports.default=e.exports}},t={};function r(o){var n=t[o];if(void 0!==n)return n.exports;var u=t[o]={exports:{}};return e[o].call(u.exports,u,u.exports,r),u.exports}r.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return r.d(t,{a:t}),t},r.d=(e,t)=>{for(var o in t)r.o(t,o)&&!r.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:t[o]})},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{\"use strict\";r(31)})()})();"; // tslint:disable-line:max-line-length
9
77
 
10
78
  var blob = new Blob([worklet], {
11
79
  type: 'application/javascript; charset=utf-8'
@@ -34,23 +102,27 @@
34
102
  return _ref.apply(this, arguments);
35
103
  };
36
104
  }();
37
- function createTimedAudioBufferSourceNodeAudioWorkletNode(audioWorkletNodeConstructor, context) {
38
- var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
105
+ var convertToContextFrame = createConvertToContextFrame(createPerformance());
106
+ var subscribeToTimingObject = createSubscribeToTimingObject(createScheduleAudioBufferSourceNode(convertToContextFrame));
107
+ function createTimedAudioBufferSourceNodeAudioWorkletNode(audioWorkletNodeConstructor, context, createAudioBufferSourceNode) {
108
+ var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
39
109
  var _a, _b;
40
110
  var _options$buffer = options.buffer,
41
- buffer = _options$buffer === void 0 ? null : _options$buffer,
42
- _options$timingObject = options.timingObject,
43
- timingObject = _options$timingObject === void 0 ? null : _options$timingObject;
111
+ buffer = _options$buffer === void 0 ? null : _options$buffer;
44
112
  if (buffer instanceof AudioBuffer && buffer.sampleRate !== context.sampleRate) {
45
113
  throw new TypeError('The AudioBuffer must have the same sampleRate as the AudioContext.');
46
114
  }
115
+ var _options$timingObject = options.timingObject,
116
+ timingObject = _options$timingObject === void 0 ? null : _options$timingObject;
47
117
  var _ref2 = (_a = timingObject === null || timingObject === void 0 ? void 0 : timingObject.query()) !== null && _a !== void 0 ? _a : {},
48
118
  _ref2$position = _ref2.position,
49
119
  position = _ref2$position === void 0 ? 0 : _ref2$position,
50
120
  _ref2$timestamp = _ref2.timestamp,
51
- timestamp = _ref2$timestamp === void 0 ? 0 : _ref2$timestamp;
121
+ timestamp = _ref2$timestamp === void 0 ? 0 : _ref2$timestamp,
122
+ _ref2$velocity = _ref2.velocity,
123
+ velocity = _ref2$velocity === void 0 ? 0 : _ref2$velocity;
52
124
  var audioWorkletNode = new audioWorkletNodeConstructor(context, 'timed-audio-buffer-source-node-audio-worklet-processor', {
53
- numberOfInputs: 0,
125
+ numberOfInputs: 1,
54
126
  numberOfOutputs: 1,
55
127
  outputChannelCount: [(_b = buffer === null || buffer === void 0 ? void 0 : buffer.numberOfChannels) !== null && _b !== void 0 ? _b : 1],
56
128
  processorOptions: {
@@ -60,16 +132,35 @@
60
132
  return buffer.getChannelData(channel);
61
133
  }) : null,
62
134
  position: position,
63
- timestamp: timestamp
135
+ timestamp: convertToContextFrame(context, timestamp),
136
+ velocity: velocity
64
137
  }
65
138
  });
139
+ var removeListener = null;
66
140
  Object.defineProperties(audioWorkletNode, {
67
141
  port: {
68
142
  get: function get() {
69
143
  throw new Error("The port of a TimedAudioBufferSourceNodeAudioWorkletNode can't be accessed.");
70
144
  }
145
+ },
146
+ timingObject: {
147
+ get: function get() {
148
+ return timingObject;
149
+ },
150
+ set: function set(value) {
151
+ removeListener === null || removeListener === void 0 ? void 0 : removeListener();
152
+ removeListener = null;
153
+ if (value === null) {
154
+ timingObject = value;
155
+ } else {
156
+ throw new TypeError('A TimingObject can only be set in the constructor.');
157
+ }
158
+ }
71
159
  }
72
160
  });
161
+ if (timingObject !== null) {
162
+ removeListener = subscribeToTimingObject(audioWorkletNode, context, createAudioBufferSourceNode, timingObject);
163
+ }
73
164
  return audioWorkletNode;
74
165
  }
75
166
 
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "dependencies": {
12
12
  "@babel/runtime": "^7.23.6",
13
13
  "standardized-audio-context": "^25.3.60",
14
- "timed-audio-buffer-source-node-audio-worklet-processor": "^1.0.13",
14
+ "timed-audio-buffer-source-node-audio-worklet-processor": "^2.1.0",
15
15
  "timing-object": "^3.1.70",
16
16
  "tslib": "^2.6.2"
17
17
  },
@@ -86,5 +86,5 @@
86
86
  "test": "grunt lint && grunt test"
87
87
  },
88
88
  "types": "build/es2019/module.d.ts",
89
- "version": "1.0.17"
89
+ "version": "2.1.0"
90
90
  }
@@ -0,0 +1,11 @@
1
+ import { TContext, TNativeContext } from 'standardized-audio-context';
2
+ import type { createPerformance } from './performance';
3
+
4
+ export const createConvertToContextFrame =
5
+ (performance: ReturnType<typeof createPerformance>) => (context: TContext | TNativeContext, timestamp: number) => {
6
+ if (performance === null) {
7
+ throw new Error('Performance is not available.');
8
+ }
9
+
10
+ return Math.round((context.currentTime - performance.now() / 1000 + timestamp) * context.sampleRate);
11
+ };
@@ -0,0 +1,2 @@
1
+ export const createPerformance = () =>
2
+ typeof window === 'undefined' ? null : typeof window.performance === 'undefined' ? null : window.performance;
@@ -0,0 +1,36 @@
1
+ import {
2
+ IAudioBufferSourceNode,
3
+ IAudioWorkletNode,
4
+ TContext,
5
+ TNativeAudioBufferSourceNode,
6
+ TNativeAudioWorkletNode,
7
+ TNativeContext
8
+ } from 'standardized-audio-context';
9
+ import { ITimingObject } from 'timing-object';
10
+ import type { createConvertToContextFrame } from './convert-to-context-frame';
11
+
12
+ export const createScheduleAudioBufferSourceNode =
13
+ (convertToContextFrame: ReturnType<typeof createConvertToContextFrame>) =>
14
+ <T extends TContext | TNativeContext>(
15
+ audioWorkletNode: T extends TContext ? IAudioWorkletNode<T> : TNativeAudioWorkletNode,
16
+ context: T,
17
+ createAudioBufferSourceNode: T extends TContext
18
+ ? (context: TContext) => IAudioBufferSourceNode<TContext>
19
+ : (context: TNativeContext) => TNativeAudioBufferSourceNode,
20
+ timingObject: ITimingObject
21
+ ): Promise<void> => {
22
+ const audioBuffer = new AudioBuffer({ length: 3, sampleRate: context.sampleRate });
23
+ const audioBufferSourceNode = createAudioBufferSourceNode(<any>context);
24
+ const { position, timestamp, velocity } = timingObject.query();
25
+
26
+ audioBuffer.copyToChannel(new Float32Array([position, convertToContextFrame(context, timestamp), velocity]), 0);
27
+
28
+ audioBufferSourceNode.buffer = audioBuffer;
29
+
30
+ const promise = new Promise<void>((resolve) => audioBufferSourceNode.addEventListener('ended', () => resolve(), { once: true }));
31
+
32
+ audioBufferSourceNode.connect(<any>audioWorkletNode);
33
+ audioBufferSourceNode.start();
34
+
35
+ return promise;
36
+ };
@@ -0,0 +1,49 @@
1
+ import {
2
+ IAudioBufferSourceNode,
3
+ IAudioWorkletNode,
4
+ TContext,
5
+ TNativeAudioBufferSourceNode,
6
+ TNativeAudioWorkletNode,
7
+ TNativeContext
8
+ } from 'standardized-audio-context';
9
+ import { ITimingObject } from 'timing-object';
10
+ import type { createScheduleAudioBufferSourceNode } from './schedule-audio-buffer-source-node';
11
+
12
+ export const createSubscribeToTimingObject =
13
+ (scheduleAudioBufferSourceNode: ReturnType<typeof createScheduleAudioBufferSourceNode>) =>
14
+ <T extends TContext | TNativeContext>(
15
+ audioWorkletNode: T extends TContext ? IAudioWorkletNode<T> : TNativeAudioWorkletNode,
16
+ context: T,
17
+ createAudioBufferSourceNode: T extends TContext
18
+ ? (context: TContext) => IAudioBufferSourceNode<TContext>
19
+ : (context: TNativeContext) => TNativeAudioBufferSourceNode,
20
+ timingObject: ITimingObject
21
+ ) => {
22
+ let hasPendingUpdate = false;
23
+ let isSendingUpdate = false;
24
+
25
+ const scheduleUpdate = () => {
26
+ hasPendingUpdate = false;
27
+
28
+ scheduleAudioBufferSourceNode(audioWorkletNode, context, createAudioBufferSourceNode, timingObject).then(() => {
29
+ if (hasPendingUpdate) {
30
+ scheduleUpdate();
31
+ } else {
32
+ isSendingUpdate = false;
33
+ }
34
+ });
35
+ };
36
+ const listener = () => {
37
+ if (isSendingUpdate) {
38
+ hasPendingUpdate = true;
39
+ } else {
40
+ isSendingUpdate = true;
41
+
42
+ scheduleUpdate();
43
+ }
44
+ };
45
+
46
+ timingObject.addEventListener('change', listener);
47
+
48
+ return () => timingObject.removeEventListener('change', listener);
49
+ };
@@ -1,3 +1,6 @@
1
1
  import { IAudioWorkletNode, TContext } from 'standardized-audio-context';
2
+ import { ITimingObject } from 'timing-object';
2
3
 
3
- export interface ITimedAudioBufferSourceNodeAudioWorkletNode<T extends TContext> extends IAudioWorkletNode<T> {}
4
+ export interface ITimedAudioBufferSourceNodeAudioWorkletNode<T extends TContext> extends IAudioWorkletNode<T> {
5
+ timingObject: null | ITimingObject;
6
+ }
package/src/module.ts CHANGED
@@ -1,11 +1,17 @@
1
1
  import {
2
+ IAudioBufferSourceNode,
2
3
  IAudioWorkletNode,
3
4
  TAudioWorkletNodeConstructor,
4
5
  TContext,
6
+ TNativeAudioBufferSourceNode,
5
7
  TNativeAudioWorkletNode,
6
8
  TNativeAudioWorkletNodeConstructor,
7
9
  TNativeContext
8
10
  } from 'standardized-audio-context';
11
+ import { createConvertToContextFrame } from './factories/convert-to-context-frame';
12
+ import { createPerformance } from './factories/performance';
13
+ import { createScheduleAudioBufferSourceNode } from './factories/schedule-audio-buffer-source-node';
14
+ import { createSubscribeToTimingObject } from './factories/subscribe-to-timing-object';
9
15
  import { ITimedAudioBufferSourceNodeAudioWorkletNode } from './interfaces';
10
16
  import { TAnyTimedAudioBufferSourceNodeAudioWorkletNodeOptions, TNativeTimedAudioBufferSourceNodeAudioWorkletNode } from './types';
11
17
  import { worklet } from './worklet/worklet';
@@ -29,9 +35,15 @@ export const addTimedAudioBufferSourceNodeAudioWorkletModule = async (addAudioWo
29
35
  }
30
36
  };
31
37
 
38
+ const convertToContextFrame = createConvertToContextFrame(createPerformance());
39
+ const subscribeToTimingObject = createSubscribeToTimingObject(createScheduleAudioBufferSourceNode(convertToContextFrame));
40
+
32
41
  export function createTimedAudioBufferSourceNodeAudioWorkletNode<T extends TContext | TNativeContext>(
33
42
  audioWorkletNodeConstructor: T extends TContext ? TAudioWorkletNodeConstructor : TNativeAudioWorkletNodeConstructor,
34
43
  context: T,
44
+ createAudioBufferSourceNode: T extends TContext
45
+ ? (context: TContext) => IAudioBufferSourceNode<TContext>
46
+ : (context: TNativeContext) => TNativeAudioBufferSourceNode,
35
47
  options: Partial<TAnyTimedAudioBufferSourceNodeAudioWorkletNodeOptions<T>> = {}
36
48
  ): T extends TContext ? ITimedAudioBufferSourceNodeAudioWorkletNode<T> : TNativeTimedAudioBufferSourceNodeAudioWorkletNode {
37
49
  type TAnyAudioWorkletNode = T extends TContext ? IAudioWorkletNode<T> : TNativeAudioWorkletNode;
@@ -39,18 +51,20 @@ export function createTimedAudioBufferSourceNodeAudioWorkletNode<T extends TCont
39
51
  ? ITimedAudioBufferSourceNodeAudioWorkletNode<T>
40
52
  : TNativeTimedAudioBufferSourceNodeAudioWorkletNode;
41
53
 
42
- const { buffer = null, timingObject = null } = options;
54
+ const { buffer = null } = options;
43
55
 
44
56
  if (buffer instanceof AudioBuffer && buffer.sampleRate !== context.sampleRate) {
45
57
  throw new TypeError('The AudioBuffer must have the same sampleRate as the AudioContext.');
46
58
  }
47
59
 
48
- const { position = 0, timestamp = 0 } = timingObject?.query() ?? {};
60
+ let { timingObject = null } = options;
61
+
62
+ const { position = 0, timestamp = 0, velocity = 0 } = timingObject?.query() ?? {};
49
63
  const audioWorkletNode: TAnyAudioWorkletNode = new (<any>audioWorkletNodeConstructor)(
50
64
  context,
51
65
  'timed-audio-buffer-source-node-audio-worklet-processor',
52
66
  {
53
- numberOfInputs: 0,
67
+ numberOfInputs: 1,
54
68
  numberOfOutputs: 1,
55
69
  outputChannelCount: [buffer?.numberOfChannels ?? 1],
56
70
  processorOptions: {
@@ -59,18 +73,39 @@ export function createTimedAudioBufferSourceNodeAudioWorkletNode<T extends TCont
59
73
  ? Array.from({ length: buffer.numberOfChannels }, (_, channel) => buffer.getChannelData(channel))
60
74
  : null,
61
75
  position,
62
- timestamp
76
+ timestamp: convertToContextFrame(context, timestamp),
77
+ velocity
63
78
  }
64
79
  }
65
80
  );
66
81
 
82
+ let removeListener: null | (() => void) = null;
83
+
67
84
  Object.defineProperties(audioWorkletNode, {
68
85
  port: {
69
86
  get(): TAnyTimedAudioBufferSourceNodeAudioWorkletNode['port'] {
70
87
  throw new Error("The port of a TimedAudioBufferSourceNodeAudioWorkletNode can't be accessed.");
71
88
  }
89
+ },
90
+ timingObject: {
91
+ get: () => timingObject,
92
+ set: (value: TAnyTimedAudioBufferSourceNodeAudioWorkletNode['timingObject']) => {
93
+ removeListener?.();
94
+
95
+ removeListener = null;
96
+
97
+ if (value === null) {
98
+ timingObject = value;
99
+ } else {
100
+ throw new TypeError('A TimingObject can only be set in the constructor.');
101
+ }
102
+ }
72
103
  }
73
104
  });
74
105
 
106
+ if (timingObject !== null) {
107
+ removeListener = subscribeToTimingObject(audioWorkletNode, context, createAudioBufferSourceNode, timingObject);
108
+ }
109
+
75
110
  return <TAnyTimedAudioBufferSourceNodeAudioWorkletNode>audioWorkletNode;
76
111
  }
@@ -1,3 +1,6 @@
1
1
  import { TNativeAudioWorkletNode } from 'standardized-audio-context';
2
+ import { ITimingObject } from 'timing-object';
2
3
 
3
- export type TNativeTimedAudioBufferSourceNodeAudioWorkletNode = TNativeAudioWorkletNode;
4
+ export type TNativeTimedAudioBufferSourceNodeAudioWorkletNode = TNativeAudioWorkletNode & {
5
+ timingObject: null | ITimingObject;
6
+ };
@@ -1,2 +1,2 @@
1
1
  // This is the minified and stringified code of the timed-audio-buffer-source-node-audio-worklet-processor package.
2
- export const worklet = `(()=>{"use strict";class e extends AudioWorkletProcessor{constructor(e){let{numberOfInputs:t,numberOfOutputs:r,outputChannelCount:o,processorOptions:n}=e;var s;const u="object"==typeof n&&null!==n&&"buffer"in n?n.buffer:null;if(!(null===u||Array.isArray(u)&&u.every((e=>e instanceof Float32Array))))throw new Error("The buffer needs to be either null or an array with where each element is a Float32Array.");if(0!==t)throw new Error("The numberOfInputs must be 0.");if(1!==r)throw new Error("The numberOfOutputs must be 1.");const i=null!==(s=null==u?void 0:u.length)&&void 0!==s?s:1;if(void 0===o||1!==o.length||i!==o[0])throw new Error("The outputChannelCount must match the number of channels of the buffer.");const f="object"==typeof n&&null!==n&&"position"in n?n.position:0;if("number"!=typeof f)throw new Error('The position needs to be of type "number".');const l="object"==typeof n&&null!==n&&"timestamp"in n?n.timestamp:0;if("number"!=typeof l)throw new Error('The timestamp needs to be of type "number".');super(),this._buffer=u,this._position=f,this._timestamp=l}process(e,t){let[r]=t;if(null!==this._buffer){const e=this._buffer.length;for(let t=0;t<e;t+=1){const e=this._buffer[t],o=r[t];for(let t=0;t<128;t+=1){const r=this._position+currentFrame-this._timestamp+t;r>=0&&r<e.length&&(o[t]=e[r])}}}return!0}}e.parameterDescriptors=[],registerProcessor("timed-audio-buffer-source-node-audio-worklet-processor",e)})();`; // tslint:disable-line:max-line-length
2
+ export const worklet = `(()=>{"use strict";class e extends AudioWorkletProcessor{constructor(e){let{numberOfInputs:t,numberOfOutputs:o,outputChannelCount:r,processorOptions:n}=e;var s;const i="object"==typeof n&&null!==n&&"buffer"in n?n.buffer:null;if(!(null===i||Array.isArray(i)&&i.every((e=>e instanceof Float32Array))))throw new Error("The buffer needs to be either null or an array with where each element is a Float32Array.");if(1!==t)throw new Error("The numberOfInputs must be 1.");if(1!==o)throw new Error("The numberOfOutputs must be 1.");const u=null!==(s=null==i?void 0:i.length)&&void 0!==s?s:1;if(void 0===r||1!==r.length||u!==r[0])throw new Error("The outputChannelCount must match the number of channels of the buffer.");const l="object"==typeof n&&null!==n&&"position"in n?n.position:0;if("number"!=typeof l)throw new Error('The position needs to be of type "number".');const h="object"==typeof n&&null!==n&&"timestamp"in n?n.timestamp:0;if("number"!=typeof h)throw new Error('The timestamp needs to be of type "number".');const f="object"==typeof n&&null!==n&&"velocity"in n?n.velocity:0;if(![0,1].includes(f))throw new Error("The velocity needs to be either 0 or 1.");super(),this._buffer=i,this._position=l,this._timestamp=h,this._velocity=f}process(e,t){let[o]=e,[r]=t;if((null==o?void 0:o.length)>0){const[e]=o;e.length>1&&(this._position=Math.round(e[0]),this._timestamp=Math.round(e[1]),this._velocity=Math.round(e[2]))}if(null!==this._buffer){const e=this._buffer.length;for(let t=0;t<e;t+=1){const e=this._buffer[t],o=r[t];for(let t=0;t<128;t+=1){const r=this._position+(currentFrame-this._timestamp+t)*this._velocity;r>=0&&r<e.length&&(o[t]=e[r])}}}return!0}}e.parameterDescriptors=[],registerProcessor("timed-audio-buffer-source-node-audio-worklet-processor",e)})();`; // tslint:disable-line:max-line-length