Problem
client/src/components/city/audio/citySynthMusic.js (~151-181) schedules chord changes (2400ms) and 16th-note arp plucks (150ms) with raw setInterval reading ctx.currentTime at fire time. Independent JS timers with no audio-clock anchor drift under main-thread load — the exact bug class the shared client/src/lib/lookaheadTransport.js was built to fix (every sibling player uses it; see the "two clocks" rationale in metronome.js:3-6).
Decision
Migrate the module onto createLookaheadTransport (or absolute ctx.currentTime lookahead targets), keeping the generative behavior (random walk, mood chord sets) identical. The stop-click fix (gain ramp) ships separately in the better/bugs-perf PR — rebase on that.
Acceptance
- No raw setInterval scheduling of note events remains; arp stays phase-locked to chord changes; mute/unmute and soundscape switching still work
Problem
client/src/components/city/audio/citySynthMusic.js(~151-181) schedules chord changes (2400ms) and 16th-note arp plucks (150ms) with raw setInterval reading ctx.currentTime at fire time. Independent JS timers with no audio-clock anchor drift under main-thread load — the exact bug class the sharedclient/src/lib/lookaheadTransport.jswas built to fix (every sibling player uses it; see the "two clocks" rationale in metronome.js:3-6).Decision
Migrate the module onto
createLookaheadTransport(or absolute ctx.currentTime lookahead targets), keeping the generative behavior (random walk, mood chord sets) identical. The stop-click fix (gain ramp) ships separately in the better/bugs-perf PR — rebase on that.Acceptance