Skip to content

Transition Scoring

Transitions between tracks are scored on six independent axes, each producing a value between 0 and 1. A weighted composite combines all available scores based on the chosen priority mode.

Both score_transition and build_set use this scoring system. score_transition returns the full breakdown for a single A-to-B pair. build_set uses it internally to evaluate thousands of candidate transitions during greedy sequencing.

The six axes are:

  1. Key — harmonic compatibility via the Camelot wheel
  2. BPM — tempo difference
  3. Energy — energy level direction relative to the set’s energy curve phase
  4. Genre — genre family relationships
  5. Brightness — spectral centroid similarity (requires Essentia)
  6. Rhythm — onset regularity similarity (requires Essentia)

Axes 5 and 6 require Essentia audio analysis. When that data is missing, those axes are excluded from the composite without penalizing the score.


Key relationships are evaluated on the Camelot wheel, where adjacent positions represent harmonically compatible keys.

RelationshipScoreLabel
Same key (6A to 6A)1.0Perfect
+1 same letter (6A to 7A)0.9Energy boost
-1 same letter (6A to 5A)0.9Energy drop
Same number A/B (6A to 6B)0.8Mood shift
+/-1 other letter (6A to 7B)0.55Energy diagonal
+/-2 same letter (6A to 8A)0.45Extended
Everything else0.1Clash

Camelot wraps at the boundary: 12A to 1A is +1 (adjacent), not +11.

The +1/-1 moves are the bread and butter of harmonic mixing. Same-number A/B shifts switch between major and minor (or vice versa) — useful for mood changes within the same harmonic center. The +2/-2 moves are usable but require more careful phrasing.


BPM compatibility uses an exponential decay based on the percentage delta between two tracks:

score = exp(-0.019 * pct^2) where pct = |from_bpm - to_bpm| / from_bpm * 100
Delta %ScoreLabel
<2%~1.0Seamless
2-4%~0.8Comfortable pitch adjust
4-6%~0.5Noticeable
6-9%~0.3Creative transition needed
≥9%<0.2Jarring

BPM is taken from Rekordbox metadata — it’s the value the DJ sees, works with, and can manually correct. stratum-dsp’s estimate is used as a fallback only when Rekordbox BPM is zero (unanalyzed tracks).


Energy is a composite value estimated from Essentia audio features.

normalized_dance = clamp(danceability / 3.0, 0, 1)
normalized_loudness = clamp((loudness_integrated + 30) / 30, 0, 1)
onset_rate_norm = clamp(onset_rate / 10.0, 0, 1)
energy = (0.4 * normalized_dance)
+ (0.3 * normalized_loudness)
+ (0.3 * onset_rate_norm)

When Essentia data is not available, a BPM-based proxy is used:

energy_proxy = clamp((bpm - 95) / 50, 0, 1)

Energy scoring depends on where you are in the energy curve. The desired energy direction changes by phase:

PhaseDesired directionScore if metScore if wrong
WarmupStable or slight rise1.00.5
BuildRising1.00.3
PeakHigh and stable1.00.5
ReleaseDropping1.00.3

Additional bonuses apply at phase boundaries based on the destination track’s loudness_range value:

  • Phase boundary with destination loudness_range > 8.0: +0.1 bonus (capped at 1.0). Tracks with wide dynamic range create natural-sounding transitions at phase boundaries.
  • Peak phase with destination loudness_range < 4.0: +0.05 bonus (capped at 1.0). Compressed, loud tracks sustain energy during the peak.

Genres are grouped into families. Compatibility depends on whether two genres share the same family.

RelationshipScore
Same canonical genre1.0
Related genres (same family)0.7
Different families0.3
FamilyGenres
HouseHouse, Deep House, Tech House, Afro House, Gospel House, Progressive House, Garage, Speed Garage, Disco, Italo Disco, 2-Step Garage, UK Funky
TechnoTechno, Deep Techno, Minimal, Dub Techno, Ambient Techno, Hard Techno, Drone Techno, Acid, EBM, Electro, Trance, Psytrance
BassDrum & Bass, Jungle, Dubstep, Breakbeat, Footwork, Future Garage, Grime, Bassline, Broken Beat
HardcoreHardstyle, Happy Hardcore, Hard Trance, Hardcore, Gabber
DowntempoAmbient, Downtempo, Trip-Hop, Dub, Dub Reggae, IDM, Experimental
OtherHip Hop, Pop, R&B, Reggae, Dancehall, Rock, Synth-pop, Highlife, Jazz

Genres within the “Other” family do not receive the 0.7 related-genre bonus with each other. They score 0.3 against all other genres, including other “Other” entries.

Genre scoring adjusts based on recent sequencing context:

  • Streak bonus (+0.1): When the current transition stays within the same genre family and the preceding run of same-family tracks is 1-4 tracks long (non-Other family), +0.1 is added to the genre axis score (capped at 1.0). This rewards building genre momentum.
  • Early switch penalty (-0.1): When switching to a different genre family after a run of only 1 same-family track, -0.1 is subtracted from the genre axis score (floored at 0.0). This discourages abrupt one-off genre detours.

These modifiers only apply during build_set sequencing, where the algorithm tracks the genre run length across the evolving set. They do not apply to standalone score_transition calls.

Genre matching uses the canonical genre assigned by reklawdbox’s classification system, not the raw genre string from Rekordbox metadata. If a track hasn’t been classified yet, the raw metadata genre is normalized to the closest canonical genre.


Brightness compatibility (spectral centroid)

Section titled “Brightness compatibility (spectral centroid)”

Brightness is derived from the spectral centroid frequency, measured in Hz. A higher spectral centroid means more high-frequency content — think bright, crispy hi-hats versus deep, muffled pads. Large jumps in brightness create timbral clashes that are especially noticeable in long blends.

Delta (Hz)ScoreLabel
< 3001.0Similar brightness
300-8000.7Noticeable shift
800-15000.4Large timbral jump
> 15000.2Jarring

When brightness data is missing for either track, this axis scores 0.5 (neutral) and is excluded from the composite denominator so it does not penalize the overall score.


Rhythm regularity measures how “on the grid” a track feels — a four-on-the-floor techno beat has high regularity, while a broken-beat track or live-drummer recording has low regularity. Delta is the absolute difference in regularity between two tracks.

DeltaScoreLabel
< 0.101.0Matching groove
0.10-0.250.7Manageable shift
0.25-0.500.4Challenging shift
> 0.500.2Groove clash

When rhythm data is missing for either track, this axis scores 0.5 (neutral) and is excluded from the composite denominator.


The final transition score is a weighted sum normalized by the weights of available axes:

composite = sum(weight_i * score_i) / sum(weight_i) for available axes

Axes with missing data (brightness, rhythm) are excluded from both the numerator and denominator. This means a transition between two tracks without Essentia analysis is scored purely on key, BPM, energy (proxy), and genre — without penalty.

Four priority modes control how axes are weighted:

PriorityKeyBPMEnergyGenreBrightnessRhythm
Balanced0.300.200.180.170.080.07
Harmonic0.480.180.120.080.080.06
Energy0.120.180.420.120.080.08
Genre0.180.180.120.380.080.06
  • Balanced — general-purpose. Good default for most sets.
  • Harmonic — prioritizes key compatibility. Best for melodic genres where clashing keys are obvious.
  • Energy — prioritizes energy flow. Best when building a set around a specific energy curve.
  • Genre — prioritizes genre cohesion. Best for sets that should stay within a genre family.

Note that brightness and rhythm always have low weights (0.06-0.08) across all presets. They act as tiebreakers when the primary axes are similar, not as dominant factors.

RangeQuality
0.85-1.0Excellent transition — mix with confidence
0.70-0.84Good transition — minor compromises on one or two axes
0.50-0.69Acceptable — requires skill or creative mixing techniques
0.30-0.49Difficult — likely noticeable to the audience
< 0.30Avoid unless intentionally jarring

These ranges are guidelines. A 0.65 score with a perfect key match and a genre clash plays differently than a 0.65 with mediocre scores across the board. Use score_transition to see the per-axis breakdown when a composite score surprises you.


The scoring system degrades gracefully based on available data:

Data availableAxes used
Rekordbox metadata onlyKey, BPM, energy (proxy), genre
+ stratum-dsp analysisKey (improved), BPM (fallback for unanalyzed), energy (proxy), genre
+ Essentia analysisAll six axes

Run analyze_audio_batch on your tracks before building sets for the best scoring accuracy. Without Essentia, brightness and rhythm are excluded entirely, and energy falls back to the BPM-based proxy.