first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,82 @@
# `decode-pipeline.ts`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
This module owns the pure logic of the decode pipeline: format sniffing
from magic bytes, the ffmpeg argument list that emits `f32le` interleaved
samples to a MEMFS scratch file, and the deinterleave step that produces
per-channel `Float32Array`s for the `DecodeResult` shape. The pipeline
runs entirely through the supplied `WorkerHost` so cancellation,
timeouts, and OOM detection are inherited from a single source of
truth.
## Features
- `sniffFormat(bytes)` recognises WAV, MP3 (ID3v2 + frame-sync), Ogg
(Vorbis vs Opus by inspecting the bos packet), FLAC, AAC ADTS, and
WebM/EBML headers.
- `deinterleave(samples, channels)` returns `channels` equal-length
`Float32Array`s.
- `runDecode(opts)` orchestrates writeFile → run → readFile via
`WorkerHost.submitFfmpeg` and returns a normalised `DecodeResult`.
- Default sample rate (48 000) and channel count (2) for callers that
do not pre-probe their input.
## Usage: Basic
```ts
import { runDecode } from "@suaveplan/audio-codec-ffmpeg-wasm/decode/decode-pipeline";
const result = await runDecode({ host, bytes, format: "wav" });
console.log(result.channelData.length); // channel count
console.log(result.channelData[0].length); // frame count
console.log(result.sampleRate);
```
## Usage: Advanced
```ts
import {
runDecode,
sniffFormat,
deinterleave,
} from "@suaveplan/audio-codec-ffmpeg-wasm/decode/decode-pipeline";
const fmt = sniffFormat(bytes);
if (!fmt) throw new Error("unsupported");
const result = await runDecode({
host,
bytes,
format: fmt as "wav" | "mp3" | "ogg" | "opus" | "flac" | "aac" | "webm",
sampleRate: 44_100,
channels: 1,
timeoutMs: 30_000,
signal: controller.signal,
});
// Drop a deinterleaved view for downstream processing
const ch = deinterleave(new Float32Array([0, 1, 2, 3]), 2);
```
## API Reference
- `DEFAULT_SAMPLE_RATE: 48_000`.
- `DEFAULT_CHANNELS: 2`.
- `sniffFormat(bytes: Uint8Array): string | undefined`.
- `deinterleave(interleaved: Float32Array, channels: number): Float32Array[]`.
- `runDecode(opts: DecodePipelineOptions): Promise<DecodeResult>`.
## Implementation Notes
The deinterleave step copies the raw `Uint8Array` through a `Float32Array`
view to honour the f32le wire layout and then takes a `.slice()` so the
returned arrays own their own backing buffer — callers can transfer or
mutate them without aliasing the worker output. The pipeline never
silently catches MEMFS cleanup failures here; the host's `submitFfmpeg`
handles try/finally cleanup and logs any delete failures via the
injected logger. A non-zero ffmpeg exit is mapped to
`AUDIO_CODEC_FFMPEG_WASM.DECODE_FAILED` inside the worker host so this
module never sees it directly.