2025-04-16 16:37:11 +08:00

70 lines
1.5 KiB
TypeScript

type EncodeWavOptions = {
numChannels?: number;
sampleRate?: number;
byteRate?: number;
};
/**
* 编码pcm文件为wav文件
* @param rawPCM
* @param options
* @returns
*/
export function encodeWav(rawPCM: Buffer | string, options?: EncodeWavOptions) {
if (typeof rawPCM === 'string') {
rawPCM = Buffer.from(rawPCM, 'binary');
}
if (!Buffer.isBuffer(rawPCM)) {
throw new TypeError('pcm data must be Buffer or string');
}
const opt = options || {};
const sampleRate = opt.sampleRate || 16000;
const numChannels = opt.numChannels || 1;
const byteRate = opt.byteRate || 16;
const buf = rawPCM;
const header = Buffer.alloc(44);
header.write('RIFF', 0);
header.writeUInt32LE(buf.length, 4);
header.write('WAVE', 8);
header.write('fmt ', 12);
header.writeUInt8(16, 16);
header.writeUInt8(1, 20);
header.writeUInt8(numChannels, 22);
header.writeUInt32LE(sampleRate, 24);
header.writeUInt32LE(byteRate, 28);
header.writeUInt8(4, 32);
header.writeUInt8(16, 34);
header.write('data', 36);
header.writeUInt32LE(buf.length + 44 - 8, 40);
return Buffer.concat([header, buf]);
}
/**
* 解码wav文件
* @param rawWav
* @returns
*/
export function decodeWav(rawWav: Buffer | string) {
if (typeof rawWav === 'string') {
rawWav = Buffer.from(rawWav, 'binary');
}
if (!Buffer.isBuffer(rawWav)) {
throw new TypeError('pcm data must be Buffer or string');
}
// remove the header of pcm format
rawWav = rawWav.subarray(44);
return rawWav;
}
export const converter = {
encodeWav,
decodeWav,
};