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,58 @@
# `mel-scale` — hertz↔mel mapping and triangular filterbank
## Purpose
The mel-scale module provides the perceptual frequency warp used by MFCC and any caller that wants a psychoacoustically motivated reduction of an FFT magnitude spectrum. It exposes the Slaney/HTK closed-form `hzToMel` and its inverse `melToHz`, plus a builder that produces a triangular filterbank for a given `(frameSize, sampleRate, melBands, minHz, maxHz)` tuple.
Each filterbank is cached so repeated frames pay zero filter-construction cost; applying a filterbank to a magnitude spectrum is then a single dense matrix-vector multiply.
## Features
- Closed-form hertz↔mel mapping that round-trips to machine precision.
- Triangular filterbank with `melBands` bands evenly spaced on the mel scale.
- Per-spec caching keyed by `(frameSize, sampleRate, melBands, minHz, maxHz)`.
- Boundary validation that `melBands` is a positive integer.
## Usage: Basic
```ts
import {
applyMelFilterbank,
buildMelFilterbank,
} from "@suaveplan/audio-analysis-spectrum/algorithms/mel-scale";
const fb = buildMelFilterbank({
frameSize: 2048,
sampleRate: 48_000,
melBands: 40,
minHz: 0,
maxHz: 24_000,
});
const mel = applyMelFilterbank(spectrum, fb);
```
## Usage: Advanced
```ts
import {
clearMelFilterbankCache,
hzToMel,
melToHz,
} from "@suaveplan/audio-analysis-spectrum/algorithms/mel-scale";
const m = hzToMel(1000);
const back = melToHz(m); // ≈ 1000 within 1e-3
clearMelFilterbankCache(); // before a benchmark sweep
```
## API Reference
- `hzToMel(hz): number` / `melToHz(mel): number` — Slaney/HTK closed forms.
- `buildMelFilterbank(spec): MelFilterbank` — cached triangular filterbank.
- `applyMelFilterbank(spectrum, bank): Float32Array` — dense mel-band vector.
- `clearMelFilterbankCache(): void` — drop every cached filterbank.
## Implementation Notes
The builder allocates `melBands + 2` mel-spaced points so each band has both a lower and an upper neighbour centre. Bin frequencies are computed once as `(i * sampleRate) / frameSize` to avoid a per-band recomputation. Each band's weights peak at `1` and taper linearly to `0` at the neighbour centres; no per-band energy normalisation is applied because the downstream MFCC log+DCT step is insensitive to global scaling.