2.5 KiB
pitch-detector
Purpose
pitch-detector.ts exposes the PitchDetector class — the Analysis Op plugin (plugin slot 3 in the @suaveplan/audio-* family) that estimates the fundamental frequency of an AudioDocument. It supports whole-document analysis (analyze), streaming refinement (analyzeStream), and synchronous single-block analysis (analyzeBlock) for real-time visualisation.
Three estimators are selectable per call — YIN (default), McLeod, and cepstrum — letting callers pick the right trade-off for the material at hand without coupling to a different package.
Features
- Three pitch algorithms behind the
algorithmoption. - Configurable frequency range via
minFreq/maxFreqand frame size. AbortSignalsupport across all three entry points.- Zod boundary validation on every options object.
- OpenTelemetry spans per detector run, counter for total runs, histograms for run and block duration.
- Stable error codes (
INVALID_OPTIONS,ABORTED,UNSUPPORTED_FORMAT,INSUFFICIENT_DATA) all routable throughAudioAnalysisError.
Usage: Basic
import { PitchDetector } from "@suaveplan/audio-analysis-pitch";
const detector = new PitchDetector();
const result = await detector.analyze(doc);
console.log(result.pitch, "Hz", "midi:", result.midiNote);
Usage: Advanced
import { PitchDetector } from "@suaveplan/audio-analysis-pitch";
const detector = new PitchDetector();
const controller = new AbortController();
const opts = { algorithm: "mcleod" as const, minFreq: 50, maxFreq: 1_000, signal: controller.signal };
const out: number[] = [];
for await (const r of detector.analyzeStream(doc, opts)) {
out.push(r.pitch);
if (out.length >= 100) controller.abort();
}
API Reference
class PitchDetector { name: "pitch-detector"; version: string; description: string; analyze(doc, opts?); analyzeStream(doc, opts?); analyzeBlock(block, ctx) }.interface PitchDetectorOptions { algorithm?, minFreq?, maxFreq?, frameSize?, hopSize?, signal? }.interface PitchResult extends AnalysisResult { op: "pitch-detector"; pitch; midiNote; confidence; timestamp; duration }.
Implementation Notes
analyze aggregates results by keeping the highest-confidence pitch across all frames. analyzeStream yields per-block estimates with a running max confidence so the stream is non-decreasing in expectation. Both honour an AbortSignal checked at every block boundary. analyzeBlock is allocation-light: it skips the Zod schema (the block path is hot) and uses the package defaults.