first commit
This commit is contained in:
@@ -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.
|
||||
Reference in New Issue
Block a user