# `utils/inspect` _(no submodules)_ ## Purpose `inspectWavHeader(bytes)` is the wrapper-layer pre-scan that classifies a WAV byte buffer **before** the upstream `@audio/decode-wav` library is invoked. The upstream library throws an undifferentiated `TypeError` for "Not a WAV file", unsupported formats and missing chunks, so the wrapper's spec requirement to distinguish `CORRUPT_HEADER`, `TRUNCATED_BODY` and `UNSUPPORTED_FORMAT` is satisfied here, in pure JavaScript, without speculative decoding. The function returns a tagged-union result and never throws. ## Features - Walks the RIFF chunk list (`fmt`, `data`, plus any auxiliary chunks) without allocating. - Distinguishes `corrupt` (RIFF/WAVE magic missing, fmt chunk too short, no data chunk, non-progressing chunk size, data-before-fmt) from `truncated` (data chunk declares more bytes than the buffer holds) from `unsupported` (format code recognised but non-PCM/non-IEEE-float). - Recognises seven WAV format codes: PCM (`0x0001`), MS-ADPCM (`0x0002`), IEEE float (`0x0003`), A-law (`0x0006`), μ-law (`0x0007`), IMA-ADPCM (`0x0011`), WAVE_FORMAT_EXTENSIBLE (`0xFFFE`). Unknown codes map to `format: "unknown"`. - Honours odd-byte padding inside the chunk walk (every chunk's `size & 1` adds a pad byte before the next chunk). ## Usage: Basic ```ts import { inspectWavHeader } from "@suaveplan/audio-decode-wav"; const result = inspectWavHeader(wavBytes); if (result.kind === "ok") { console.log(result.sampleRate, result.channels, result.bitsPerSample); } ``` ## Usage: Advanced ```ts import { inspectWavHeader } from "@suaveplan/audio-decode-wav"; function summarise(bytes: Uint8Array): string { const r = inspectWavHeader(bytes); switch (r.kind) { case "ok": return `${r.channels} ch @ ${r.sampleRate} Hz, ${r.bitsPerSample}-bit, data=${r.dataBytesDeclared}`; case "truncated": return `truncated: ${r.bytesAvailable}/${r.bytesDeclared}`; case "unsupported": return `unsupported: ${r.format}`; case "corrupt": return `corrupt: ${r.reason}`; } } ``` ## API Reference - `function inspectWavHeader(bytes: Uint8Array): InspectResult` — never throws. - `type InspectResult = InspectOk | InspectCorrupt | InspectTruncated | InspectUnsupported`. - `interface InspectOk` — `{ kind: "ok"; sampleRate; channels; bitsPerSample; dataStart; dataBytesDeclared }`. - `interface InspectCorrupt` — `{ kind: "corrupt"; reason: string }`. - `interface InspectTruncated` — `{ kind: "truncated"; bytesAvailable; bytesDeclared }`. - `interface InspectUnsupported` — `{ kind: "unsupported"; format: AudioFormatType }`. ## Implementation Notes The function reads chunk identifiers as ASCII via `String.fromCharCode` rather than decoding UTF-8 — RIFF chunk IDs are guaranteed ASCII per the spec, so this is faster and avoids host text-decoder dependencies. The buffer-overrun guard (`pos + 8 + chunkSize > bytes.length`) catches both a too-short `fmt` chunk and a malformed `data` chunk before the upstream library has a chance to throw. The order of checks matters: `fmt` must precede `data`, so a `data`-before-`fmt` layout is classified `corrupt`, not `truncated`.