first commit
This commit is contained in:
123
docs/media/audio/audio-codecs/src/decode/decode-source.md
Normal file
123
docs/media/audio/audio-codecs/src/decode/decode-source.md
Normal file
@@ -0,0 +1,123 @@
|
||||
# `decode/decode-source`
|
||||
|
||||
Universal decode entry point — the single function callers use to turn
|
||||
any `Source` into a decoded `AudioDocument`.
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
`decodeSource` is the top-level public-facing decode API. Callers do
|
||||
not need to know about codec registries, format detection, or
|
||||
runtime-gated source resolution — they pass in a `Source` (string,
|
||||
URL, ArrayBuffer, Uint8Array, or ReadableStream) plus optional
|
||||
hints/callbacks, and receive a fully-decoded `AudioDocument` from the
|
||||
default registry (which ships every native + WASM codec).
|
||||
|
||||
The companion `progressiveDecode` provides the same surface but is the
|
||||
hook for future per-chunk-fed decoders that allow editing the
|
||||
document while decoding is still in progress. The current
|
||||
implementation falls back to a full-buffer decode for every codec
|
||||
because none of the native or WASM wrappers expose
|
||||
`createDecoder` factories yet — the contract is in place so a future
|
||||
streaming-aware codec can plug in without callers changing their
|
||||
code.
|
||||
|
||||
## Features
|
||||
|
||||
- Accepts any `Source` variant — bytes, URL, file path, stream.
|
||||
- Optional `opts.format` overrides detection (use when callers know
|
||||
the format and want to skip the magic-byte sniff).
|
||||
- Optional `opts.budget` projects required memory before allocating
|
||||
pages — if projection exceeds the budget the call aborts with
|
||||
`AUDIO_CODECS.BUDGET_EXCEEDED` carrying the projected and budgeted
|
||||
byte counts in `context`.
|
||||
- Optional `opts.signal` (AbortSignal) — checked before resolution,
|
||||
before format detection, and before page allocation. Aborts throw
|
||||
`AUDIO_CODECS.STREAM_ERROR`.
|
||||
- Optional `opts.notify()` fires once the first page is materialised;
|
||||
`opts.ondata(delta)` fires per decoded block delta. Useful for
|
||||
progress UI on long-running decodes.
|
||||
- Optional `opts.registry` lets callers inject a pre-configured
|
||||
`CodecRegistry` (e.g. with extra codecs) instead of using the
|
||||
default.
|
||||
- Zod-validated options — invalid `budget` (non-positive number) or
|
||||
any other schema violation throws `AUDIO_CODECS.INVALID_SOURCE` with
|
||||
the Zod issue list in `context`.
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { decodeSource } from "@suaveplan/audio-codecs/decode/decode-source";
|
||||
|
||||
const doc = await decodeSource(wavBytes);
|
||||
console.log(doc.sourceLength, doc.sampleRate);
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
Decode a stream with a memory budget, abort signal, and progress
|
||||
callbacks:
|
||||
|
||||
```ts
|
||||
import { decodeSource } from "@suaveplan/audio-codecs/decode/decode-source";
|
||||
|
||||
const ctrl = new AbortController();
|
||||
const ui = makeProgressUi();
|
||||
|
||||
const doc = await decodeSource(
|
||||
fetch("https://cdn/audio.flac").then((r) => r.body!),
|
||||
{
|
||||
budget: 500 * 1024 * 1024, // 500 MB cap
|
||||
signal: ctrl.signal,
|
||||
notify: () => ui.startedDecoding(),
|
||||
ondata: ({ samples }) => ui.updateProgress(samples),
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `interface DecodeSourceOpts { format?, budget?, signal?, notify?,
|
||||
ondata?, registry? }`.
|
||||
- `const DecodeSourceOptsSchema` — Zod schema for the options object.
|
||||
- `async function decodeSource(source: Source, opts?:
|
||||
DecodeSourceOpts): Promise<AudioDocument>` — throws
|
||||
`INVALID_SOURCE` for invalid options or unrecognised source values;
|
||||
`UNKNOWN_FORMAT` if detection finds no codec and `opts.format` is
|
||||
also missing; `BUDGET_EXCEEDED` if projected memory exceeds
|
||||
`opts.budget`; `STREAM_ERROR` for AbortSignal cancellation.
|
||||
- `async function progressiveDecode(source, opts?, registry?):
|
||||
Promise<AudioDocument>` — same surface as `decodeSource` plus an
|
||||
optional positional `registry` for callers that prefer not to pass
|
||||
it via `opts.registry`.
|
||||
- `re-export CodecRegistry` — convenience so consumers needing custom
|
||||
codec registration can import it from the same subpath.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- The default registry is constructed lazily via a top-level promise
|
||||
(`DEFAULT_REGISTRY_PROMISE`) so the side-effects of registering ten
|
||||
codecs only happen the first time the registry is needed. Imports
|
||||
of the package barrel itself don't trigger codec registration.
|
||||
- `opts.signal` is checked at every coarse-grained boundary —
|
||||
before resolution, after registry availability, before detection.
|
||||
Codec-internal aborts are codec-specific and not covered by this
|
||||
function.
|
||||
- The budget projection uses `sampleRate * channels * sampleCount * 4`
|
||||
(4 bytes per float32 sample) as an upper bound. For compressed
|
||||
sources the actual decoded size depends on the codec's expansion
|
||||
ratio; the projection assumes a conservative 5× expansion of input
|
||||
bytes which catches the common cases (MP3, FLAC, Opus all
|
||||
decompress within 5×) without false positives for raw WAV.
|
||||
- `progressiveDecode` is currently equivalent to `decodeSource` —
|
||||
the streaming-page-fill behaviour described in the spec
|
||||
("editable before decode completes") requires codec `createDecoder`
|
||||
factories which only WAV currently exposes. The function name and
|
||||
signature reserve the contract so future streaming-aware codecs
|
||||
drop in without API changes.
|
||||
- Both functions are async — even when the input is fully in-memory,
|
||||
format detection and codec dispatch involve at least one microtask
|
||||
boundary because the codec methods are async.
|
||||
Reference in New Issue
Block a user