@mediabunny/flac-encoder 1.42.0 → 1.43.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.
package/src/encoder.ts CHANGED
@@ -29,7 +29,7 @@ class FlacEncoder extends CustomAudioEncoder {
29
29
  reject: (reason?: unknown) => void;
30
30
  }>();
31
31
 
32
- private ctx = 0;
32
+ private ctx: number | null = null;
33
33
  private chunkMetadata: EncodedAudioChunkMetadata = {};
34
34
  private description: Uint8Array | null = null;
35
35
  private nextTimestampInSamples: number | null = null;
@@ -65,19 +65,6 @@ class FlacEncoder extends CustomAudioEncoder {
65
65
  };
66
66
  nodeWorker.on('message', onMessage);
67
67
  }
68
-
69
- const result = await this.sendCommand({
70
- type: 'init',
71
- data: {
72
- numberOfChannels: this.config.numberOfChannels,
73
- sampleRate: this.config.sampleRate,
74
- },
75
- });
76
-
77
- this.ctx = result.ctx;
78
-
79
- this.description = new Uint8Array(result.header);
80
- this.resetInternalState();
81
68
  }
82
69
 
83
70
  private resetInternalState() {
@@ -94,15 +81,50 @@ class FlacEncoder extends CustomAudioEncoder {
94
81
  }
95
82
 
96
83
  async encode(audioSample: AudioSample) {
84
+ if (this.ctx === null) {
85
+ // This is the first sample, let's do some init
86
+
87
+ let bitsPerSample: 16 | 24;
88
+ switch (audioSample.format) {
89
+ case 'u8':
90
+ case 'u8-planar':
91
+ case 's16':
92
+ case 's16-planar':
93
+ bitsPerSample = 16;
94
+ break;
95
+ case 's32':
96
+ case 's32-planar':
97
+ case 'f32':
98
+ case 'f32-planar':
99
+ bitsPerSample = 24;
100
+ break;
101
+ default:
102
+ assertNever(audioSample.format);
103
+ assert(false);
104
+ }
105
+
106
+ const result = await this.sendCommand({
107
+ type: 'init',
108
+ data: {
109
+ numberOfChannels: this.config.numberOfChannels,
110
+ sampleRate: this.config.sampleRate,
111
+ bitsPerSample,
112
+ },
113
+ });
114
+
115
+ this.ctx = result.ctx;
116
+ this.description = new Uint8Array(result.header);
117
+ this.resetInternalState();
118
+ }
119
+
97
120
  if (this.nextTimestampInSamples === null) {
98
121
  this.nextTimestampInSamples = Math.round(audioSample.timestamp * this.config.sampleRate);
99
122
  }
100
123
 
101
- const totalBytes = audioSample.allocationSize({ format: 's16', planeIndex: 0 });
102
- const audioBytes = new Uint8Array(totalBytes);
103
- audioSample.copyTo(audioBytes, { format: 's16', planeIndex: 0 });
124
+ const totalBytes = audioSample.allocationSize({ format: 's32', planeIndex: 0 });
125
+ const audioData = new ArrayBuffer(totalBytes);
126
+ audioSample.copyTo(audioData, { format: 's32', planeIndex: 0 });
104
127
 
105
- const audioData = audioBytes.buffer;
106
128
  const result = await this.sendCommand({
107
129
  type: 'encode',
108
130
  data: {
@@ -116,6 +138,10 @@ class FlacEncoder extends CustomAudioEncoder {
116
138
  }
117
139
 
118
140
  async flush() {
141
+ if (this.ctx === null) {
142
+ return;
143
+ }
144
+
119
145
  const result = await this.sendCommand({ type: 'flush', data: { ctx: this.ctx } });
120
146
  this.emitPackets(result.packets);
121
147
 
@@ -173,7 +199,8 @@ class FlacEncoder extends CustomAudioEncoder {
173
199
 
174
200
  /**
175
201
  * Registers the FLAC encoder, which Mediabunny will then use automatically when applicable. Make sure to call this
176
- * function before starting any encoding task.
202
+ * function before starting any encoding task. The FLAC encoder will automatically determine the output bit depth
203
+ * (16 or 24) based on the sample format of incoming `AudioSample` instances.
177
204
  *
178
205
  * Preferably, wrap the call in a condition to avoid overriding any native FLAC encoder:
179
206
  *
@@ -198,3 +225,8 @@ function assert(x: unknown): asserts x {
198
225
  throw new Error('Assertion failed.');
199
226
  }
200
227
  }
228
+
229
+ export const assertNever = (x: never) => {
230
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
231
+ throw new Error(`Unexpected value: ${x}`);
232
+ };
package/src/shared.ts CHANGED
@@ -16,6 +16,7 @@ export type WorkerCommand = {
16
16
  data: {
17
17
  numberOfChannels: number;
18
18
  sampleRate: number;
19
+ bitsPerSample: 16 | 24;
19
20
  };
20
21
  } | {
21
22
  type: 'encode';