diff --git a/COMPLETED.md b/COMPLETED.md index a43c5b2..8e5a987 100644 --- a/COMPLETED.md +++ b/COMPLETED.md @@ -6,6 +6,22 @@ Newest entries at the top. Group by phase/wave header (mirroring `PLAN.md` / `CM --- +## Phase 1.2 — Audio format diversity + +**Landed:** 2026-06-11 on dev (all three waves complete). + +- **What:** Today `AudioProcessor`, `WavOffsetService`, and the JS decoder are PCM/WAV-only. `MimeTypeExtensions` already maps MP3, FLAC, Ogg, AAC, M4A — none are wired. +- **Why it matters:** WAV-only is a real ceiling for any non-internal release. Distribution-grade formats (MP3, FLAC at minimum) are table stakes for a music site. +- **Shape:** Two seams need a strategy pattern. + - Server side: replace `AudioProcessor.ProcessWavFileAsync` with a format-router that selects a per-format processor; replace `WavOffsetService` with a per-format offset strategy (some formats — MP3, Ogg — have natural frame boundaries; FLAC has block headers; AAC has ADTS). + - Client side: the JS decoder is currently a WAV byte-walker. For non-WAV, the simplest path is `decodeAudioData` over the full payload (loses streaming-start). The richer path is per-format chunked decoders. Worth a design pass before committing. +- **Prerequisite:** None functionally, but consider settling **Phase 4 (HTTP Range)** first — native range/cache is much more important for large MP3s than for WAVs. +- **Constraint:** Spectrum FFT tap currently relies on raw `AudioBuffer`s through `decodeAudioData`. If a future path uses `MediaElementAudioSourceNode` (see 4.1), the FFT tap still works but the early-playback story changes. + +**Completion note:** Fully landed across three waves on 2026-06-11. Server upload now accepts .wav/.mp3/.flac via `AudioProcessorRouter`. Client `StreamDecoder` is format-agnostic; `Mp3FormatDecoder` and `FlacFormatDecoder` provide chunked streaming with frame-boundary alignment and seek. Factory routing in `AudioPlayer.createFormatDecoder` selects decoder by Content-Type. + +--- + ## Phase 7 — Shared UI Components ### 7.1 ParallaxImage component diff --git a/PLAN.md b/PLAN.md index 647162d..5c04c51 100644 --- a/PLAN.md +++ b/PLAN.md @@ -23,17 +23,6 @@ What this means for the roadmap: the streaming substrate is solid. Future work c These were flagged during the audit but classified as feature work, not defect fixes. They are listed in rough order of user-visible impact. -### 1.2 Audio format diversity - -- **What:** Today `AudioProcessor`, `WavOffsetService`, and the JS decoder are PCM/WAV-only. `MimeTypeExtensions` already maps MP3, FLAC, Ogg, AAC, M4A — none are wired. -- **Why it matters:** WAV-only is a real ceiling for any non-internal release. Distribution-grade formats (MP3, FLAC at minimum) are table stakes for a music site. -- **Shape:** Two seams need a strategy pattern. - - Server side: replace `AudioProcessor.ProcessWavFileAsync` with a format-router that selects a per-format processor; replace `WavOffsetService` with a per-format offset strategy (some formats — MP3, Ogg — have natural frame boundaries; FLAC has block headers; AAC has ADTS). - - Client side: the JS decoder is currently a WAV byte-walker. For non-WAV, the simplest path is `decodeAudioData` over the full payload (loses streaming-start). The richer path is per-format chunked decoders. Worth a design pass before committing. -- **Prerequisite:** None functionally, but consider settling **Phase 4 (HTTP Range)** first — native range/cache is much more important for large MP3s than for WAVs. -- **Constraint:** Spectrum FFT tap currently relies on raw `AudioBuffer`s through `decodeAudioData`. If a future path uses `MediaElementAudioSourceNode` (see 4.1), the FFT tap still works but the early-playback story changes. -- **Progress:** Wave 1 (foundation) landed on `dev` (2026-06-10). Format router (`Mp3AudioProcessor`, `FlacAudioProcessor`, `AudioProcessorRouter`) and client-side `IFormatDecoder` interface + `WavFormatDecoder` implementation are in place. `TrackContentService.AddTrackAsync` is the new format-agnostic primary method; `AddTrackFromWavAsync` is a shim. Client `StreamDecoder` is now format-agnostic; WAV-specific logic moved to `WavFormatDecoder`. Wave 2 (per-format chunked decoders) landed on `dev` (2026-06-11): `Mp3FormatDecoder` and `FlacFormatDecoder` are implemented modules at `DeepDrftPublic/Interop/audio/`; `IFormatDecoder.getAlignedSegmentSize` extended with optional `rawData` parameter for format-specific frame-boundary scanning; `StreamDecoder.tryDecodeNextSegment` updated to peek candidate bytes and pass them via `rawData`, using zero-copy `subarray` for segments. Wave 3 (wiring decoders into `AudioPlayer.createFormatDecoder` factory; end-to-end integration) pending. - ### 1.3 Preload / prefetch of the next track - **What:** No mechanism to begin the next track's stream during the tail of the current. Each play is a cold fetch.