Skip to content

perf(audio-runtime): centralize frame scheduling and deduplicate audio loading #117

Description

@codeacme17

Parent

#114

Summary

Introduce a cancellable real-time scheduling primitive for audio-driven hooks and deduplicate repeated audio fetch and decode work.

Echo UI currently allows individual hooks to create unrestricted animation loops and allows multiple consumers of the same audio URL to download and decode identical data independently. This issue establishes the shared runtime behavior needed by the real-time visualizer and waveform follow-up work.

Scope

Frame scheduling

  • Define a reusable scheduler for audio-driven UI updates.
  • Guarantee no more than one pending animation-frame callback per scheduler instance.
  • Support an explicit maximum publication rate independently from the audio sampling rate.
  • Stop scheduling immediately after an error, cancellation, or unmount.
  • Pause or substantially reduce UI work while the document is hidden.
  • Avoid publishing values that have not changed meaningfully.
  • Keep scheduler callbacks and lifecycle behavior stable across React renders.
  • Apply the new behavior to playback-progress updates as the first production integration.
  • Preserve access to underlying Tone nodes and the current public hook behavior.

Audio loading and decoding

  • Deduplicate concurrent requests for the same audio resource.
  • Reuse in-flight fetch and decode work when lifecycle semantics permit it.
  • Provide an explicit cache ownership and invalidation strategy.
  • Avoid creating a new decoding context for every identical request.
  • Preserve request-version handling so a stale request cannot overwrite a newer result.
  • Preserve AbortSignal behavior for individual consumers.
  • Ensure failed or aborted requests are not retained as successful cache entries.
  • Document whether shared caching is default, opt-in, or configurable.

Acceptance criteria

  • A scheduler instance never has more than one pending animation-frame callback.
  • Unmounting cancels every pending frame, timer, observer, and subscription owned by the runtime.
  • An exception in a sampling or publication callback stops the associated loop and follows the documented error path.
  • Hidden-document behavior is covered by an automated test.
  • Playback progress has a documented maximum UI update rate.
  • Audio sampling and React publication can run at different rates.
  • Stable sampled values do not cause redundant React updates.
  • Concurrent consumers of the same URL can share one in-flight download and decode operation.
  • Aborting one consumer does not incorrectly cancel other active consumers.
  • Failed and aborted operations are retryable.
  • Cache invalidation and memory-lifetime behavior are documented and tested.
  • Existing playback, seek, loop, error, and cancellation semantics remain compatible.

Recommended defaults

  • Player progress: 15–30 UI updates per second.
  • Real-time visualizers: up to 30 UI updates per second unless a component has a justified higher rate.
  • Work should pause while the document is hidden unless continuing is explicitly required.

Out of scope

  • Rewriting Oscilloscope, Spectrogram, or VU Meter rendering.
  • Waveform peak extraction and rendering.
  • A general-purpose application data cache.
  • Changing the public ownership model without documentation and compatibility coverage.

Validation

  • Test normal playback, pause, seek, loop, error, source replacement, unmount, and visibility changes.
  • Test two or more simultaneous consumers of the same audio URL.
  • Test cancellation races and failed decode retries.
  • Use the performance harness to verify pending-frame and redundant-update behavior.

Dependencies

Blocked by: #115.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions