feat(editor): clickable, audible keyboard gutter in the piano roll - #128
Conversation
… keyboard DAW roadmap 4.1. In keys/piano view the left note-label column is now rendered as an actual keyboard laid on its side, and clicking a key auditions its pitch. - drawPianoLabels rewritten: white/black key shading per row (black keys inset from the front edge so the white tails read between them, the side-on keyboard look), C rows labelled with their octave, white-white separators only at E–F / B–C, and a front-edge divider. String view is untouched (it keeps its string labels). - midiToFreq (equal temperament, A4=440; 0 for non-finite) + _auditionPitch: a gentle, hearing-safe voice (soft attack, ~0.28 peak, ~0.32s decay) through the existing master limiter — the edit-blip envelope, pitched and a touch longer. No-op until the audio context is running (autoplay-gated) and for inaudibly-high pitches. - onMouseDown routes a left-click in the LABEL_W gutter (keys mode only) to _auditionPitch(yToMidi(y)) via the pure _inKeyboardGutterPure region test, and returns — no selection, no edit. Right-click still opens the menu. Tests: tests/keyboard_gutter.test.js (10) — midiToFreq temperament + non-finite guard, the gutter hit region's half-open edges, and _auditionPitch's autoplay guard + single-voice-at-pitch scheduling + inaudible-pitch refusal. 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: 31 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 (2)
📝 WalkthroughWalkthroughAdds a real keyboard gutter to the piano roll, with MIDI-to-frequency helpers, pitch audition on left-click, double-click suppression in the gutter, runtime tests, and a changelog update. ChangesKeyboard gutter and pitch audition
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant drawNotes
participant _auditionPitch
participant AudioContext
User->>drawNotes: left-click inside keyboard gutter
drawNotes->>_auditionPitch: audition pitch(midi)
_auditionPitch->>AudioContext: check state running
alt context not running or invalid frequency
_auditionPitch-->>drawNotes: no-op
else context running and audible range
_auditionPitch->>_auditionPitch: midiToFreq(midi)
_auditionPitch->>AudioContext: create triangle oscillator + gain envelope
_auditionPitch->>_auditionPitch: track guide voice, prune if over limit
end
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Guard onDblClick against the keyboard gutter: a double-click on a gutter key was falling through to showAddNote (hitNote miss -> add-note dialog at time 0), silently authoring a note. The gutter is audition-only, so scope a keys-mode gutter early-return via _inKeyboardGutterPure. Adds a regression test that fails on pre-fix code. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@coderabbitai review |
✅ Action performedReview finished.
|
…gutter # Conflicts: # CHANGELOG.md
DAW roadmap 4.1 (
SONG-EDITOR-DAW-WORKSPACE-DESIGN.md§F4). Editor-only.What
In keys/piano view the piano roll's left axis was a flat dark strip with sparse C/F labels. It's now drawn as an actual keyboard laid on its side, and clicking a key auditions its pitch.
drawPianoLabelsrewritten): white/black key shading per MIDI row — black keys inset from the front (right) edge so the white keys' tails read between them, the side-on keyboard look — C rows labelled with their octave (C4…), white-to-white separators only where a real keyboard has no black key between (E–F, B–C), and a front-edge divider so the gutter reads as a panel. String view is untouched._auditionPitch+midiToFreq): a gentle, hearing-safe voice — soft 6 ms attack, ~0.28 peak, ~0.32 s decay — routed through the existing master limiter, i.e. the edit-blip envelope, pitched and a touch longer so it reads as a note.midiToFreqis equal-tempered (A4 = 440). No-op until the audio context is running (autoplay-gated), and for inaudibly-high pitches.onMouseDown): a left-click in theLABEL_Wgutter (keys mode only) →_auditionPitch(yToMidi(y))via the pure_inKeyboardGutterPureregion test, then returns — no selection, no note edit. Right-click still opens the context menu.Tests —
tests/keyboard_gutter.test.js(10, all fail on main)midiToFreqtemperament (A4/A5/A3/middle-C/E4) + non-finite → 0 guard; the gutter hit region's half-open edges (never overlaps the note area or the waveform/beat strips);_auditionPitchautoplay guard (no ctx / suspended → nothing scheduled), one-voice-at-pitch scheduling on a running ctx, and the inaudible-pitch refusal. Full JS suite green.Scope / fresh region
Touches the piano-roll left-axis render (
drawPianoLabels), a newmidiToFreq/_inKeyboardGutterPurepure block,_auditionPitchbeside_editBlipAt, and one branch inonMouseDown— none of which the open PRs (#112/#125/#126/#127) touch (#126's roll work was in_drawPianoNote, the note render, not the gutter). No core, no spec.Summary by CodeRabbit