Skip to content

Server tempo: Mixxx's beat tracker instead of the envelope estimator - #116

Merged
fnyaker merged 1 commit into
masterfrom
subgenre-track-lists
Oct 14, 2026
Merged

fnyaker merged 1 commit into
masterfrom
subgenre-track-lists

Conversation

@fnyaker

@fnyaker fnyaker commented Oct 13, 2026

Copy link
Copy Markdown
Owner

Deezer publishes no bpm for nearly all of a hard-dance library (2 of 3 462 files here), so the envelope estimator was what every track got: rounded to a whole BPM and often 2-4 off (154 for 150), the wrong octave on half the non-club records — and the player now locks to it.

deezer/beats.py ports Mixxx's default analyser to numpy: qm-dsp's complex spectral difference onsets and TempoTrackV2 (comb filter bank + Viterbi for the period, dynamic programming for the beats), then Mixxx's BeatUtils constant-tempo pass and rounding (GPL-2.0-or-later, credited). On top: hardcore tracked at half is doubled when the half beats strike as hard as the beats (kick band and whole spectrum, 0.85-1.3); no tempo without attacks and on-beat salience; Deezer's figure only witnesses the octave.

tools/tempo_eval.py: 17/26 within 3.5% -> 23/26 exact, 26/26 with Deezer as witness, 0 phantoms. ~0.4 s and ~100 MB a track. ANALYSIS_VERSION 5, and a stale library is re-measured on boot (webui/analysis.reanalyse_if_stale). Without numpy the envelope estimator still answers.

Deezer publishes no bpm for nearly all of a hard-dance library (2 of 3 462
files here), so the envelope estimator was what every track got: rounded to a
whole BPM and often 2-4 off (154 for 150), the wrong octave on half the
non-club records — and the player now locks to it.

deezer/beats.py ports Mixxx's default analyser to numpy: qm-dsp's complex
spectral difference onsets and TempoTrackV2 (comb filter bank + Viterbi for
the period, dynamic programming for the beats), then Mixxx's BeatUtils
constant-tempo pass and rounding (GPL-2.0-or-later, credited). On top:
hardcore tracked at half is doubled when the half beats strike as hard as the
beats (kick band and whole spectrum, 0.85-1.3); no tempo without attacks and
on-beat salience; Deezer's figure only witnesses the octave.

tools/tempo_eval.py: 17/26 within 3.5% -> 23/26 exact, 26/26 with Deezer as
witness, 0 phantoms. ~0.4 s and ~100 MB a track. ANALYSIS_VERSION 5, and a
stale library is re-measured on boot (webui/analysis.reanalyse_if_stale).
Without numpy the envelope estimator still answers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comment thread supysonic/deezer/beats.py

import logging
import math
import subprocess
Comment thread supysonic/deezer/beats.py
"ffmpeg", "-v", "error", "-nostdin", "-t", str(seconds), "-i", path,
"-vn", "-ac", "1", "-ar", str(SR), "-f", "f32le", "-",
]
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
Comment on lines +271 to +272
except Exception:
pass
@fnyaker
fnyaker merged commit 46fe7a1 into master Oct 14, 2026
14 checks passed
@fnyaker
fnyaker deleted the subgenre-track-lists branch October 14, 2026 20:06
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