# Tasks: enterprise-audio-engine-browser **Change ID**: enterprise-audio-engine-browser **Package**: `@suaveplan/audio-engine-browser` **Target path**: `packages/audio/audio-engine-browser` **Prerequisite packages on Verdaccio**: `@suaveplan/audio-core`, `@suaveplan/audio-timeline`, `@suaveplan/audio-transport`, `@suaveplan/audio-fx-plugin-base`, `@suaveplan/error`, `@suaveplan/events` --- ## 1. Scaffold - [ ] Create directory `packages/audio/audio-engine-browser/` with `src/`, `tests/`, `src/__benchmarks__/`, and all feature subdirectories per the layout in `proposal.md`. - [ ] Write `package.json` at version `0.1.0` with `"type": "module"`, `"sideEffects": false`, full `exports` map, deps: `@suaveplan/audio-core workspace:^`, `@suaveplan/audio-timeline workspace:^`, `@suaveplan/audio-transport workspace:^`, `@suaveplan/audio-fx-plugin-base workspace:^`, `@suaveplan/error workspace:^`, `@suaveplan/events workspace:^`, `standardized-audio-context`. - [ ] Write `tsconfig.json` extending `@suaveplan/typescript-config/library.json`. - [ ] Write `vitest.config.ts` using `createTestConfig()` from `@suaveplan/testing/config` with `happy-dom` environment. - [ ] Add `lint`, `typecheck`, `test`, `test:coverage`, `build`, `docs:check` scripts. --- ## 2. Types + errors - [ ] Write `src/adapter/browser-adapter.types.ts` — `BrowserAdapterOptions`. - [ ] Write `src/graph/web-audio-graph.types.ts` — `AudioGraphSnapshot`, `AudioNodeType`. - [ ] Write `src/worklet/worklet-manager.types.ts` — `WorkletManagerOptions`, `WorkletModuleOptions`. - [ ] Write co-located `.md` files for each types module (≥200 words). - [ ] Write `src/error-codes.ts` — `defineCodes("AUDIO_ENGINE_BROWSER", [...])` producing `AUDIO_ENGINE_BROWSER.*` code strings; export `BrowserAudioErrorCode`, `AUDIO_ENGINE_BROWSER_ERROR_METADATA`, `registerBrowserAudioErrorCodes()`, and a `BrowserAudioError` class extending `AudioError` from `@suaveplan/audio-core`. - [ ] Write Zod schemas: `BrowserAdapterOptionsSchema`, `WorkletManagerOptionsSchema`, `WorkletModuleOptionsSchema`, `AudioGraphSnapshotSchema`. --- ## 3. WebAudioGraph - [ ] Implement `WebAudioGraph` in `src/graph/web-audio-graph.ts`: - `addNode`, `removeNode` with ID-based registry. - `connect` / `disconnect` wrapping `AudioNode.connect` / `disconnect`. - `snapshot()` returns serializable `AudioGraphSnapshot`. - `restore(snapshot)` recreates nodes and connections from a snapshot. - [ ] Write `web-audio-graph.test.ts` and `web-audio-graph.md`. --- ## 4. AudioWorkletManager - [ ] Implement `AudioWorkletManager` in `src/worklet/worklet-manager.ts`: - `addModule` with URL allow-list check. - `createNode` returns `AudioWorkletNode`. - `postMessage` / `onMessage` for processor communication. - `isLoaded` tracks loaded module URLs. - [ ] Write `worklet-manager.test.ts` and `worklet-manager.md`. --- ## 5. Html5AudioFallback - [ ] Implement `Html5AudioFallback` in `src/fallback/html5-fallback.ts`: - Implements `TimelineAdapter` using `HTMLAudioElement`. - Supports: play, pause, seek, volume, loop. - No FX, no analysis, no precise scheduling. - All other adapter methods are no-ops or throw `BrowserAudioError` for unsupported operations. - [ ] Write `html5-fallback.test.ts` and `html5-fallback.md`. --- ## 6. BrowserTimelineAdapter - [ ] Implement `BrowserTimelineAdapter` in `src/adapter/browser-adapter.ts`: - `init()` creates `AudioContext` via `standardized-audio-context` (or uses injected `context`) and resumes it. - `setTracks`, `addTrack`, `removeTrack`, `updateTrack` build per-track subgraphs: `AudioBufferSourceNode` → `GainNode` (clip) → `GainNode` (track) → `StereoPannerNode` → `DynamicsCompressorNode` → `GainNode` (master) → `AnalyserNode` → destination. - `play`, `pause`, `stop`, `seek` drive `AudioBufferSourceNode` scheduling. - Mute/solo logic: when any track is soloed, all non-soloed tracks have gain set to 0. - `setLoop`, `setMasterVolume`, `setTrackVolume`, `setTrackMute`, `setTrackSolo`, `setTrackPan`, `setTempo` update graph parameters. - `lookAhead` and `ppqn` exposed as readonly properties. - `dispose()` closes context and releases all nodes. - [ ] Write `browser-adapter.test.ts` (≤500 lines): init with injected `OfflineAudioContext`, set tracks, play/stop, track volume/pan, mute/solo logic, loop, dispose. - [ ] Write `browser-adapter.md`. --- ## 7. Offline render - [ ] Implement `renderOffline` in `src/offline/offline-render.ts`: - Creates `OfflineAudioContext` via `standardized-audio-context`. - Instantiates `BrowserTimelineAdapter` with injected offline context. - Attaches adapter to `TimelineEngine`, plays from 0, and returns rendered `AudioBuffer`. - [ ] Write `offline-render.test.ts` and `offline-render.md`. --- ## 8. FX plugin hosting - [ ] Implement `createFxNode` utility in `src/adapter/browser-adapter.ts` (or separate `fx-host.ts` if needed): - **AudioNode path**: `plugin.createAudioNode(context)` returns native `AudioNode` chain. - **Worklet path**: `plugin.createWorkletProcessor()` returns processor code; host wraps in `AudioWorkletNode` via `AudioWorkletManager`. - **Fallback path**: `ScriptProcessorNode` wrapping block processor for main-thread fallback. - [ ] Write unit tests for all three FX hosting paths. --- ## 9. Benchmarks - [ ] Write `src/__benchmarks__/graph.bench.ts` — add 100 nodes, connect 200 edges, snapshot + restore. - [ ] Write `src/__benchmarks__/worklet.bench.ts` — load 10 worklet modules, create 50 nodes. --- ## 10. Integration tests - [ ] Write `tests/integration.test.ts` — full browser adapter lifecycle with injected `OfflineAudioContext`: init, set tracks with clips, play, verify graph structure, mute/solo behavior, offline render returns `AudioBuffer` with expected length. --- ## 11. Docs + verify + publish - [ ] All co-located `.md` files (≥200 words each). - [ ] Write `README.md` at package root. - [ ] `bunx turbo lint typecheck test --filter=@suaveplan/audio-engine-browser` — green. - [ ] `bunx turbo test:coverage --filter=@suaveplan/audio-engine-browser` — 100%. - [ ] `bun scripts/publish.ts --package @suaveplan/audio-engine-browser`. - [ ] Fold `specs/audio-engine-browser/spec.md` into `openspec/specs/audio-engine-browser/spec.md`. - [ ] Archive to `openspec/archive/2026-05-14-enterprise-audio-engine-browser/`.