61 lines
1.8 KiB
TypeScript
61 lines
1.8 KiB
TypeScript
export class Stereo48kToMono16kDownsampler {
|
|
private readonly pendingMono48k: number[] = [];
|
|
|
|
pushStereo48kChunk(chunk: Buffer): Int16Array {
|
|
if (chunk.length < 4) {
|
|
return new Int16Array();
|
|
}
|
|
|
|
for (let offset = 0; offset + 3 < chunk.length; offset += 4) {
|
|
const left = chunk.readInt16LE(offset);
|
|
const right = chunk.readInt16LE(offset + 2);
|
|
this.pendingMono48k.push(Math.round((left + right) / 2));
|
|
}
|
|
|
|
const outputLength = Math.floor(this.pendingMono48k.length / 3);
|
|
if (outputLength === 0) {
|
|
return new Int16Array();
|
|
}
|
|
|
|
const output = new Int16Array(outputLength);
|
|
let readIndex = 0;
|
|
for (let index = 0; index < outputLength; index += 1) {
|
|
const a = this.pendingMono48k[readIndex];
|
|
const b = this.pendingMono48k[readIndex + 1];
|
|
const c = this.pendingMono48k[readIndex + 2];
|
|
output[index] = Math.round((a + b + c) / 3);
|
|
readIndex += 3;
|
|
}
|
|
|
|
this.pendingMono48k.splice(0, readIndex);
|
|
return output;
|
|
}
|
|
}
|
|
|
|
export function int16ArrayToFloat32(input: Int16Array): Float32Array {
|
|
const output = new Float32Array(input.length);
|
|
for (let index = 0; index < input.length; index += 1) {
|
|
output[index] = input[index] / 32768;
|
|
}
|
|
return output;
|
|
}
|
|
|
|
export function float32ToPcm16Buffer(input: Float32Array): Buffer {
|
|
const buffer = Buffer.allocUnsafe(input.length * 2);
|
|
for (let index = 0; index < input.length; index += 1) {
|
|
const value = Math.max(-1, Math.min(1, input[index]));
|
|
const scaled = value < 0 ? value * 32768 : value * 32767;
|
|
buffer.writeInt16LE(Math.round(scaled), index * 2);
|
|
}
|
|
return buffer;
|
|
}
|
|
|
|
export function takeFrame(source: number[], frameSize: number): Int16Array | null {
|
|
if (source.length < frameSize) {
|
|
return null;
|
|
}
|
|
|
|
const values = source.splice(0, frameSize);
|
|
return Int16Array.from(values);
|
|
}
|