Real-time pitch, BPM & rhythm analysis web app - #1
Open
silas-dsc wants to merge 11 commits into
Open
Conversation
Mobile-friendly, dependency-free web app using the Web Audio API: - Microphone and audio-file input - Autocorrelation pitch detection with cents deviation from perfect pitch - Spectral-flux onset detection and onset-envelope autocorrelation for BPM - Beat-grid fitting with per-onset timing error in ms - Live note/cents/BPM readouts, rhythm timeline, note history - Top-3 most out-of-tune notes and most out-of-time onsets - Zero-dependency static dev server and Node unit tests for the DSP math https://claude.ai/code/session_01Df9csCTPk457zYQLYJcWaV
If PORT is not set explicitly and the default port (5173) is busy, the dev server now binds an OS-assigned free port instead of crashing. An explicitly-requested PORT still errors clearly so the user's choice is respected. https://claude.ai/code/session_01Df9csCTPk457zYQLYJcWaV
The score draws each note on a treble/bass grand staff at its perfect pitch and beat position (hollow target), with a colour-coded overlay showing the actual performance offset left/right for early/late and up/down for sharp/flat. Green/yellow/red encodes accuracy. Adds independent pitch and rhythm strictness sliders that drive the score colours, offender lists, history table and tuning meter via a new pure tolerance module. New staff-position module maps MIDI notes to diatonic grand-staff steps including sharps. Both are unit-tested. https://claude.ai/code/session_01Df9csCTPk457zYQLYJcWaV
The piano roll shows pitch (vertical lanes with a keyboard gutter) vs. time (scrolling). Each note draws a hollow target bar at its perfect pitch lane and quantized beat, plus a colour-coded actual bar offset left/right for early/late and up/down within the lane for sharp/flat (one semitone = one lane). Black-key lanes are shaded and octaves are labelled. Removes the now-unused staff-position module and its tests; pitch is mapped directly from MIDI. Strictness sliders and accuracy colours are unchanged. https://claude.ai/code/session_01Df9csCTPk457zYQLYJcWaV
- Note history now stores and renders the full session (not just the last 60), with row metadata for navigation. - When the mic is stopped or a file ends, the piano roll can be scrolled and dragged back through the whole performance; the history table highlights and follows the visible window. - Tap tempo via a button or the Enter key sets a manual BPM; min/max bounds constrain auto-detection and disambiguate octave errors. - Clicking a "most out of tune/time" entry jumps to that note in the history (and centres it in the roll when paused). - Tempo detection is smoothed with octave-folding inertia (smoothBpm) so it stays steady instead of flickering. https://claude.ai/code/session_01Df9csCTPk457zYQLYJcWaV
- Capture the mic take (MediaRecorder -> decoded AudioBuffer); uploaded files are reused directly. After stopping, a playback transport appears. - New Playback module plays the buffer with a continuous media-time position so the piano roll scrolls in sync and the history window follows. A unified transport slider doubles as review scrubber and playback seek; the roll can also be scrolled/dragged. - Metronome click track locked to the detected/tapped beat grid (accented downbeats), toggle on/off. - Variable playback speed 0.3x–2x in 0.1 steps; click and roll stay in sync via rate-rebased position tracking. - beatGrid() finds the beat phase for the click; covered by tests. https://claude.ai/code/session_01Df9csCTPk457zYQLYJcWaV
- Play back through an <audio> element so variable speed (0.3x–2x)
preserves pitch instead of transposing it.
- Add a synthesized piano voice ("MIDI notes") for the detected notes,
toggleable like the click track and scheduled against the audio clock.
- Add horizontal (time) and vertical (pitch) +/- zoom controls for the
piano roll.
- Stop piano-roll wheel/drag/touch from scrolling the page
(touch-action: none + preventDefault).
- Analyzer now exposes a playback URL + duration (object URLs, revoked
on reset) instead of a decoded buffer.
https://claude.ai/code/session_01Df9csCTPk457zYQLYJcWaV
History sync used element.scrollIntoView(), which scrolls the whole window — so any control click / redraw yanked the page down to the history table. Scroll the history table's own container instead, leaving the page scroll position untouched. https://claude.ai/code/session_01Df9csCTPk457zYQLYJcWaV
When the piano roll is vertically zoomed in, the visible pitch window now follows the pitch under the playhead (notes sounding at the current time, else the nearest note) instead of staying centred on the global range — so during playback and zoom the current notes stay on screen. Falls back to the full range when not zoomed. https://claude.ai/code/session_01Df9csCTPk457zYQLYJcWaV
Refactor the piano roll's vertical mapping to be centre-based with a fractional centre, so the pitch-follow glides by sub-lane amounts instead of jumping a whole semitone at a time. The centre eases toward the playhead's pitch while playing/recording and snaps when paused so zoom/seek still frame instantly. https://claude.ai/code/session_01Df9csCTPk457zYQLYJcWaV
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A mobile-friendly, dependency-free web app that analyzes audio in real time to measure pitch, tempo (BPM) and rhythm, and shows how far each note strays from perfect pitch and perfect time. Everything runs locally in the browser via the Web Audio API — no audio leaves the device.
Features
How it works
js/pitch.jsjs/rhythm.jsjs/rhythm.jsjs/rhythm.jsAnalyserNodepolled per animation framejs/analyzer.jsjs/app.jsRunning & testing
The pure DSP functions are covered by 9 passing unit tests (note identification, cents deviation, autocorrelation pitch detection, tempo estimation, timing-error analysis).
Notes / limitations
https://claude.ai/code/session_01Df9csCTPk457zYQLYJcWaV
Generated by Claude Code