first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,73 @@
# `audio-fingerprinter` — Spectrogram → peaks → constellation orchestrator
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## 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>`.
- `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.