Depends on #54 (seed for retry). Key gating depends on ADR-0024 (currently Proposed); BPM uses the existing gated beat detection (ADR-0010/0014/0025).
Problem
A generated pad/track lands at whatever tempo and key the model felt like. generateToPad already injects "N BPM" into the prompt for music loops (frontend/src/deck/useDeck.ts:1258-1264), but that is a hint, not a guarantee, and there is no key targeting at all (key detection is still ADR-0024, Proposed). So a generated loop often clashes with what is playing and gets discarded. With beat detection (and soon key) we can verify the generated clip and retry/snap until it fits — the generative-side cousin of harmonic auto-mix (#51).
Proposed approach
Target a BPM and key (taken from the other deck's gated estimate, or set manually); generate with those in the prompt; then measure the clip's actual BPM (existing beat path) and, once ADR-0024 lands, its key; if it is off by more than a tolerance, retry with a fresh seed (#54) and/or varispeed-snap the tempo (the M20 mechanism, ADR-0014). Honest gate (ADR-0010): if the target or the measurement is low-confidence, do not claim a match.
Acceptance criteria
- A user targets BPM (+ key when ADR-0024 lands); the delivered clip measures within tolerance of the target, or the UI honestly reports it could not (no false "matched").
- BPM uses the existing gated detector; key is gated behind ADR-0024's confidence (low confidence ⇒ no key claim).
- Retry uses fresh seeds; tempo snap reuses the M20 varispeed path rather than re-rendering when possible.
- Tests cover the verify-and-retry loop on known-BPM fixtures; strings via i18n; house style;
npx tsc -p tsconfig.app.json --noEmit clean.
Scope & non-goals
In scope: target → generate → verify → retry/snap for BPM and (gated) key. Non-goals: the plumbing (#54); building key detection (ADR-0024); steering the Magenta deck's key (#51); guaranteeing a musical key from an atonal/percussive prompt.
Depends on #54 (seed for retry). Key gating depends on ADR-0024 (currently Proposed); BPM uses the existing gated beat detection (ADR-0010/0014/0025).
Problem
A generated pad/track lands at whatever tempo and key the model felt like.
generateToPadalready injects "N BPM" into the prompt for music loops (frontend/src/deck/useDeck.ts:1258-1264), but that is a hint, not a guarantee, and there is no key targeting at all (key detection is still ADR-0024, Proposed). So a generated loop often clashes with what is playing and gets discarded. With beat detection (and soon key) we can verify the generated clip and retry/snap until it fits — the generative-side cousin of harmonic auto-mix (#51).Proposed approach
Target a BPM and key (taken from the other deck's gated estimate, or set manually); generate with those in the prompt; then measure the clip's actual BPM (existing beat path) and, once ADR-0024 lands, its key; if it is off by more than a tolerance, retry with a fresh seed (#54) and/or varispeed-snap the tempo (the M20 mechanism, ADR-0014). Honest gate (ADR-0010): if the target or the measurement is low-confidence, do not claim a match.
Acceptance criteria
npx tsc -p tsconfig.app.json --noEmitclean.Scope & non-goals
In scope: target → generate → verify → retry/snap for BPM and (gated) key. Non-goals: the plumbing (#54); building key detection (ADR-0024); steering the Magenta deck's key (#51); guaranteeing a musical key from an atonal/percussive prompt.