keyshift-api / app /services /key_detector.py
balakrishna567's picture
feat: key detector — Krumhansl-Schmuckler 24-key Pearson correlation
0845ad7
Raw
History Blame Contribute Delete
858 Bytes
import numpy as np
NOTE_NAMES = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
MAJOR_PROFILE = np.array([6.35, 2.23, 3.48, 2.33, 4.38, 4.09, 2.52, 5.19, 2.39, 3.66, 2.29, 2.88])
MINOR_PROFILE = np.array([6.33, 2.68, 3.52, 5.38, 2.60, 3.53, 2.54, 4.75, 3.98, 2.69, 3.34, 3.17])
def detect_key(chroma: np.ndarray) -> tuple[str, str, float]:
"""Krumhansl-Schmuckler: return (root, mode, confidence 0-1)."""
best_corr, best_root, best_mode = -np.inf, "C", "major"
for i, note in enumerate(NOTE_NAMES):
for profile, mode in ((MAJOR_PROFILE, "major"), (MINOR_PROFILE, "minor")):
corr = float(np.corrcoef(chroma, np.roll(profile, i))[0, 1])
if corr > best_corr:
best_corr, best_root, best_mode = corr, note, mode
return best_root, best_mode, round((best_corr + 1.0) / 2.0, 4)