Skip to content

Repository files navigation

KEY // DETECT

Live at srp1357.github.io/song-key-detection

Detect the musical key of a song, track key changes (modulations), estimate its tempo, and watch a live piano roll of every transcribed note — entirely in your browser. No uploads, no servers, no external API calls. The transcription can be downloaded as a standard MIDI file.

How it works

Everything runs client-side in a Web Worker:

  1. Decode — the browser's own audio decoder handles mp3/wav/ogg/m4a/flac, resampled to 22050 Hz mono. Files must be between 10 seconds and 15 minutes.
  2. Chromagram — Hann-windowed 32768-point FFT frames over C1–B6 (the six-octave band validated by KeyFinder's evaluation), folded into 12 pitch classes with circular-mean tuning correction and CLP-style log compression (Müller & Ewert, ISMIR 2011) — src/lib/chroma.ts.
  3. Key detection — each 8-second window is scored against all 24 keys by Pearson correlation with libKeyFinder's production tone profiles, then Viterbi decoding with a uniform switch penalty (the local-key HMM structure of Schreiber, Weiß & Müller, ICASSP 2020) turns window scores into stable key segments, so brief chromatic passages don't register as modulations — src/lib/keyDetection.ts. Each segment reports its measured evidence (profile fit, margin, runner-up key) rather than a synthetic confidence percentage.
  4. Tempo & beats — onset strength from mel-band spectral flux, global tempo from a prior-weighted autocorrelation, and beat positions from Ellis's dynamic-programming beat tracker (J. New Music Research, 2007 — the method librosa ships as its default). The piano roll's gridlines are drawn on these beats, with bars assuming 4/4 — src/lib/tempo.ts.
  5. Note transcription — Spotify's basic-pitch neural network (TensorFlow.js) transcribes every note for the piano roll, using Spotify's published default thresholds.

The transcription is exportable as a standard MIDI file (notes, the detected tempo, and the detected key as the key signature) — src/lib/midiExport.ts.

The model weights (~0.9 MB) are vendored into public/model/ and served from this site's own origin — the app has zero runtime dependencies on any third party. Audio never leaves the tab.

Why basic-pitch? Newer open transcription models exist (e.g. MuScriptor, 2026: multi-instrument, higher accuracy) but need 393 MB+ of weights, have no official browser runtime, and carry a non-commercial license. Basic-pitch is Apache-2.0, ships an official TensorFlow.js port, and its entire model fits in under a megabyte — the right trade-off for a fully client-side static site.

Development

npm install
npm run dev      # dev server at http://localhost:5173
npm run build    # production build into dist/

Verification and diagnostics (no browser required):

npx tsx scripts/verify-keys.ts             # all 24 keys + modulation, exact-match test
npx tsx scripts/verify-tempo.ts            # tempo/beat tracking on synthesized tracks
npx tsx scripts/verify-midi.ts             # MIDI export round-trip (tempo, key sig, notes)
npx tsx scripts/sanity-check.ts            # key detection on synthesized chords
npx tsx scripts/diagnose-file.ts song.wav  # full evidence dump for a real file (wav/mp3)
npx tsx scripts/peak-check.ts song.wav     # raw spectral peaks, bypasses the pipeline
npx tsx scripts/sanity-transcribe.ts       # transcription check (needs `npm run dev` running)

Deployment

Pushing to main triggers the GitHub Actions workflow in .github/workflows/deploy.yml, which builds the site and deploys it to GitHub Pages. In the repo settings, set Pages → Source to GitHub Actions.

Stack

  • Vite + React + TypeScript
  • Tailwind CSS 4 (slate palette, JetBrains Mono)
  • @spotify/basic-pitch + TensorFlow.js (WebGL backend, CPU fallback)
  • @tonejs/midi (MIDI file export)
  • Custom FFT / chromagram / tone-profile correlation + Viterbi / tempo & beat tracking implementation (no DSP libraries)

About

In-browser song key detector: find musical key and key changes, estimate BPM, transcribe notes, and export MIDI. Fully client-side.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages