2.7 KiB
yin
Purpose
yin.ts ships three fundamental-frequency estimators behind a unified PitchEstimate shape so the PitchDetector can swap algorithms via the algorithm option without callers branching on the result type. The default is YIN (de Cheveigné & Kawahara, 2002), with McLeod Pitch Method (MPM) and a real-cepstrum estimator available for material where they outperform YIN.
This file also vendors a small radix-2 real FFT plus nextPow2 / realFftMagnitude helpers consumed by the chromagram and cepstrum paths so the package has no hard dependency on @suaveplan/audio-analysis-spectrum.
Features
yinPitch— difference function, cumulative mean normalised difference, absolute threshold pick at 0.1, parabolic interpolation.mcleodPitch— NSDF + key-maxima picking with threshold-relative-to-global-max.cepstrumPitch— log-magnitude inverse FFT with quefrency peak in the lag window.- Robust no-pitch result: returns
pitch: 0,confidence: 0when the input is silent or has no detectable periodicity. - Vendored radix-2 FFT for self-contained operation.
Usage: Basic
import { yinPitch } from "@suaveplan/audio-analysis-pitch/algorithms/yin";
const frame = new Float32Array(4096);
for (let i = 0; i < frame.length; i++) {
frame[i] = Math.sin((2 * Math.PI * 440 * i) / 48_000);
}
const { pitch, confidence } = yinPitch(frame, 48_000, 20, 20_000);
Usage: Advanced
import {
cepstrumPitch,
mcleodPitch,
yinPitch,
} from "@suaveplan/audio-analysis-pitch/algorithms/yin";
function multiAlgorithmEnsemble(frame: Float32Array, sr: number) {
const yin = yinPitch(frame, sr, 50, 2_000);
const mpm = mcleodPitch(frame, sr, 50, 2_000);
const cep = cepstrumPitch(frame, sr, 50, 2_000);
return [yin, mpm, cep].sort((a, b) => b.confidence - a.confidence)[0];
}
API Reference
interface PitchEstimate { pitch: number; confidence: number }.yinPitch(frame, sampleRate, minFreq, maxFreq): PitchEstimate.mcleodPitch(frame, sampleRate, minFreq, maxFreq, threshold = 0.85): PitchEstimate.cepstrumPitch(frame, sampleRate, minFreq, maxFreq): PitchEstimate.nextPow2(n: number): number.realFftMagnitude(frame: Float32Array): Float32Array.
Implementation Notes
YIN's CMNDF gives lag-zero a value of 1, suppressing the trivial autocorrelation peak. MPM walks the NSDF from the first negative crossing onward to avoid the same trivial peak. Parabolic interpolation around the chosen lag yields sub-sample precision. The cepstrum path is sample-rate-bound in resolution (one bin equals sr/period²), so its accuracy is coarser than YIN/MPM — typically within ±20 Hz at 48 kHz for a 4096-sample frame.