Skip to content

Playout change-detection hash omits activeTakeId (latent; will affect Multi-Take Recording) #22

Description

@develephant

Playout change-detection hash omits activeTakeId (latent; will affect Multi-Take Recording)

What

In app/[locale]/compose/page.tsx, the hash that triggers rescheduling doesn't include activeTakeId:

return `${c.id}:${c.startBar}:${c.lengthBars}:${c.instrumentPreset || ''}:${noteHash}`;

That hash drives the useEffect which calls scheduleClips(). If a clip's activeTakeId changes but its position and length don't, the hash is unchanged, no reschedule happens, and playoutManager keeps the previously scheduled Tone.Player — which still holds the old take's audio buffer.

Not currently reproducible

I want to be upfront: I don't think any user action can trigger this today. All three writes to activeTakeId happen on a clip created immediately beforehand:

  • lib/audio/recording-manager.ts:303 (after addClip on :279)
  • components/compose/TrackList.tsx:1505 and :1569 (after addClip in the drop handlers)

In each case project.clips.length changes, which is a separate dependency of the same effect, so rescheduling happens anyway.

Why it seems worth fixing anyway

Multi-Take Recording ("record multiple takes and comp the best parts") is on the roadmap, and swapping the active take on an existing clip is exactly the operation this misses. The failure mode is unpleasant to debug: the timeline waveform and the waveform editor both read activeTakeId directly and show the new take, while playback continues producing the old one. Everything looks correct and sounds wrong.

I hit this in a fork where I regenerate audio into an existing clip, which is why I noticed it. Took a while to find, since audio disposal in playoutManager.unscheduleClip() is correct — the reschedule simply never gets requested.

Suggested fix

-        return `${c.id}:${c.startBar}:${c.lengthBars}:${c.instrumentPreset || ''}:${noteHash}`;
+        return `${c.id}:${c.startBar}:${c.lengthBars}:${c.activeTakeId || ''}:${c.instrumentPreset || ''}:${noteHash}`;

Happy to open a PR, or leave it for whoever builds comping — entirely your call. Filing it mainly so it's written down somewhere before it costs someone an afternoon.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions