feat(editor): detect key from a part's notes (Krumhansl–Schmuckler) - #132
Conversation
DAW roadmap 4.17 (the passive-key third; sibling to the chord-at-cursor readout). A "Detect" button in the key controls guesses the current part's key and sets it. - @pure:key-detect: _detectKeyPure runs the Krumhansl–Schmuckler algorithm — PEARSON CORRELATION of a 12-bin pitch-class histogram against the standard major/minor key profiles, over all 24 keys. Correlation (not a raw dot product) is what makes the cross-mode comparison fair — the two profiles have different magnitudes — and makes a profile score 1.0 against its own key. Returns null for an empty or perfectly flat histogram (no tonal centre). - window.editorDetectKey builds the histogram from the active arrangement, resolving fretted parts to sounding pitch (capo/tuning via _rollMidiForNote + _rollPitchCtx) and keys parts to their packed pitch, duration-weighted with a small floor so staccato notes still count. Sets S.editorKey, turns the in-key highlight on, and reports the guess. A suggestion — the pickers stay editable. New Detect button in the key group. Tests: tests/key_detect.test.js (8) — exact profiles detect their own key (C major, G major, A minor via rotation), a textbook C-major distribution, uses-all-weights (shifting the histogram shifts the tonic by the same amount), degenerate → null (empty/all-zero/short/non-array/flat), single-pc, and the NaN/negative-bin guard. All fail on main. Full JS suite green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HzMBtxWnLGHYkMMXtK38Bg
|
Warning Review limit reached
Next review available in: 29 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughThis PR adds a key-detection feature: a pure Krumhansl–Kessler/Pearson-correlation algorithm ( ChangesKey Detection
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant DetectButton as Detect Button
participant editorDetectKey
participant _detectKeyPure
participant EditorState as Editor State/UI
User->>DetectButton: click
DetectButton->>editorDetectKey: editorDetectKey()
editorDetectKey->>editorDetectKey: build weighted pitch-class histogram from notes
editorDetectKey->>_detectKeyPure: pcWeights
_detectKeyPure-->>editorDetectKey: {tonic, scale, score} or null
editorDetectKey->>EditorState: update S.editorKey, enable highlighting, persist key
editorDetectKey->>EditorState: refresh key controls, redraw, set status message
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
@coderabbitai review |
✅ Action performedReview finished.
|
# Conflicts: # CHANGELOG.md # screen.js
DAW roadmap 4.17 — the passive-key third of the item, sibling to the chord-at-cursor readout (#130). Editor-only.
What
A new Detect button in the key controls guesses the current part's key from its pitch-class content and sets it, turning the in-key highlight on so you see the result immediately.
@pure:key-detect(_detectKeyPure): the Krumhansl–Schmuckler algorithm — Pearson correlation of a 12-bin pitch-class histogram against the standard major/minor key profiles, across all 24 keys. Correlation (not a raw dot product) is the load-bearing choice: the two profiles have different magnitudes, so a dot product would systematically favour one mode, and correlation makes a profile score a perfect 1.0 against its own key. Returnsnullfor an empty or perfectly flat histogram (no tonal centre) so the caller shows nothing.editorDetectKey: builds the histogram from the active arrangement — fretted parts resolved to sounding pitch (capo/tuning-aware via_rollMidiForNote+_rollPitchCtx), keys parts to their packed pitch — duration-weighted (a held note counts more than a passing one, with a small floor so staccato still registers). SetsS.editorKey, enables the highlight, and reports the guess. A suggestion — the tonic/scale pickers stay editable.Tests —
tests/key_detect.test.js(8, all fail on main)Exact profiles detect their own key (C major, G major, A minor via rotation); a textbook C-major distribution; uses-all-weights (shifting the histogram shifts the detected tonic by exactly the same amount); degenerate inputs →
null(empty / all-zero / short / non-array / flat); a single pitch class; and the NaN/negative-bin guard. Full JS suite green.Scope / fresh region
New
@pure:key-detectblock by@pure:scale, aneditorDetectKeyhandler by the other key handlers, and one HTML button. No core, no spec; independent of the chord-readout PR (#130) — different block, different control.Summary by CodeRabbit