2.2 KiB
key-finding
Purpose
key-finding.ts correlates an aggregated chromagram against 24 major/minor key profiles to estimate the musical key of a passage. Two profile sets ship: the classic Krumhansl-Schmuckler perceptual weights and Temperley's revised weights which reduce relative-major/minor confusion.
The estimator returns the best-scoring key together with a confidence derived from the margin between the top and runner-up correlation, giving callers a usable proxy for how decisive the result was.
Features
- 12 tonics × 2 modes = 24 candidate keys scored per call.
- Two interchangeable profile sets via the
profileSetargument. - Pearson correlation as the scoring function — robust to multiplicative gain.
- Stable pitch-class naming via
KEY_PROFILE_NAMES. - Numerically safe: zero-denom Pearson collapses to zero rather than NaN.
Usage: Basic
import { detectKey } from "@suaveplan/audio-analysis-pitch/algorithms/key-finding";
const chroma = new Float32Array([6.35, 2.23, 3.48, 2.33, 4.38, 4.09, 2.52, 5.19, 2.39, 3.66, 2.29, 2.88]);
const { key, confidence } = detectKey(chroma);
console.log(key); // "C major"
Usage: Advanced
import { detectKey, type KeyProfileSet } from "@suaveplan/audio-analysis-pitch/algorithms/key-finding";
function compareProfiles(chroma: Float32Array) {
const sets: KeyProfileSet[] = ["krumhansl-schmuckler", "temperley"];
return sets.map((set) => ({ set, ...detectKey(chroma, set) }));
}
API Reference
type KeyProfileSet = "krumhansl-schmuckler" | "temperley".interface KeyEstimate { key: string; mode: "major" | "minor"; tonic: number; confidence: number }.detectKey(chroma: Float32Array, profileSet?: KeyProfileSet): KeyEstimate.KEY_PROFILE_NAMES: readonly string[]—["C", "C#", "D", …].
Implementation Notes
Profiles are rotated to each tonic with O(1) lookup; for 24 candidates this is 24 Pearson computations per call, each O(12). The confidence is the normalised margin (best - second) / max(|best|, ε) clamped to [0, 1]. If the chromagram has zero variance the Pearson denominator collapses to zero and the function returns C major with zero confidence rather than NaN.