# `audio-fingerprinter` — Spectrogram → peaks → constellation orchestrator _(no submodules)_ ## Purpose `AudioFingerprinter` is the entry point that turns an `AudioDocument` into a deterministic constellation fingerprint. It composes three pieces: the spectrogram from `@suaveplan/audio-analysis-spectrum` (the ONLY FFT used by this package), the local-peak detector defined alongside this file, and the constellation pair-hasher. The class owns no DSP — every numerical step is delegated, which keeps the fingerprint algorithm in one auditable file. ## Features - Zod-validated options (`frameSize`, `hopSize`, `window`, `noiseFloor`, `peaksPerFrame`, `neighbourhood`, `fanout`, `targetZoneSec`). - Cooperative cancellation via `AbortSignal` checked at every pipeline stage. - Monotonic progress callback (`{ fraction }`) reported at 0, 0.5, 0.8, 1. - Wraps spectrogram failures in `REACT_AUDIO_FINGERPRINT.FINGERPRINT_FAILED` while preserving the underlying `cause`. - Stable output: identical input bytes produce a byte-equal fingerprint. - Returns the sample rate, hop, and frame size alongside the fingerprint so the matcher / visualizer can reconstruct frame ↔ time arithmetic. ## Usage: Basic Example ```ts import { AudioFingerprinter } from "@suaveplan/react-audio-fingerprint/fingerprint/audio-fingerprinter"; const fp = await new AudioFingerprinter().fingerprint(doc); console.log(fp.fingerprint.length, "pairs"); ``` ## Usage: Advanced Example Pass an `AbortSignal` and a progress callback while running a non-default window: ```ts import { AudioFingerprinter } from "@suaveplan/react-audio-fingerprint/fingerprint/audio-fingerprinter"; const controller = new AbortController(); const fp = await new AudioFingerprinter().fingerprint(doc, { window: "blackman", frameSize: 2048, hopSize: 512, signal: controller.signal, onProgress: ({ fraction }) => console.log(fraction), }); ``` ## API Reference - `class AudioFingerprinter`. - `fingerprint(doc, opts?): Promise`. - `FingerprintResult = { fingerprint, sampleRate, hopSize, frameSize }`. - `FingerprintOptionsSchema` — Zod schema; defaults `frameSize=4096`, `hopSize=1024`, `window="hann"`, `targetZoneSec=5`. - `signal?: AbortSignal`, `onProgress?: ({ fraction }) => void`. ## Implementation Notes `targetZoneFrames` is derived from `targetZoneSec` using the document's actual `sampleRate` and the configured `hopSize`. This keeps the target zone musically consistent across rates (e.g. 16 kHz speech vs 48 kHz music). The class only re-throws a `ReactAudioFingerprintError` when it can identify the original failure as an abort; everything else becomes `FINGERPRINT_FAILED` with the original error as `cause`. There is no caching — every call re-runs the spectrogram. Callers wanting to fingerprint the same document twice should memoise the result themselves.