Initial Commit

This commit is contained in:
2026-05-27 23:47:53 +01:00
parent fbc70f96e6
commit 9b28db724f
18103 changed files with 1600554 additions and 0 deletions

View File

@@ -0,0 +1,156 @@
/**
* Programmatic WAV fixture builders used by the test suite. No binary files
* are checked in — every fixture is generated deterministically from
* primitives at test time. Each builder returns a `Uint8Array` ready to be
* fed to `decodeWav` or `createWavStreamDecoder`.
*/
export interface BuildWavInput {
readonly sampleRate: number;
readonly channels: number;
readonly bitsPerSample: number;
readonly samplesPerChannel: number;
/** `1` for integer PCM, `3` for IEEE float PCM. */
readonly formatCode: 1 | 3;
/** Per-channel sample generator. Defaults to silence. */
readonly sampler?: (channel: number, index: number) => number;
}
/** Build a well-formed RIFF/WAVE byte buffer. */
export function buildWav(input: BuildWavInput): Uint8Array {
const {
sampleRate,
channels,
bitsPerSample,
samplesPerChannel,
formatCode,
sampler = () => 0,
} = input;
const bytesPerSample = bitsPerSample / 8;
const dataBytes = samplesPerChannel * channels * bytesPerSample;
const headerBytes = 44;
const buffer = new Uint8Array(headerBytes + dataBytes);
const dv = new DataView(buffer.buffer);
writeAscii(buffer, 0, "RIFF");
dv.setUint32(4, headerBytes - 8 + dataBytes, true);
writeAscii(buffer, 8, "WAVE");
writeAscii(buffer, 12, "fmt ");
dv.setUint32(16, 16, true);
dv.setUint16(20, formatCode, true);
dv.setUint16(22, channels, true);
dv.setUint32(24, sampleRate, true);
dv.setUint32(28, sampleRate * channels * bytesPerSample, true);
dv.setUint16(32, channels * bytesPerSample, true);
dv.setUint16(34, bitsPerSample, true);
writeAscii(buffer, 36, "data");
dv.setUint32(40, dataBytes, true);
let p = headerBytes;
for (let i = 0; i < samplesPerChannel; i++) {
for (let c = 0; c < channels; c++) {
const v = sampler(c, i);
p += writeSample(dv, p, v, bitsPerSample, formatCode);
}
}
return buffer;
}
function writeAscii(b: Uint8Array, off: number, s: string): void {
for (let i = 0; i < s.length; i++) b[off + i] = s.charCodeAt(i);
}
function writeSample(
dv: DataView,
pos: number,
value: number,
bits: number,
fmt: 1 | 3
): number {
if (fmt === 3) {
if (bits === 32) {
dv.setFloat32(pos, value, true);
return 4;
}
dv.setFloat64(pos, value, true);
return 8;
}
if (bits === 16) {
const clipped = clip(value);
const v = Math.round(clipped < 0 ? clipped * 32768 : clipped * 32767);
dv.setInt16(pos, v, true);
return 2;
}
if (bits === 24) {
const clipped = clip(value);
const v = Math.round(
clipped < 0 ? clipped * 8388608 : clipped * 8388607
);
dv.setUint8(pos, v & 0xff);
dv.setUint8(pos + 1, (v >> 8) & 0xff);
dv.setUint8(pos + 2, (v >> 16) & 0xff);
return 3;
}
const clipped = clip(value);
const v = Math.round(
clipped < 0 ? clipped * 2147483648 : clipped * 2147483647
);
dv.setInt32(pos, v, true);
return 4;
}
function clip(v: number): number {
if (v > 1) return 1;
if (v < -1) return -1;
return v;
}
/** Build an A-law WAV header — the body is silence; we only verify rejection. */
export function buildAlawWav(): Uint8Array {
const dataBytes = 32;
const buffer = new Uint8Array(44 + dataBytes);
const dv = new DataView(buffer.buffer);
writeAscii(buffer, 0, "RIFF");
dv.setUint32(4, 36 + dataBytes, true);
writeAscii(buffer, 8, "WAVE");
writeAscii(buffer, 12, "fmt ");
dv.setUint32(16, 16, true);
dv.setUint16(20, 6, true); // A-law format code
dv.setUint16(22, 1, true);
dv.setUint32(24, 8000, true);
dv.setUint32(28, 8000, true);
dv.setUint16(32, 1, true);
dv.setUint16(34, 8, true);
writeAscii(buffer, 36, "data");
dv.setUint32(40, dataBytes, true);
return buffer;
}
/** Build a WAV whose `data` chunk declares double the bytes present. */
export function buildTruncatedWav(): Uint8Array {
const real = buildWav({
sampleRate: 8000,
channels: 1,
bitsPerSample: 16,
samplesPerChannel: 100,
formatCode: 1,
});
const dv = new DataView(real.buffer);
const declared = dv.getUint32(40, true);
dv.setUint32(40, declared * 2, true);
return real;
}
/** Build a buffer whose first 4 bytes are zeroed (no RIFF magic). */
export function buildCorruptHeaderWav(): Uint8Array {
const real = buildWav({
sampleRate: 8000,
channels: 1,
bitsPerSample: 16,
samplesPerChannel: 8,
formatCode: 1,
});
real[0] = 0;
real[1] = 0;
real[2] = 0;
real[3] = 0;
return real;
}