3.7 KiB
adapter-track-ops
Purpose
adapter-track-ops packs every track-scoped mutation that the
BrowserTimelineAdapter exposes — adding, removing, updating, and the
five per-track setters (volume, mute, solo, pan, plus the chain
- subgraph teardown helper) — into pure functions that operate on an
explicit
TrackOpEnvrather than on adapter-private state. The adapter itself becomes a thin coordinator: it owns the lifecycle invariants and the lazy environment, and delegates the actual work here.
Pulling the work out of the class keeps browser-adapter.ts inside the
300-line hard cap and makes every track operation unit-testable by
passing a hand-built TrackOpEnv with deterministic state lambdas. The
adapter file still exposes the same public methods; readers should
follow the call chain to this module for the implementation.
Features
TrackOpEnvinterface — explicit dependency injection of the track map, graph, context, bus orchestrator, and the four lazy state accessors (currentTime,playState,masterVolume).addTrackImpl— builds the subgraph, constructs the chain, wires the latency-changed event, applies mixer + ambient state.releaseTrackImpl— symmetric teardown: dispose chain, tear down subgraph, drop from the map.updateTrackImpl,setTrack{Volume,Mute,Solo,Pan}Impl— small composable mutations sharing the same epilogue (mixer / ambient recompute).
Usage: Basic Example
import { addTrackImpl } from "@suaveplan/audio-engine-browser/adapter/adapter-track-ops";
addTrackImpl(env, track);
Usage: Advanced Example
import {
addTrackImpl,
releaseTrackImpl,
setTrackPanImpl,
setTrackVolumeImpl,
} from "@suaveplan/audio-engine-browser/adapter/adapter-track-ops";
addTrackImpl(env, track);
setTrackVolumeImpl(env, rec, 0.8);
setTrackPanImpl(env, rec, -0.3);
releaseTrackImpl(env, track.id);
API Reference
TrackOpEnv
interface TrackOpEnv {
tracks: Map<string, TrackRecord>;
graph: WebAudioGraph;
context: ContextLike;
busOrch: BusOrchestrator;
currentTime(): number;
playState(): "stopped" | "playing" | "paused";
masterVolume(): number;
}
addTrackImpl(env, track) → void
Builds the per-track subgraph, constructs a PluginChain bound to the
project's shared BusRegistry, subscribes to latency-changed, and
applies the mixer + ambient state.
releaseTrackImpl(env, trackId) → void
Removes the chain + subgraph for trackId. Idempotent for missing ids.
updateTrackImpl(env, rec, track) → void
Mutates the TrackRecord in place, refreshes the pan node, and
re-applies mixer + ambient state.
setTrackVolumeImpl / setTrackMuteImpl / setTrackSoloImpl / setTrackPanImpl
Single-purpose updaters. Each mutates the relevant fields and runs the
small epilogue: applyMixerState then applyAmbientForTrack.
Implementation Notes
- The OTel counter is module-scoped because every adapter shares the
same series; the adapter itself owns the
kind=fxincrement, and this module ownskind=track-subgraph(+7 per added track). TrackOpEnvaccessors are lambdas rather than direct fields so the adapter can pass() => this.currentTimewithout leakingthisbinding. This keeps the helpers callable from any code path (top-level, tests, future async restoration).releaseTrackImplswallows chain dispose errors so a misbehaving plugin disposal cannot prevent the subgraph teardown — the adapter invariant is "track must be fully released byremoveTrack".- Adding the same track id again replays the release path first, which
is how the adapter handles
updateTrackon a recreated chain shape.