Initial Commit

This commit is contained in:
2026-05-27 23:47:53 +01:00
parent fbc70f96e6
commit 9b28db724f
18103 changed files with 1600554 additions and 0 deletions

View File

@@ -0,0 +1,62 @@
# `SpectrumAnalyzer` — magnitude spectrum + scalar features
## Purpose
`SpectrumAnalyzer` is the workhorse analysis op of this package: it slices an `AudioDocument` into overlapping frames, windows each frame, runs the real FFT, and reduces the per-bin magnitudes into a fixed-length `spectrum` plus three scalar features — centroid, rolloff, flux. The default 128-bin output is the standard size used by visualisers and feature pipelines.
The class implements `analyze` (single-shot whole document), `analyzeStream` (per-frame async generator suitable for real-time visualisation), and `analyzeBlock` (one already-windowed block via a `BlockContext`).
## Features
- Slices `doc` into `frameSize`/`hopSize` overlapping frames (defaults `2048`/`512`).
- Hann window by default; Hamming or Blackman selectable via `window`.
- Log-spaced bucket-mean reduction to the configured `bins` (default `128`).
- Centroid, 85% rolloff, and positive-flux scalars per result.
- `analyzeStream` yields per-frame results; the final frame's vectors match `analyze`.
- `analyzeBlock` runs a single FFT-sized block with `BlockContext.sampleRate`.
## Usage: Basic
```ts
import { SpectrumAnalyzer } from "@suaveplan/audio-analysis-spectrum/analyzer/spectrum-analyzer";
const analyzer = new SpectrumAnalyzer();
const result = await analyzer.analyze(doc);
console.log(result.centroid, result.rolloff, result.flux, result.spectrum);
```
## Usage: Advanced
```ts
const analyzer = new SpectrumAnalyzer();
const ctrl = new AbortController();
setTimeout(() => ctrl.abort(), 50);
try {
for await (const frame of analyzer.analyzeStream(doc, {
frameSize: 4096,
hopSize: 1024,
bins: 256,
window: "blackman",
signal: ctrl.signal,
})) {
updateVisualiser(frame.spectrum);
}
} catch (err) {
// AUDIO_ANALYSIS_SPECTRUM.ABORTED expected on early cancel.
}
const block = analyzer.analyzeBlock([new Float32Array(2048)], {
sampleRate: 48_000,
startSample: 0,
});
```
## API Reference
- `name`, `description`, `analyze(doc, opts?)`, `analyzeStream(doc, opts?)`, `analyzeBlock(block, ctx)`.
- `opts` includes `bins`, `frameSize`, `hopSize`, `window`, `signal`; defaults from the Zod schema.
- Result extends `AnalysisResult` with `op: "spectrum-analyzer"`, `spectrum`, `centroid`, `rolloff`, `flux`.
## Implementation Notes
The DSP pipeline lives in the `dsp` module so `SpectrumAnalyzer` stays an orchestrator. `analyze` retains only the final frame's `spectrum`/`magnitude` and the previous frame's `magnitude` so flux is well-defined. Each frame revalidates the abort signal between iterations, satisfying the mid-scan abort scenario. `analyzeBlock` does not consult an `AbortSignal` — block calls are bounded-time and the call site owns its own cancellation.