first commit
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
# 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 `algorithm` option.
|
||||
- Configurable frequency range via `minFreq` / `maxFreq` and frame size.
|
||||
- `AbortSignal` support 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 through `AudioAnalysisError`.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
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
|
||||
|
||||
```ts
|
||||
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.
|
||||
Reference in New Issue
Block a user