Files
2026-05-27 23:29:53 +01:00

6.3 KiB

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/.