← Gallery Chroma filterbank — pitch-class filters

Chroma filterbank — pitch-class filters

filters/index.js

How does a chromagram decide which frequencies count as a C, a C#, or an A? This heatmap shows the answer: twelve rows of frequency filters, one per pitch class, with Gaussian bumps that repeat every octave and an octave-dominance envelope fading the extremes. Technically: filters.chroma({sr:22050, n_fft:2048}) is rendered as a 12 × 1025 heatmap (each row is a pitch class, C at the bottom, base_c grid; x-axis is FFT bin frequency 0 → 11025 Hz). Proofs: the pitch class with the most weight at the FFT bin nearest 440 Hz must be 9 (A), and every column's L2 norm must be ≤ 1 + 1e-6 (per-bin norm=2 column normalization, then dominance weighting only ever shrinks it).

x: 0 Hz → 11025 Hz (1025 FFT bins) · y: pitch class B (top) → C (bottom)