1// Mono 16-bit PCM WAV encoder.
3/** Encodes the signal as a 16-bit PCM mono WAV file; samples are clamped to [-1, 1]. */
4export function encodeWav(samples: Float32Array, fs: number): Blob {
5 const n = samples.length;
6 const dataBytes = n * 2;
7 const buf = new ArrayBuffer(44 + dataBytes);
8 const v = new DataView(buf);
9 const ascii = (offset: number, s: string): void => {
10 for (let k = 0; k < s.length; k++) v.setUint8(offset + k, s.charCodeAt(k));
11 };
12 const rate = Math.round(fs);
13 ascii(0, "RIFF");
14 v.setUint32(4, 36 + dataBytes, true);
15 ascii(8, "WAVE");
16 ascii(12, "fmt ");
17 v.setUint32(16, 16, true); // fmt chunk size
18 v.setUint16(20, 1, true); // PCM
19 v.setUint16(22, 1, true); // channels
20 v.setUint32(24, rate, true);
21 v.setUint32(28, rate * 2, true); // byte rate
22 v.setUint16(32, 2, true); // block align
23 v.setUint16(34, 16, true); // bits per sample
24 ascii(36, "data");
25 v.setUint32(40, dataBytes, true);
26 for (let k = 0; k < n; k++) {
27 const x = samples[k];
28 const s = x > 1 ? 1 : x < -1 ? -1 : x !== x ? 0 : x;
29 v.setInt16(44 + 2 * k, Math.round(s * 32767), true);
30 }
31 return new Blob([buf], { type: "audio/wav" });
32}