BPM and key detection
How we estimate tempo + musical key + Camelot notation on every upload, how often we are right, and when we deliberately answer nothing.
What we detect
Every master you upload gets two automatic analyses:
- BPM: tempo in beats per minute, stored with two decimals (for example 127.83).
- Musical key: like "C", "F#", "Am", "G#m". Major keys have no suffix; minor keys end in "m". Always sharps, never flats (enharmonic-normalized so the same key is never split between "Db" and "C#").
- Camelot wheel code: derived from the musical key. Example: A minor = 8A, C major = 8B.
The values appear on:
- The listen page (
/listen/<token>) - The file list in Storage, where you can sort by BPM or into a harmonic mix order (DJ use case)
How it works under the hood
We use a deterministic offline analysis (lib/audio-analyze/), no cloud
API and no machine learning. For the tempo, we split the audio into five
frequency bands and look for the moments energy rises in each of them,
which is what a drum hit really is. Balancing the bands against each
other is the point: it makes a kick and a snare count for roughly the
same, so the pulse the analyzer locks onto is the beat rather than the
kick-snare-kick-snare pattern that runs at half the speed. For the key,
we pick out the individual tones in the spectrum, work out whether the
whole track is tuned slightly sharp or flat and correct for that, fold
each tone back onto the note it belongs to, and compare the resulting
twelve-note fingerprint against the 24 major and minor key templates.
We also look at how the track ENDS. Music nearly always comes to rest on its home note, and a piece that spends most of its time leaning on the fifth can fool a method that only counts notes across the whole track; that is exactly why some tracks used to come back a fourth away from home. The ending only gets to choose between the two keys that already scored highest; it can never propose a third one of its own.
One case cannot be settled that way at all: a major key and its relative minor contain exactly the same seven notes. C major and A minor are the same white keys; so are G major and E minor. When a track spends equal time on both, the audio genuinely does not say which one is home. We used to try to break that tie with a second fingerprint built from the bass alone. We measured it properly this time and it made things slightly worse, so it is gone. Instead we make the call openly: in that situation we report the MINOR. Most electronic music is minor, that is what the DJ world calls such a loop, and on the Camelot wheel the two answers are the same number with a different letter (8A and 8B), which are harmonically compatible anyway, so the cost of being wrong inside that pair is small.
How good is it, really
We keep a benchmark of synthesised tracks whose tempo and key we already
know (49 for tempo and 53 for key) plus thirteen real finished masters
whose tempo and key come from the original project files. Every change
runs the current analyzer and both of its predecessors over all of them
(lib/audio-analyze/bench/). The honest numbers:
- Tempo: right to within 2 BPM on 45 of the 49 synthesised tracks (91.8%), and on 12 of the 13 real masters. The oldest analyzer managed 24 of 49 and 8 of 13. Nothing is held back from that count: the four cases we know are hardest are in it.
- Key: right on 47 of the 53 synthesised tracks (88.7%), where the previous version managed 35 and the oldest 33. On the real masters it is right on all 5 where we know the key, but those five are five versions of the same piece of music, so treat that as one observation, not five.
Read the key number carefully, because it flatters us: those tracks were synthesised by us, and a machine that scores its own homework scores well. On real, dense, electronic material the honest expectation is lower: roughly 2 in 3. That is not a confession of a bug, it is where this whole field sits. On the standard research collection of dance tracks the best commercial tools get the key exactly right around 7 times in 10, so even they are wrong on nearly 3 in 10. Anyone promising more than that is measuring something easier.
Loops and short files get no tempo at all
We also tested a set of commercial sample-pack loops between half a second and twenty-four seconds long. Almost none of them get a tempo now, and that is deliberate.
To be sure a pulse is really the tempo, the analyzer checks that independent six-second stretches of the track agree with each other. Below about twelve seconds there are not two stretches to compare, so there is nothing to check against, and a number nobody checked is a guess. It used to hand those out: four to twelve seconds of pure noise came back as 176 to 191 BPM. Now anything under roughly twelve seconds gets no tempo and the reason is written to our log.
Tempo needs at least about twelve seconds of audio. Even above that, loops are the weak spot: of the readable loops in our set, most were still wrong. Four bars of a bassline simply do not contain enough repetition, and a name like "140_Drums" is the tempo of the pack rather than something measurable in a fragment. Tempo on a full track is the part we would defend on your catalogue; tempo on a loop is not.
One file format we cannot read at all
Samples that come out of an Ableton Pack are often .aif files using
Ableton's own compression inside them. Nothing outside Ableton can read
those, us included; thirteen of the twenty-eight files in our loop set
were exactly that. We now recognise them during the upload and stop them
there, with that sentence on screen, rather than accepting a file that would
sit unplayable in your library. If you need one on SoundAssist, export or
consolidate it from Ableton as a normal WAV or AIFF first.
What it gets wrong
- A major key and its relative minor still get confused. C major and A minor contain exactly the same seven notes; so do G major and E minor. When a track spends equal time on both, we get it right about half the time, which is chance, and no better than the old analyzer managed. We now at least fail in a predictable direction (we answer the minor, see above) instead of at random, but the underlying problem is not solved and no purely automatic method has solved it.
- Half-time grooves can come out at double speed. A slow beat with a busy hi-hat pattern is sometimes reported at twice its tempo. Both numbers describe the same groove; ours picks the wrong one of the two.
- Half or double tempo in general. Much rarer than it used to be, but still the main way a BPM goes wrong. Drum & bass at 174 is no longer reported as 87. Two of the test masters used to come back at 67 instead of 134 and no longer do: on top of counting the beats, the analyzer now also asks how quickly the sound of the track changes from moment to moment, because a genuinely slow piece packs more distinct events into one beat than a fast one does. That second opinion is only consulted on full, produced tracks, where the published research behind it was measured, never on a loop or on anything we generated ourselves.
- A track whose bass never touches the tonic (everything played in inversions, or a long pedal note under changing chords) can come out a fifth away from home. Where the track ends counts here, but only when the ending is unambiguous.
- Tracks that change key get the dominant key; the bridge is ignored.
- A track with two different arrangements in one file (two versions bounced back to back, say) can come back with no tempo at all, because the two halves disagree about the beat. That is the analyzer refusing to average two answers into a third one that is true of neither.
- Anything shorter than about twelve seconds gets no tempo at all; see above. The field stays empty and the reason goes to our log rather than a number being invented. And the floor is a floor, not a promise: above it there is still no length at which a loop's tempo becomes trustworthy.
- Drums with no accents at all. If every hi-hat stroke is exactly the same loudness, the tempo can land an octave out. Live playing and most programming accent the beat, so this is rare, but it is a real limit and the benchmark prints it rather than hiding it.
What it refuses to answer
When it cannot tell, it writes nothing and the field stays empty. That is deliberate, and it matters most for people who are not uploading songs: room tone, a synth drone, mains hum, a spoken-word bed or a sound-design stem now gets no BPM and no key instead of a confident wrong one. The old analyzer would happily put "143 BPM, A major" on a sustained pad.
There is no confidence score stored anywhere; it exists only inside the analysis, to make that write-or-stay-empty decision. Empty fields get picked up again by the backfill (up to three attempts per version, after which the version is parked).
BPM and key are read-only. They are not editable on the track-edit page, and there is no manual override.
Camelot wheel basics
The Camelot wheel is the DJ-friendly way to find compatible tracks:
- Same number, different letter: relative major / minor (e.g. 8A → 8B)
- Adjacent numbers, same letter: perfect-fifth shift (8A → 9A, both minor)
- Diagonal jumps: generally avoid (energy clashes)
Mixing into a compatible Camelot code = no key clash on the crossfade. In Storage, the Key sort puts your files in a mix order built on these rules; see Find tracks by BPM or key.
Backfill for old uploads
If a track from before the analyzer launched shows no BPM / key, it gets picked up by the next backfill run, which happens automatically as a low-priority background job. A version that fails three times is parked and stops being retried.
Privacy
The analysis runs on our server and the bytes stay there; we don't ship the audio to any external service for analysis. The only thing stored in the database is the resulting values: BPM, key, Camelot code. The audio file itself is the master you already uploaded; no copies, no derivative analyses on third-party services.