// Mono PCM WAV encoding (16- or 24-bit). export function encodeWav(y: Float32Array, sampleRate: number, bitDepth: 16 | 24): Blob { const bytesPerSample = bitDepth / 8; const dataSize = y.length * bytesPerSample; const buf = new ArrayBuffer(44 + dataSize); const dv = new DataView(buf); const writeStr = (off: number, s: string) => { for (let i = 0; i < s.length; i++) dv.setUint8(off + i, s.charCodeAt(i)); }; writeStr(0, 'RIFF'); dv.setUint32(4, 36 + dataSize, true); writeStr(8, 'WAVE'); writeStr(12, 'fmt '); dv.setUint32(16, 16, true); dv.setUint16(20, 1, true); // PCM dv.setUint16(22, 1, true); // mono dv.setUint32(24, sampleRate, true); dv.setUint32(28, sampleRate * bytesPerSample, true); dv.setUint16(32, bytesPerSample, true); dv.setUint16(34, bitDepth, true); writeStr(36, 'data'); dv.setUint32(40, dataSize, true); let off = 44; for (let i = 0; i < y.length; i++) { const v = Math.max(-1, Math.min(1, y[i])); if (bitDepth === 16) { dv.setInt16(off, Math.round(v * 32767), true); off += 2; } else { const iv = Math.round(v * 8388607); dv.setUint8(off, iv & 0xff); dv.setUint8(off + 1, (iv >> 8) & 0xff); dv.setUint8(off + 2, (iv >> 16) & 0xff); off += 3; } } return new Blob([buf], { type: 'audio/wav' }); }