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