Files
skills/docs/media/audio/audio-analysis-pitch/src/algorithms/yin.md
2026-05-29 08:20:56 +01:00

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: 0 when 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.