import { describe, expect, it } from "vitest"; import { encodeWav } from "../src/audio/wav"; const str = (b: Uint8Array, off: number, n: number) => String.fromCharCode(...b.subarray(off, off + n)); describe("encodeWav", () => { it("writes a well-formed 24-bit mono PCM header by default", () => { const b = encodeWav(new Float32Array(10), 96000); const v = new DataView(b.buffer); expect(b.length).toBe(44 + 30); expect(str(b, 0, 4)).toBe("RIFF"); expect(v.getUint32(4, true)).toBe(b.length - 8); expect(str(b, 8, 4)).toBe("WAVE"); expect(str(b, 12, 4)).toBe("fmt "); expect(v.getUint16(20, true)).toBe(1); expect(v.getUint16(22, true)).toBe(1); expect(v.getUint32(24, true)).toBe(96000); expect(v.getUint32(28, true)).toBe(288000); expect(v.getUint16(32, true)).toBe(3); expect(v.getUint16(34, true)).toBe(24); expect(str(b, 36, 4)).toBe("data"); expect(v.getUint32(40, true)).toBe(30); }); it("quantizes 24-bit samples as the reference simulator does, little-endian two's complement", () => { const b = encodeWav([0, 1, -1, 0.5, 2, NaN], 8000, 24); const s = (i: number) => { const off = 44 + 3 * i; let x = b[off] | (b[off + 1] << 8) | (b[off + 2] << 16); if (x >= 1 << 23) x -= 1 << 24; return x; }; expect(s(0)).toBe(0); expect(s(1)).toBe(8388607); expect(s(2)).toBe(-8388607); expect(s(3)).toBe(4194304); expect(s(4)).toBe(8388607); expect(s(5)).toBe(0); }); it("still writes 16-bit files when asked", () => { const b = encodeWav([0, 1, -1, 0.5, 2, -3, NaN, Infinity], 8000, 16); const v = new DataView(b.buffer); expect(v.getUint16(34, true)).toBe(16); const s = (i: number) => v.getInt16(44 + 2 * i, true); expect(s(0)).toBe(0); expect(s(1)).toBe(32767); expect(s(2)).toBe(-32767); expect(s(3)).toBe(16384); expect(s(4)).toBe(32767); expect(s(5)).toBe(-32767); expect(s(6)).toBe(0); expect(s(7)).toBe(0); }); });