first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,47 @@
# 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 `profileSet` argument.
- 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
```ts
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
```ts
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.