Rubato
Source Idle
Current chord
—
Waiting for audio
Confidence
–
Input levelNo input
-60 dB-40-200
Spectrum
Pitch classeschord tones lit
Beat –
Now playing
Nothing playing
+0.0 s

Play a song in any app. It will show up here.

Progression
Chord changes will appear here.
How it works

Chords from audio it has already heard

Every 40 ms, 25 times a second, Rubato turns the newest slice of sound into a chord. It never waits for the rest of the song, so it can follow live playing. It runs entirely on this device: the audio is never uploaded.

1 · Note energies

A constant-Q transform measures how loud each musical note is: 144 bins over 6 octaves, two per semitone. Every window ends at "now".

2 · CNN

A small convolutional network spots local patterns: which notes stack into a chord, which are just overtones, where notes start.

3 · Transformer

Adds context from the last ~32 s, so it knows the key and feel of the song when a moment is ambiguous. A KV cache keeps each step cheap.

4 · HMM smoothing

A hidden Markov model filters the guesses over time: chords tend to last, and some changes are far likelier than others. It runs forward only, so it adds no delay.

5 · Key and spelling

A rolling estimate of the key spells chords the way a musician would: G♯m in E major, D♭ in A♭ major.

6 · Display

The live chord, a steadier big chord that hides split-second blips, and a sheet that writes a chord down once it has held for half a second.

How it was trained

What's different

~82% right (major/minor) on songs it never trained on 109 chord types ~2M parameters 15–25 ms per step on a phone or laptop CPU Open source: GitHub