@ain1084/audio-worklet-stream 0.1.8 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/README.md +23 -40
  2. package/dist/events.d.ts +6 -6
  3. package/dist/events.js +8 -8
  4. package/dist/events.js.map +1 -1
  5. package/dist/frame-buffer/buffer-config.d.ts +67 -0
  6. package/dist/frame-buffer/buffer-config.js +64 -0
  7. package/dist/frame-buffer/buffer-config.js.map +1 -0
  8. package/dist/frame-buffer/buffer-factory.d.ts +1 -2
  9. package/dist/frame-buffer/buffer-factory.js +6 -3
  10. package/dist/frame-buffer/buffer-factory.js.map +1 -1
  11. package/dist/frame-buffer/buffer-reader.d.ts +30 -10
  12. package/dist/frame-buffer/buffer-reader.js +38 -16
  13. package/dist/frame-buffer/buffer-reader.js.map +1 -1
  14. package/dist/frame-buffer/buffer-utils.js +2 -2
  15. package/dist/frame-buffer/buffer-utils.js.map +1 -1
  16. package/dist/frame-buffer/buffer-writer.d.ts +32 -12
  17. package/dist/frame-buffer/buffer-writer.js +40 -18
  18. package/dist/frame-buffer/buffer-writer.js.map +1 -1
  19. package/dist/frame-buffer/buffer.d.ts +33 -22
  20. package/dist/frame-buffer/buffer.js +50 -40
  21. package/dist/frame-buffer/buffer.js.map +1 -1
  22. package/dist/output-message.d.ts +9 -9
  23. package/dist/output-stream-node.d.ts +13 -19
  24. package/dist/output-stream-node.js +20 -26
  25. package/dist/output-stream-node.js.map +1 -1
  26. package/dist/output-stream-processor.js +25 -18
  27. package/dist/output-stream-processor.js.map +1 -1
  28. package/dist/stream-node-factory.d.ts +10 -0
  29. package/dist/stream-node-factory.js +27 -12
  30. package/dist/stream-node-factory.js.map +1 -1
  31. package/dist/write-strategy/manual.d.ts +1 -1
  32. package/dist/write-strategy/manual.js +1 -1
  33. package/dist/write-strategy/manual.js.map +1 -1
  34. package/dist/write-strategy/timed.d.ts +1 -1
  35. package/dist/write-strategy/timed.js +1 -1
  36. package/dist/write-strategy/timed.js.map +1 -1
  37. package/dist/write-strategy/worker/message.d.ts +1 -1
  38. package/dist/write-strategy/worker/strategy.d.ts +1 -1
  39. package/dist/write-strategy/worker/worker.js +1 -1
  40. package/dist/write-strategy/worker/worker.js.map +1 -1
  41. package/package.json +9 -9
  42. package/src/events.ts +4 -4
  43. package/src/frame-buffer/buffer-config.ts +129 -0
  44. package/src/frame-buffer/buffer-reader.ts +38 -16
  45. package/src/frame-buffer/buffer-writer.ts +40 -18
  46. package/src/frame-buffer/buffer.ts +51 -40
  47. package/src/output-message.ts +9 -9
  48. package/src/output-stream-node.ts +23 -29
  49. package/src/output-stream-processor.ts +25 -18
  50. package/src/stream-node-factory.ts +33 -15
  51. package/src/write-strategy/manual.ts +1 -1
  52. package/src/write-strategy/timed.ts +1 -1
  53. package/src/write-strategy/worker/message.ts +1 -1
  54. package/src/write-strategy/worker/strategy.ts +1 -1
  55. package/src/write-strategy/worker/worker.ts +1 -1
  56. package/src/frame-buffer/buffer-factory.ts +0 -115
  57. package/src/frame-buffer/buffer-utils.ts +0 -48
@@ -12,8 +12,8 @@ const createFrameBufferReader = (options) => {
12
12
  class OutputStreamProcessor extends AudioWorkletProcessor {
13
13
  _frameReader;
14
14
  _shouldStop = false;
15
- _stopFrames;
16
- _underrunFrames = 0;
15
+ _stopFramePosition;
16
+ _underrunFrameCount = 0;
17
17
  /**
18
18
  * Creates an instance of OutputStreamProcessor.
19
19
  * @param options - The options for the processor, including shared buffers.
@@ -31,12 +31,12 @@ class OutputStreamProcessor extends AudioWorkletProcessor {
31
31
  if (event.data.type !== 'stop') {
32
32
  throw new Error(`Unexpected message type: ${event.data.type}`);
33
33
  }
34
- const frames = event.data.frames;
35
- if (frames <= 0) {
34
+ const framePosition = event.data.framePosition;
35
+ if (framePosition <= 0) {
36
36
  this._shouldStop = true;
37
37
  }
38
38
  else {
39
- this._stopFrames = frames;
39
+ this._stopFramePosition = framePosition;
40
40
  }
41
41
  }
42
42
  /**
@@ -44,25 +44,25 @@ class OutputStreamProcessor extends AudioWorkletProcessor {
44
44
  * If underrunFrames is provided and not zero, it adds to the current underrun frame count.
45
45
  * If underrunFrames is 0, it indicates that the underrun state has been resolved,
46
46
  * and the total underrun frame count is sent to the main thread before being reset.
47
- * @param underrunFrames - The number of underrun frames to add (default is 0).
47
+ * @param underrunFrameCount - The number of underrun frames to add (default is 0).
48
48
  */
49
- updateUnderrun(underrunFrames = 0) {
50
- if (underrunFrames !== 0) {
51
- this._underrunFrames += underrunFrames;
49
+ updateUnderrun(underrunFrameCount = 0) {
50
+ if (underrunFrameCount !== 0) {
51
+ this._underrunFrameCount += underrunFrameCount;
52
52
  return;
53
53
  }
54
- if (this._underrunFrames === 0) {
54
+ if (this._underrunFrameCount === 0) {
55
55
  return;
56
56
  }
57
- this.port.postMessage({ type: 'underrun', frames: this._underrunFrames });
58
- this._underrunFrames = 0;
57
+ this.port.postMessage({ type: 'underrun', underrunFrameCount: this._underrunFrameCount });
58
+ this._underrunFrameCount = 0;
59
59
  }
60
60
  /**
61
61
  * Checks the stop condition.
62
62
  * @param totalFrames - The total number of frames processed so far.
63
63
  */
64
64
  checkStopCondition(totalFrames) {
65
- if (this._stopFrames !== undefined && totalFrames >= this._stopFrames) {
65
+ if (this._stopFramePosition !== undefined && totalFrames >= this._stopFramePosition) {
66
66
  this._shouldStop = true;
67
67
  }
68
68
  }
@@ -74,16 +74,23 @@ class OutputStreamProcessor extends AudioWorkletProcessor {
74
74
  */
75
75
  process(_inputs, outputs) {
76
76
  const output = outputs[0];
77
- const readFrames = this._frameReader.read((frame, offset) => {
78
- const frames = Math.min(frame.frames, output[0].length - offset);
79
- frame.buffer.convertToOutput(frame.index, frames, output, offset);
80
- return frames;
77
+ const samplesPerFrame = output.length;
78
+ const readFrames = this._frameReader.read((buffer, offset) => {
79
+ const bufferFrameCount = buffer.length / samplesPerFrame;
80
+ const frameCount = Math.min(bufferFrameCount, output[0].length - offset);
81
+ // Deinterleaves interleaved audio frame data and writes it to the output.
82
+ output.forEach((outputChannel, channelIndex) => {
83
+ for (let i = channelIndex, j = 0; j < frameCount; i += samplesPerFrame, ++j) {
84
+ outputChannel[offset + j] = buffer[i];
85
+ }
86
+ });
87
+ return frameCount;
81
88
  });
82
89
  const totalFrames = this._frameReader.totalFrames;
83
90
  this.checkStopCondition(totalFrames);
84
91
  if (this._shouldStop) {
85
92
  this.updateUnderrun();
86
- this.port.postMessage({ type: 'stop', frames: totalFrames });
93
+ this.port.postMessage({ type: 'stop', totalProcessedFrames: totalFrames });
87
94
  this.port.close();
88
95
  return false;
89
96
  }
@@ -1 +1 @@
1
- {"version":3,"file":"output-stream-processor.js","sourceRoot":"","sources":["../src/output-stream-processor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"output-stream-processor.js","sourceRoot":"","sources":["../src/output-stream-processor.ts"],"names":[],"mappings":"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"}
@@ -79,6 +79,16 @@ export declare class StreamNodeFactory {
79
79
  * @throws Error - If validation fails.
80
80
  */
81
81
  private static validateTimedBufferNodeParams;
82
+ /**
83
+ * Applies a default sample rate to the given parameters if the sampleRate is undefined.
84
+ * This function creates a new TimedBufferNodeParams object with the specified sampleRate,
85
+ * while keeping other properties unchanged.
86
+ *
87
+ * @param params - The original parameters for the TimedBufferNode.
88
+ * @param defaultSampleRate - The default sample rate to use if params.sampleRate is undefined.
89
+ * @returns A new TimedBufferNodeParams object with the sample rate applied.
90
+ */
91
+ private static applySampleRateToParams;
82
92
  /**
83
93
  * Get the AudioContext associated with this factory.
84
94
  * @returns The AudioContext instance.
@@ -1,6 +1,6 @@
1
1
  import processor from './output-stream-processor?worker&url';
2
2
  import { ManualBufferWriteStrategy } from './write-strategy/manual';
3
- import { FrameBufferFactory } from './frame-buffer/buffer-factory';
3
+ import { createFillerFrameBufferConfig, createFrameBufferConfig } from './frame-buffer/buffer-config';
4
4
  import { TimedBufferWriteStrategy } from './write-strategy/timed';
5
5
  import { WorkerBufferWriteStrategy } from './write-strategy/worker/strategy';
6
6
  /**
@@ -34,7 +34,7 @@ export class StreamNodeFactory {
34
34
  context.audioWorklet.addModule(processor),
35
35
  import('./output-stream-node'),
36
36
  ]);
37
- return new StreamNodeFactory(context, loadResults[1].OutputStreamNodeFactory);
37
+ return new StreamNodeFactory(context, loadResults[1].OutputStreamNode);
38
38
  }
39
39
  catch (error) {
40
40
  throw new Error('Failed to load modules: ' + error);
@@ -52,9 +52,9 @@ export class StreamNodeFactory {
52
52
  if (params.frameBufferSize <= 0 || !Number.isInteger(params.frameBufferSize)) {
53
53
  throw new Error('Invalid frameBufferSize: must be a positive integer.');
54
54
  }
55
- const bufferConfig = FrameBufferFactory.createFrameBufferConfig({ ...params });
56
- const strategy = new ManualBufferWriteStrategy(bufferConfig);
57
- return [await this._outputStreamNodeFactory.create(this.audioContext, bufferConfig, strategy), strategy.writer];
55
+ const config = createFrameBufferConfig({ ...params });
56
+ const strategy = new ManualBufferWriteStrategy(config);
57
+ return [await this._outputStreamNodeFactory.create(this.audioContext, config, strategy), strategy.writer];
58
58
  }
59
59
  /**
60
60
  * Creates an OutputStreamNode with timed buffer writing strategy.
@@ -63,13 +63,13 @@ export class StreamNodeFactory {
63
63
  * @returns A promise that resolves to an OutputStreamNode instance.
64
64
  */
65
65
  async createTimedBufferNode(frameFiller, params) {
66
- StreamNodeFactory.validateTimedBufferNodeParams(params);
67
66
  if (typeof frameFiller !== 'object' || frameFiller === null) {
68
67
  throw new Error('Invalid frameFiller: must be an object.');
69
68
  }
70
- const config = FrameBufferFactory.createFillerFrameBufferConfig(this._audioContext.sampleRate, { ...params });
71
- const strategy = new TimedBufferWriteStrategy(config, frameFiller);
72
- return this._outputStreamNodeFactory.create(this.audioContext, config, strategy);
69
+ StreamNodeFactory.validateTimedBufferNodeParams(params);
70
+ const paramsWithSampleRate = StreamNodeFactory.applySampleRateToParams(params, this._audioContext.sampleRate);
71
+ const config = createFillerFrameBufferConfig(paramsWithSampleRate);
72
+ return this._outputStreamNodeFactory.create(this.audioContext, config, new TimedBufferWriteStrategy(config, frameFiller));
73
73
  }
74
74
  /**
75
75
  * Creates an OutputStreamNode with worker buffer writing strategy.
@@ -79,9 +79,9 @@ export class StreamNodeFactory {
79
79
  */
80
80
  async createWorkerBufferNode(worker, params) {
81
81
  StreamNodeFactory.validateTimedBufferNodeParams(params);
82
- const config = FrameBufferFactory.createFillerFrameBufferConfig(this._audioContext.sampleRate, { ...params });
83
- const strategy = new WorkerBufferWriteStrategy(config, worker, params.fillerParams);
84
- return this._outputStreamNodeFactory.create(this._audioContext, config, strategy);
82
+ const paramsWithSampleRate = StreamNodeFactory.applySampleRateToParams(params, this._audioContext.sampleRate);
83
+ const config = createFillerFrameBufferConfig(paramsWithSampleRate);
84
+ return this._outputStreamNodeFactory.create(this._audioContext, config, new WorkerBufferWriteStrategy(config, worker, params.fillerParams));
85
85
  }
86
86
  /**
87
87
  * Validates the parameters for timed buffer node creation.
@@ -102,6 +102,21 @@ export class StreamNodeFactory {
102
102
  throw new Error('Invalid frameBufferChunks: must be a positive integer.');
103
103
  }
104
104
  }
105
+ /**
106
+ * Applies a default sample rate to the given parameters if the sampleRate is undefined.
107
+ * This function creates a new TimedBufferNodeParams object with the specified sampleRate,
108
+ * while keeping other properties unchanged.
109
+ *
110
+ * @param params - The original parameters for the TimedBufferNode.
111
+ * @param defaultSampleRate - The default sample rate to use if params.sampleRate is undefined.
112
+ * @returns A new TimedBufferNodeParams object with the sample rate applied.
113
+ */
114
+ static applySampleRateToParams(params, defaultSampleRate) {
115
+ return {
116
+ ...params,
117
+ sampleRate: params.sampleRate ?? defaultSampleRate,
118
+ };
119
+ }
105
120
  /**
106
121
  * Get the AudioContext associated with this factory.
107
122
  * @returns The AudioContext instance.
@@ -1 +1 @@
1
- {"version":3,"file":"stream-node-factory.js","sourceRoot":"","sources":["../src/stream-node-factory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"stream-node-factory.js","sourceRoot":"","sources":["../src/stream-node-factory.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { BufferWriteStrategy } from './strategy';
2
- import { FrameBufferConfig } from '../frame-buffer/buffer-factory';
2
+ import { FrameBufferConfig } from '../frame-buffer/buffer-config';
3
3
  import { FrameBufferWriter } from '../frame-buffer/buffer-writer';
4
4
  /**
5
5
  * ManualBufferWriteStrategy class
@@ -1,4 +1,4 @@
1
- import { createFrameBufferWriter } from '../frame-buffer/buffer-factory';
1
+ import { createFrameBufferWriter } from '../frame-buffer/buffer-config';
2
2
  /**
3
3
  * ManualBufferWriteStrategy class
4
4
  * Implements the BufferWriteStrategy interface for manually writing to the buffer.
@@ -1 +1 @@
1
- {"version":3,"file":"manual.js","sourceRoot":"","sources":["../../src/write-strategy/manual.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAqB,MAAM,gCAAgC,CAAA;AAG3F;;;IAGI;AACJ,MAAM,OAAO,yBAAyB;IACnB,OAAO,CAAmB;IAE3C;;;OAGG;IACH,YAAY,MAAyB;QACnC,IAAI,CAAC,OAAO,GAAG,uBAAuB,CAAC,MAAM,CAAC,CAAA;IAChD,CAAC;IAED;;;OAGG;IACH,IAAW,MAAM;QACf,OAAO,IAAI,CAAC,OAAO,CAAA;IACrB,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,MAAM,EAAC,4BAA4B;QACvC,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;;;OAIG;IACH,OAAO,EAAC,4BAA4B;QAClC,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;OAEG;IACH,SAAS,KAAU,CAAC;CACrB"}
1
+ {"version":3,"file":"manual.js","sourceRoot":"","sources":["../../src/write-strategy/manual.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAqB,MAAM,+BAA+B,CAAA;AAG1F;;;IAGI;AACJ,MAAM,OAAO,yBAAyB;IACnB,OAAO,CAAmB;IAE3C;;;OAGG;IACH,YAAY,MAAyB;QACnC,IAAI,CAAC,OAAO,GAAG,uBAAuB,CAAC,MAAM,CAAC,CAAA;IAChD,CAAC;IAED;;;OAGG;IACH,IAAW,MAAM;QACf,OAAO,IAAI,CAAC,OAAO,CAAA;IACrB,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,MAAM,EAAC,4BAA4B;QACvC,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;;;OAIG;IACH,OAAO,EAAC,4BAA4B;QAClC,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;OAEG;IACH,SAAS,KAAU,CAAC;CACrB"}
@@ -1,5 +1,5 @@
1
1
  import { BufferWriteStrategy } from './strategy';
2
- import { FillerFrameBufferConfig } from '../frame-buffer/buffer-factory';
2
+ import { FillerFrameBufferConfig } from '../frame-buffer/buffer-config';
3
3
  import { FrameBufferFiller } from '../frame-buffer/buffer-filler';
4
4
  import { OutputStreamNode } from '../output-stream-node';
5
5
  /**
@@ -1,4 +1,4 @@
1
- import { createFrameBufferWriter } from '../frame-buffer/buffer-factory';
1
+ import { createFrameBufferWriter } from '../frame-buffer/buffer-config';
2
2
  /**
3
3
  * PlayContext class
4
4
  * Manages the buffer filling process using a timer.
@@ -1 +1 @@
1
- {"version":3,"file":"timed.js","sourceRoot":"","sources":["../../src/write-strategy/timed.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAA2B,MAAM,gCAAgC,CAAA;AAKjG;;;GAGG;AACH,MAAM,WAAW;IACP,QAAQ,GAAW,CAAC,CAAA;IAE5B;;;;;;OAMG;IACH,YAAY,IAAsB,EAAE,MAAyB,EAAE,MAAyB,EAAE,YAAoB;QAC5G,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE;YACtC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;gBACpC,OAAM;YACR,CAAC;YACD,IAAI,CAAC;gBACH,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;oBACzB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;gBAC/B,CAAC;YACH,CAAC;YACD,MAAM,CAAC;gBACL,IAAI,CAAC,OAAO,EAAE,CAAA;gBACd,IAAI,CAAC,IAAI,EAAE,CAAA;YACb,CAAC;QACH,CAAC,EAAE,YAAY,CAAC,CAAA;IAClB,CAAC;IAED;;OAEG;IACI,OAAO;QACZ,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;YAC5B,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAA;QACnB,CAAC;IACH,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,OAAO,wBAAwB;IAClB,OAAO,CAAmB;IAC1B,OAAO,CAAmB;IAC1B,SAAS,CAAQ;IACjB,mBAAmB,CAAS;IACrC,QAAQ,GAAuB,IAAI,CAAA;IAE3C;;;;OAIG;IACH,YAAY,MAA+B,EAAE,MAAyB;QACpE,IAAI,CAAC,OAAO,GAAG,uBAAuB,CAAC,MAAM,CAAC,CAAA;QAC9C,IAAI,CAAC,OAAO,GAAG,MAAM,CAAA;QACrB,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,YAAY,CAAA;QACpC,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAC5D,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,MAAM,EAAC,4BAA4B;QACvC,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;;;OAIG;IACH,OAAO,CAAC,IAAsB;QAC5B,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAA;QACxD,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC9B,OAAO,KAAK,CAAA;QACd,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,IAAI,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,CAAA;QACjF,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;OAEG;IACH,SAAS;QACP,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAA;QACxB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAA;IACtB,CAAC;CACF"}
1
+ {"version":3,"file":"timed.js","sourceRoot":"","sources":["../../src/write-strategy/timed.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAA2B,MAAM,+BAA+B,CAAA;AAKhG;;;GAGG;AACH,MAAM,WAAW;IACP,QAAQ,GAAW,CAAC,CAAA;IAE5B;;;;;;OAMG;IACH,YAAY,IAAsB,EAAE,MAAyB,EAAE,MAAyB,EAAE,YAAoB;QAC5G,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE;YACtC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;gBACpC,OAAM;YACR,CAAC;YACD,IAAI,CAAC;gBACH,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;oBACzB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;gBAC/B,CAAC;YACH,CAAC;YACD,MAAM,CAAC;gBACL,IAAI,CAAC,OAAO,EAAE,CAAA;gBACd,IAAI,CAAC,IAAI,EAAE,CAAA;YACb,CAAC;QACH,CAAC,EAAE,YAAY,CAAC,CAAA;IAClB,CAAC;IAED;;OAEG;IACI,OAAO;QACZ,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;YAC5B,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAA;QACnB,CAAC;IACH,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,OAAO,wBAAwB;IAClB,OAAO,CAAmB;IAC1B,OAAO,CAAmB;IAC1B,SAAS,CAAQ;IACjB,mBAAmB,CAAS;IACrC,QAAQ,GAAuB,IAAI,CAAA;IAE3C;;;;OAIG;IACH,YAAY,MAA+B,EAAE,MAAyB;QACpE,IAAI,CAAC,OAAO,GAAG,uBAAuB,CAAC,MAAM,CAAC,CAAA;QAC9C,IAAI,CAAC,OAAO,GAAG,MAAM,CAAA;QACrB,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,YAAY,CAAA;QACpC,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAC5D,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,MAAM,EAAC,4BAA4B;QACvC,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;;;OAIG;IACH,OAAO,CAAC,IAAsB;QAC5B,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAA;QACxD,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC9B,OAAO,KAAK,CAAA;QACd,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,IAAI,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,CAAA;QACjF,OAAO,IAAI,CAAA;IACb,CAAC;IAED;;OAEG;IACH,SAAS;QACP,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAA;QACxB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAA;IACtB,CAAC;CACF"}
@@ -1,4 +1,4 @@
1
- import type { FillerFrameBufferConfig } from '../../frame-buffer/buffer-factory';
1
+ import type { FillerFrameBufferConfig } from '../../frame-buffer/buffer-config';
2
2
  /**
3
3
  * Message sent from the main thread to the worker.
4
4
  *
@@ -1,5 +1,5 @@
1
1
  import type { BufferWriteStrategy } from '../strategy';
2
- import type { FillerFrameBufferConfig } from '../../frame-buffer/buffer-factory';
2
+ import type { FillerFrameBufferConfig } from '../../frame-buffer/buffer-config';
3
3
  import type { OutputStreamNode } from '../../output-stream-node';
4
4
  /**
5
5
  * WorkerBufferWriteStrategy class
@@ -1,4 +1,4 @@
1
- import { createFrameBufferWriter } from '../../frame-buffer/buffer-factory';
1
+ import { createFrameBufferWriter } from '../../frame-buffer/buffer-config';
2
2
  /**
3
3
  * Context class
4
4
  * Manages the buffer filling process within a web worker.
@@ -1 +1 @@
1
- {"version":3,"file":"worker.js","sourceRoot":"","sources":["../../../src/write-strategy/worker/worker.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"worker.js","sourceRoot":"","sources":["../../../src/write-strategy/worker/worker.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ain1084/audio-worklet-stream",
3
- "version": "0.1.8",
3
+ "version": "1.0.1",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -41,14 +41,14 @@
41
41
  },
42
42
  "devDependencies": {
43
43
  "@stylistic/eslint-plugin": "^2.9.0",
44
- "@types/audioworklet": "^0.0.60",
45
- "@types/node": "^22.7.5",
46
- "@typescript-eslint/parser": "^8.8.1",
44
+ "@types/audioworklet": "^0.0.61",
45
+ "@types/node": "^22.7.6",
46
+ "@typescript-eslint/parser": "^8.9.0",
47
47
  "eslint": "^9.12.0",
48
- "globals": "^15.10.0",
49
- "typedoc": "^0.26.8",
50
- "typescript": "^5.6.2",
51
- "typescript-eslint": "^8.8.1",
52
- "vite": "^5.4.8"
48
+ "globals": "^15.11.0",
49
+ "typedoc": "^0.26.10",
50
+ "typescript": "^5.6.3",
51
+ "typescript-eslint": "^8.9.0",
52
+ "vite": "^5.4.9"
53
53
  }
54
54
  }
package/src/events.ts CHANGED
@@ -8,9 +8,9 @@ export class StopEvent extends Event {
8
8
  public static readonly type = STOP_EVENT_TYPE
9
9
  /**
10
10
  * Creates an instance of StopEvent.
11
- * @param frames - The position in the audio stream where the stop occurred.
11
+ * @param stoppedAtFrame - The position in the audio stream where the stop occurred.
12
12
  */
13
- public constructor(readonly frames: bigint) {
13
+ public constructor(readonly stoppedAtFrame: bigint) {
14
14
  super(StopEvent.type)
15
15
  }
16
16
  }
@@ -24,9 +24,9 @@ export class UnderrunEvent extends Event {
24
24
  public static readonly type = UNDERRUN_EVENT_TYPE
25
25
  /**
26
26
  * Creates an instance of UnderrunEvent.
27
- * @param frames - The number of frames that were not processed due to the underrun.
27
+ * @param frameCount - The number of frames that were not processed due to the underrun.
28
28
  */
29
- public constructor(readonly frames: number) {
29
+ public constructor(readonly frameCount: number) {
30
30
  super(UnderrunEvent.type)
31
31
  }
32
32
  }
@@ -0,0 +1,129 @@
1
+ import { FrameBuffer } from './buffer'
2
+ import { FrameBufferWriter } from './buffer-writer'
3
+
4
+ /**
5
+ * The default number of chunks in the frame buffer when
6
+ * FillerFrameBufferParams.frameBufferChunks is not provided.
7
+ * A frame buffer sufficient to hold fillInterval * frameBufferChunks of playback time is allocated.
8
+ */
9
+ const DEFAULT_FILL_INTERVAL_MS = 20
10
+
11
+ /**
12
+ * The default number of chunks in the frame buffer when
13
+ * FillerFrameBufferParams.frameBufferChunks is not provided.
14
+ * The total frame buffer size will be fillInterval * frameBufferChunks.
15
+ */
16
+ const DEFAULT_FRAME_BUFFER_CHUNKS = 5
17
+
18
+ /**
19
+ * The unit for rounding up the frame buffer size.
20
+ * This value is aligned with the audio data block size used by the AudioWorkletProcessor.
21
+ * Reference: https://developer.mozilla.org/en-US/docs/Web/API/AudioWorkletProcessor/process
22
+ */
23
+ const AUDIO_WORKLET_BLOCK_SIZE = 128
24
+
25
+ /**
26
+ * Parameters for creating a FrameBuffer.
27
+ * @property frameBufferSize - The size of the frame buffer.
28
+ * @property channelCount - The number of audio channels.
29
+ */
30
+ export type FrameBufferParams = Readonly<{
31
+ frameBufferSize: number
32
+ channelCount: number
33
+ }>
34
+
35
+ /**
36
+ * Parameters for creating a FillerFrameBuffer.
37
+ * @property channelCount - The number of audio channels.
38
+ * @property fillInterval - The interval in milliseconds for filling the buffer.
39
+ * @property sampleRate - The sample rate of the audio context.
40
+ * @property frameBufferChunks - The number of chunks in the frame buffer.
41
+ */
42
+ export type FillerFrameBufferParams = Readonly<{
43
+ channelCount: number
44
+ fillInterval?: number
45
+ sampleRate?: number
46
+ frameBufferChunks?: number
47
+ }>
48
+
49
+ /**
50
+ * Configuration for a FrameBuffer.
51
+ * This configuration is returned by the createFrameBufferConfig function.
52
+ * @property sampleBuffer - The shared buffer for audio data frames.
53
+ * @property samplesPerFrame - The number of samples per frame.
54
+ * @property usedFramesInBuffer - The usage count of the frames in the buffer.
55
+ * @property totalReadFrames - The total frames read from the buffer.
56
+ * @property totalWriteFrames - The total frames written to the buffer.
57
+ */
58
+ export type FrameBufferConfig = Readonly<{
59
+ sampleBuffer: Float32Array
60
+ samplesPerFrame: number
61
+ usedFramesInBuffer: Uint32Array
62
+ totalReadFrames: BigUint64Array
63
+ totalWriteFrames: BigUint64Array
64
+ }>
65
+
66
+ /**
67
+ * Configuration for a FillerFrameBuffer.
68
+ * This configuration is returned by the createFillerFrameBufferConfig function.
69
+ * @property sampleRate - The sample rate of the audio context.
70
+ * @property fillInterval - The interval in milliseconds for filling the buffer.
71
+ */
72
+ export type FillerFrameBufferConfig = FrameBufferConfig & Readonly<{
73
+ sampleRate: number
74
+ fillInterval: number
75
+ }>
76
+
77
+ /**
78
+ * Creates a FrameBufferWriter instance.
79
+ * @param config - The configuration for the FrameBuffer.
80
+ * @returns A new instance of FrameBufferWriter.
81
+ */
82
+ export const createFrameBufferWriter = (config: FrameBufferConfig): FrameBufferWriter => {
83
+ return new FrameBufferWriter(
84
+ new FrameBuffer(config.sampleBuffer, config.samplesPerFrame),
85
+ config.usedFramesInBuffer, config.totalWriteFrames,
86
+ )
87
+ }
88
+
89
+ /**
90
+ * Creates a FrameBufferConfig instance.
91
+ * @param params - The parameters for the FrameBuffer.
92
+ * @returns A new instance of FrameBufferConfig.
93
+ */
94
+ export const createFrameBufferConfig = (params: FrameBufferParams): FrameBufferConfig => {
95
+ return {
96
+ sampleBuffer: new Float32Array(
97
+ new SharedArrayBuffer(params.frameBufferSize * params.channelCount * Float32Array.BYTES_PER_ELEMENT),
98
+ ),
99
+ samplesPerFrame: params.channelCount,
100
+ usedFramesInBuffer: new Uint32Array(new SharedArrayBuffer(Uint32Array.BYTES_PER_ELEMENT)),
101
+ totalReadFrames: new BigUint64Array(new SharedArrayBuffer(BigUint64Array.BYTES_PER_ELEMENT)),
102
+ totalWriteFrames: new BigUint64Array(new SharedArrayBuffer(BigUint64Array.BYTES_PER_ELEMENT)),
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Creates a FillerFrameBufferConfig instance.
108
+ * @param params - The parameters for the FillerFrameBuffer.
109
+ * @returns A new instance of FillerFrameBufferConfig.
110
+ */
111
+ export const createFillerFrameBufferConfig = (params: FillerFrameBufferParams): FillerFrameBufferConfig => {
112
+ const sampleRate = params.sampleRate
113
+ // Check if 'sampleRate' is a positive integer
114
+ if (sampleRate === undefined || (!Number.isInteger(sampleRate) || sampleRate <= 0)) {
115
+ throw new Error('Invalid sampleRate: must be a positive integer.')
116
+ }
117
+ const intervalMillisecond = params.fillInterval ?? DEFAULT_FILL_INTERVAL_MS
118
+ const frameBufferSize = Math.floor(
119
+ sampleRate * intervalMillisecond / 1000 + (AUDIO_WORKLET_BLOCK_SIZE - 1),
120
+ ) & ~(AUDIO_WORKLET_BLOCK_SIZE - 1)
121
+ const frameBufferChunkCount = params.frameBufferChunks ?? DEFAULT_FRAME_BUFFER_CHUNKS
122
+ const config = createFrameBufferConfig(
123
+ { frameBufferSize: frameBufferSize * frameBufferChunkCount, channelCount: params.channelCount })
124
+ return {
125
+ ...config,
126
+ sampleRate,
127
+ fillInterval: intervalMillisecond,
128
+ }
129
+ }
@@ -1,4 +1,3 @@
1
- import { enumFrames, type FrameCallback } from './buffer-utils'
2
1
  import { FrameBuffer } from './buffer'
3
2
 
4
3
  /**
@@ -8,19 +7,19 @@ import { FrameBuffer } from './buffer'
8
7
  */
9
8
  export class FrameBufferReader {
10
9
  private readonly _frameBuffer: FrameBuffer
11
- private readonly _usedFrameInBuffer: Uint32Array
10
+ private readonly _usedFramesInBuffer: Uint32Array
12
11
  private readonly _totalFrames: BigUint64Array
13
12
  private _index: number = 0
14
13
 
15
14
  /**
16
15
  * Creates an instance of FrameBufferReader.
17
16
  * @param frameBuffer - The shared buffer to read from.
18
- * @param usedFrameInBuffer - The Uint32Array tracking the usage of the buffer.
17
+ * @param usedFramesInBuffer - The Uint32Array tracking the usage of the buffer.
19
18
  * @param totalFrames - The BigUint64Array tracking the total frames read from the buffer.
20
19
  */
21
- constructor(frameBuffer: FrameBuffer, usedFrameInBuffer: Uint32Array, totalFrames: BigUint64Array) {
20
+ constructor(frameBuffer: FrameBuffer, usedFramesInBuffer: Uint32Array, totalFrames: BigUint64Array) {
22
21
  this._frameBuffer = frameBuffer
23
- this._usedFrameInBuffer = usedFrameInBuffer
22
+ this._usedFramesInBuffer = usedFramesInBuffer
24
23
  this._totalFrames = totalFrames
25
24
  }
26
25
 
@@ -28,29 +27,52 @@ export class FrameBufferReader {
28
27
  * Get the number of available frames in the buffer.
29
28
  * @returns The number of available frames in the buffer.
30
29
  */
31
- public get available(): number {
32
- return Atomics.load(this._usedFrameInBuffer, 0)
30
+ public get availableFrames(): number {
31
+ return Atomics.load(this._usedFramesInBuffer, 0)
33
32
  }
34
33
 
35
34
  /**
36
35
  * Get the total number of frames read from the buffer.
36
+ *
37
37
  * @returns The total number of frames read.
38
38
  */
39
39
  public get totalFrames(): bigint {
40
+ // This class is not used concurrently by multiple threads,
41
+ // so `Atomics` is not necessary when reading `totalFrames`.
40
42
  return this._totalFrames[0]
41
43
  }
42
44
 
43
45
  /**
44
- * Reads audio frame data from the buffer and processes it using the provided callback.
45
- * @param frameCallback - The callback function to process each section of the buffer.
46
- * @returns The number of frames processed.
47
- * @throws RangeError - If the processed length exceeds the part length.
46
+ * Reads audio frame data from the buffer using the provided callback.
47
+ * This method handles one or more readable segments within the ring buffer
48
+ * and invokes the callback for each segment.
49
+ *
50
+ * @param processFrameSegment - The callback function invoked for each readable segment
51
+ * of the ring buffer. It receives:
52
+ * 1. `buffer`: A Float32Array representing the readable segment of the buffer.
53
+ * 2. `offset`: The cumulative number of frames processed so far, used as the starting index
54
+ * for the current segment relative to the entire data.
55
+ *
56
+ * The callback must return the number of frames it successfully processed.
57
+ * If the callback processes fewer frames than available in the current segment,
58
+ * processing will stop early.
59
+ *
60
+ * @returns The total number of frames processed across all segments.
61
+ * Note: The return value is in frames, not in samples.
62
+ *
63
+ * @throws RangeError - If the processFrameSegment callback returns a processed length greater than the available frames in the current segment.
64
+ *
65
+ * @remarks The buffer is an array of samples, but it is always provided in frame-sized segments.
66
+ * Each frame consists of multiple samples (e.g., for stereo, a frame contains a sample for the left channel
67
+ * and one for the right channel). You must access and process the buffer in frame-sized chunks,
68
+ * based on the structure of the frames.
69
+ *
48
70
  */
49
- public read(frameCallback: FrameCallback): number {
50
- const result = enumFrames(this._frameBuffer, this._index, this.available, frameCallback)
71
+ public read(processFrameSegment: (buffer: Float32Array, offset: number) => number): number {
72
+ const result = this._frameBuffer.enumFrameSegments(this._index, this.availableFrames, processFrameSegment)
51
73
  this._index = result.nextIndex
52
- Atomics.sub(this._usedFrameInBuffer, 0, result.frames)
53
- Atomics.add(this._totalFrames, 0, BigInt(result.frames))
54
- return result.frames
74
+ Atomics.sub(this._usedFramesInBuffer, 0, result.totalProcessedFrames)
75
+ Atomics.add(this._totalFrames, 0, BigInt(result.totalProcessedFrames))
76
+ return result.totalProcessedFrames
55
77
  }
56
78
  }