docs(plan): Phase 18 OQ resolutions + VBR-safe accurate Opus seek model

This commit is contained in:
daniel-c-harvey
2026-06-23 05:26:58 -04:00
parent 6af6677a12
commit e3a4364b8c
3 changed files with 543 additions and 183 deletions
@@ -13,10 +13,15 @@ endpoint.
> (`product-notes/phase-18-opus-low-data-streaming.md`) — is a prerequisite that sequences ahead of
> windowing. Phase 21's windowing must work across **both** delivery formats (lossless WAV and Opus).
> Its C5 invariant below already anticipated this ("must not foreclose MP3/FLAC"); **Opus is now the
> concrete VBR/containerized driver of C5.** Windowing an Opus stream uses the decoder's *approximate*
> byte↔time mapping (`OpusFormatDecoder.calculateByteOffset` — Ogg-page interpolation), exactly the C5
> case — not the exact CBR-WAV `byteRate` math. Build the window machinery format-agnostically
> (§2 C3/C5) so it inherits Opus for free.
> concrete VBR/containerized driver of C5.** Windowing an Opus stream uses the decoder's **accurate
> index-based** byte↔time mapping (`OpusFormatDecoder.calculateByteOffset` — a binary search in the Phase 18
> precomputed seek index), exactly the C5 case — *not* the exact CBR-WAV `byteRate` math, and *not*
> approximate Ogg-page interpolation. **Correction (Daniel, 2026-06-23):** an earlier draft described the
> Opus mapping as "approximate page interpolation"; the Phase 18 seek-model resolution rejected that — Opus
> seeking is **accurate**, backed by a precomputed seek index built at transcode time, so refill resolves to
> the *exact* page offset. The windowed refill controller calls the **same** index resolver an explicit seek
> does (Phase 18 §3.4a D); a window opening away from byte 0 still decodes via the Phase 18 sidecar setup
> header. Build the window machinery format-agnostically (§2 C3/C5) so it inherits Opus for free.
---
@@ -66,14 +71,20 @@ docs. This phase **modifies that seam** — so the contract it must preserve is
user-visible control, no change to seek/transport semantics beyond what the listener already
experiences. Seek must still feel identical.
- **C5 — Must window both delivery formats (WAV lossless AND Opus low-data).** Byte↔time mapping for
refill is exact and cheap for WAV (CBR: `byteRate` from the header). For VBR/containerized formats it
is approximate (the decoders carry TOC/SEEKTABLE/Ogg-page seek math). **Phase 18 (Opus) is sequenced
before this phase and is the concrete driver here:** an Ogg Opus 320 stream is VBR and page-paged, so
its `calculateByteOffset` is an *approximate* page-interpolation, not exact-offset. The window
machinery must express refill purely in terms of the decoder's existing `calculateByteOffset`, so the
same code windows WAV exactly and Opus approximately — **no WAV-special-cased offset math in the
window layer.** (MP3/FLAC decoders are already wired in the registry too — the registry dispatches on
content-type today; an `OpusFormatDecoder` joins them in Phase 18.)
refill is exact and cheap for WAV (CBR: `byteRate` from the header). **Phase 18 (Opus) is sequenced
before this phase and is the concrete VBR driver here** — and its mapping is **also exact**, but by a
different mechanism: an Ogg Opus 320 stream has no linear time↔byte relationship, so
`OpusFormatDecoder.calculateByteOffset` resolves via a **precomputed seek index** (granule→byte, built at
transcode; Phase 18 §3.4a), a binary search that returns the exact page offset — **not** an approximate
page interpolation. (An earlier draft of this invariant said "approximate"; the Phase 18 seek-model
resolution, Daniel 2026-06-23, made Opus seeking accurate. Corrected here.) The window machinery must
express refill purely in terms of the decoder's existing `calculateByteOffset`, so the same code windows
WAV (via `byteRate`) and Opus (via the index) — **no WAV-special-cased offset math in the window layer**,
and no approximation for either. A window that opens away from byte 0 must also prepend the decoder's
retained/sidecar setup header (Phase 18 §3.4a B) — the format-agnostic refill path already routes
continuations through the decoder's header-carry, so this comes for free. (MP3/FLAC decoders are already
wired in the registry too — the registry dispatches on content-type today; an `OpusFormatDecoder` joins
them in Phase 18.)
- **C6 — No regression to the single-instance JS decoder concurrency guarantees.** The current code is
careful that only one streaming loop touches the single JS `StreamDecoder` at a time
(`DrainActiveStreamingTaskAsync`, the `_streamingCancellation` identity dance). Windowed refill