Skip to content

feat(metronome): beat click during normal playback - #22

Merged
byrongamatos merged 2 commits into
mainfrom
feat/metronome
Jul 17, 2026
Merged

feat(metronome): beat click during normal playback#22
byrongamatos merged 2 commits into
mainfrom
feat/metronome

Conversation

@gionnibgud

@gionnibgud gionnibgud commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

What

A METRONOME toggle in the Staff View options pill: clicks on every beat of bundle.beats during normal playback, accented on downbeats (measure >= 0). Persisted to localStorage.

Study mode is deliberately excluded — it already runs its own preroll count-in clicks, and a gated note-by-note run has no steady pulse to click against.

How

  • Reuses the existing _svStudyBeep click and its lazily-recreated AudioContext rather than opening a second audio path.
  • _svMetroTick binary-searches beats the same way _svSyncCursor does, tracking the last beat index a click fired for (_svMetroBeatIdx): an ordinary one-beat advance clicks, while a seek/jump resyncs silently. No click while paused, in study mode, or before the first beat.
  • _svMetroBeatIdx resets alongside the cursor's own per-song reset points (teardown, init(), chart change).

Testing

  • npm test — 112/112 pass (104 existing + 8 new in tests/metronome.test.js, following the suite's existing source-extraction pattern: accent-on-downbeat, silent mid-beat, seek resync, pre-first-beat reset, metronome off, study mode, paused/missing audio, <2 beats).
  • Verified in the running app.

Note

Depends on nothing in #21, but both branches touch the same ## [Unreleased] anchor in CHANGELOG.md — whichever merges second may need a trivial conflict resolution there.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added a Metronome toggle to Staff View’s options pill.
    • When enabled during normal playback (focused, not study mode, audio playing), plays beat clicks with downbeats accented.
    • Persists the setting between sessions.
  • Bug Fixes

    • Suppresses duplicate clicks immediately after seeking by silently resynchronizing beat timing.
    • Resets metronome beat tracking on initialization, chart/arrangement changes, and teardown.
  • Tests

    • Added automated coverage for ticking, accenting, gating (off/unfocused/study/paused), and seek/resync behavior.

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 9d3b7232-4614-4e90-83cd-f51dd49519dd

📥 Commits

Reviewing files that changed from the base of the PR and between 805d882 and cb36ef0.

📒 Files selected for processing (2)
  • screen.js
  • tests/metronome.test.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • screen.js

📝 Walkthrough

Walkthrough

Staff View adds a persisted Metronome toggle to the options pill. During normal playback, beat advancement triggers reused study-beep clicks with downbeat accents. Study mode, seeks, paused audio, and insufficient beat data suppress clicks. Tests cover the metronome tick behavior.

Changes

Metronome playback

Layer / File(s) Summary
Metronome option and persisted state
screen.js, CHANGELOG.md
Adds the options-pill toggle, localStorage persistence, button state updates, layout placement, and changelog documentation.
Beat-synchronized playback clicks
screen.js
Tracks the current beat during draw operations, triggers normal-playback clicks, suppresses duplicate or invalid clicks, handles seek resynchronization, and resets state during initialization and teardown.
Metronome behavior coverage
tests/metronome.test.js
Tests accented downbeats, beat progression, seeking, disabled conditions, paused or missing audio, unfocused panels, and insufficient beat data.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly reflects the main change: adding metronome beat clicks during normal playback.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/metronome

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@screen.js`:
- Around line 3382-3384: The metronome tick logic around _svMetroBeatIdx must
distinguish ordinary beat advances from completed silent seek transitions,
including exact one-beat forward and backward seeks. In screen.js lines
3382-3384, track audio seek completion so the next tick only resynchronizes
without calling _svStudyBeep; update tests/metronome.test.js lines 35-58 to
model seek completion and cover both exact-one-beat seek directions.
- Around line 3365-3370: Update _svMetroTick in screen.js to return when
_svIsFocused is false before processing the shared audio element or emitting
clicks. In tests/metronome.test.js, expose _svIsFocused in the harness and add
coverage confirming an unfocused instance remains silent; the test site requires
this direct harness and assertion change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c73db240-4262-4b29-b51f-118b97637548

📥 Commits

Reviewing files that changed from the base of the PR and between 58ca2ae and 805d882.

📒 Files selected for processing (3)
  • CHANGELOG.md
  • screen.js
  • tests/metronome.test.js

Comment thread screen.js
Comment thread screen.js
gionnibgud and others added 2 commits July 17, 2026 11:15
Adds a METRONOME toggle to the options pill that clicks on every beat
of bundle.beats during normal playback (accented on downbeats,
measure >= 0). Study mode is excluded — it already runs its own
preroll count-in clicks.

Reuses the existing _svStudyBeep click and its lazily-recreated
AudioContext rather than opening a second audio path. _svMetroTick
binary-searches beats the same way _svSyncCursor does, tracking the
last beat index a click fired for (_svMetroBeatIdx) so an ordinary
one-beat advance clicks while a seek/jump just resyncs silently.
State is persisted to localStorage and reset alongside the cursor's
own per-song reset points (teardown, init, chart change).

Co-Authored-By: Claude Sonnet <noreply@anthropic.com>
Signed-off-by: gionnibgud <gionnibgud@gmail.com>
Two review findings on _svMetroTick:
- Shared #audio in split-screen: gate on _svIsFocused so only the
  focused panel clicks/advances state.
- A seek forward by exactly one beat satisfied the "advanced one
  beat" check and clicked, violating the seek-resyncs-silently
  contract. Attach a 'seeked' listener (mirrors _svStudySeekHandler)
  that flags the next tick to resync without clicking, covering A/B
  loop wraps too.

Co-Authored-By: Claude Sonnet <noreply@anthropic.com>
Signed-off-by: gionnibgud <gionnibgud@gmail.com>
@byrongamatos
byrongamatos merged commit 3cf5b38 into main Jul 17, 2026
2 checks passed
@byrongamatos
byrongamatos deleted the feat/metronome branch July 17, 2026 09:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants