mirror of
https://github.com/arcodange-org/mediabunny.git
synced 2026-09-28 19:33:51 +02:00
Make FLAC encoder bit depth depend on input sample format, add sampleFormat audio transformation option, fix incorrect bitrate validation for FLAC (closes #357)
This commit is contained in:
@@ -29,7 +29,7 @@ class FlacEncoder extends CustomAudioEncoder {
|
||||
reject: (reason?: unknown) => void;
|
||||
}>();
|
||||
|
||||
private ctx = 0;
|
||||
private ctx: number | null = null;
|
||||
private chunkMetadata: EncodedAudioChunkMetadata = {};
|
||||
private description: Uint8Array | null = null;
|
||||
private nextTimestampInSamples: number | null = null;
|
||||
@@ -65,19 +65,6 @@ class FlacEncoder extends CustomAudioEncoder {
|
||||
};
|
||||
nodeWorker.on('message', onMessage);
|
||||
}
|
||||
|
||||
const result = await this.sendCommand({
|
||||
type: 'init',
|
||||
data: {
|
||||
numberOfChannels: this.config.numberOfChannels,
|
||||
sampleRate: this.config.sampleRate,
|
||||
},
|
||||
});
|
||||
|
||||
this.ctx = result.ctx;
|
||||
|
||||
this.description = new Uint8Array(result.header);
|
||||
this.resetInternalState();
|
||||
}
|
||||
|
||||
private resetInternalState() {
|
||||
@@ -94,15 +81,50 @@ class FlacEncoder extends CustomAudioEncoder {
|
||||
}
|
||||
|
||||
async encode(audioSample: AudioSample) {
|
||||
if (this.ctx === null) {
|
||||
// This is the first sample, let's do some init
|
||||
|
||||
let bitsPerSample: 16 | 24;
|
||||
switch (audioSample.format) {
|
||||
case 'u8':
|
||||
case 'u8-planar':
|
||||
case 's16':
|
||||
case 's16-planar':
|
||||
bitsPerSample = 16;
|
||||
break;
|
||||
case 's32':
|
||||
case 's32-planar':
|
||||
case 'f32':
|
||||
case 'f32-planar':
|
||||
bitsPerSample = 24;
|
||||
break;
|
||||
default:
|
||||
assertNever(audioSample.format);
|
||||
assert(false);
|
||||
}
|
||||
|
||||
const result = await this.sendCommand({
|
||||
type: 'init',
|
||||
data: {
|
||||
numberOfChannels: this.config.numberOfChannels,
|
||||
sampleRate: this.config.sampleRate,
|
||||
bitsPerSample,
|
||||
},
|
||||
});
|
||||
|
||||
this.ctx = result.ctx;
|
||||
this.description = new Uint8Array(result.header);
|
||||
this.resetInternalState();
|
||||
}
|
||||
|
||||
if (this.nextTimestampInSamples === null) {
|
||||
this.nextTimestampInSamples = Math.round(audioSample.timestamp * this.config.sampleRate);
|
||||
}
|
||||
|
||||
const totalBytes = audioSample.allocationSize({ format: 's16', planeIndex: 0 });
|
||||
const audioBytes = new Uint8Array(totalBytes);
|
||||
audioSample.copyTo(audioBytes, { format: 's16', planeIndex: 0 });
|
||||
const totalBytes = audioSample.allocationSize({ format: 's32', planeIndex: 0 });
|
||||
const audioData = new ArrayBuffer(totalBytes);
|
||||
audioSample.copyTo(audioData, { format: 's32', planeIndex: 0 });
|
||||
|
||||
const audioData = audioBytes.buffer;
|
||||
const result = await this.sendCommand({
|
||||
type: 'encode',
|
||||
data: {
|
||||
@@ -116,6 +138,10 @@ class FlacEncoder extends CustomAudioEncoder {
|
||||
}
|
||||
|
||||
async flush() {
|
||||
if (this.ctx === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await this.sendCommand({ type: 'flush', data: { ctx: this.ctx } });
|
||||
this.emitPackets(result.packets);
|
||||
|
||||
@@ -198,3 +224,8 @@ function assert(x: unknown): asserts x {
|
||||
throw new Error('Assertion failed.');
|
||||
}
|
||||
}
|
||||
|
||||
export const assertNever = (x: never) => {
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
||||
throw new Error(`Unexpected value: ${x}`);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user