fix(rtmg/web): reset loop band on swap to a different track#289
Open
seanhanca wants to merge 1 commit into
Open
fix(rtmg/web): reset loop band on swap to a different track#289seanhanca wants to merge 1 commit into
seanhanca wants to merge 1 commit into
Conversation
A drawn loop region (loopBand) is stored in coordinates measured against the current source. useFixtureSwap.run() swapped the player buffer in place but never cleared the band, so the worklet kept stale loopBandStart/End: on a shorter new track process() indexed the buffer out of bounds (pops / NaN); on a longer one the loop was musically misaligned. Clear the store band in the non-forced new-track path. That makes WaveformScrubBox's existing sync effect fire, which pushes clearLoopBand to the worklet and sendLoopBand(null, null) to the server — no new plumbing. Source-mode hotswaps (force=true) are the same song and keep the loop. Adds a focused unit test asserting loopBand is null after a non-forced swap and unchanged after a forced source-mode swap. Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bug
Issue tracker: "Edit loop length on upload" (Value Category = Bug).
A loop region (
loopBand) drawn over the current track carries over with stale frame coordinates when the user swaps/uploads a different track. On a shorter new track the worklet indexes the playback buffer out of bounds (pops / NaN); on a longer one the loop span is musically misaligned.Root cause (verified)
The loop region is never reset/re-clamped on a track swap:
usePerformanceStore.setLoopBandis the source of truth for the band, but nothing in the swap path clears it.setFixtureonly sets the name (store/usePerformanceStore.ts:719).useFixtureSwap.run()swaps the player buffer in place (session.player?.swap(...)) and never clears the band.WaveformScrubBox's effect that mirrors the band to the worklet + server only re-runs on[bandState, bandLoopEnabled, hasPlayer, player](components/Performance/WaveformScrubBox.tsx:384) — none change on a swap, so it never re-fires.swaphandler updatesframeCountbut leavesloopBandStart/Endat the OLD frame values (public/audio-worklet.js:119-128);process()readsregionEndfromloopBandEndwith no re-clamp (public/audio-worklet.js:272-276) → out-of-bounds indexing on a shorter track.Fix (minimal)
In
useFixtureSwap.run, inside the existing non-forced new-track block (if (!force)), clear the band:This reuses existing plumbing: clearing the store band makes
WaveformScrubBox's sync effect fire, which sendsclearLoopBandto the worklet andsendLoopBand(null, null)to the server. No new subsystem.Source-mode hotswaps (vocals ↔ instruments) use
force = true— the same song — and intentionally keep the loop.No-regression test
web/tests/unit/fixtureSwapLoopBand.test.tsdrives the real hook (stubbing React'suseEffect/useRef, exercising the real zustand stores + a fakeRemoteBackendthat echoesswap_ready) and asserts:loopBandis null after a non-forced swap to a different track.loopBandis unchanged after a forced source-mode (same-song) hotswap.Verified the test fails on the non-force case when the fix is reverted, and passes with it.
Verification
In
demos/realtime_motion_graph_web/web/:npx vitest run tests/unit/fixtureSwapLoopBand.test.ts→ 2 passednpm run typecheck→ cleannpm run build→ compiled successfully(Unrelated:
float16/sliceEpochsuites fail locally withMath.f16round is not a function— a Node-version artifact of the dev box, pre-existing and untouched by this change.)Made with Cursor