daw-ui

Spectrum

How loud each frequency is, from the bins of an FFT, on a logarithmic axis, drawn on canvas once per frame without rendering, as the analysers of equalizers show it.

Anatomy

import { Spectrum } from '@addstack/daw-ui/react';

// One array for the whole time; the analyser fills it anew each frame.
const bins = new Float32Array(analyser.frequencyBinCount);

<Spectrum.Root
  read={() => (analyser.getFloatFrequencyData(bins), bins)}
  sampleRate={audio.sampleRate}
  aria-label={t('spectrum')}
  className="h-40"
>
  <Spectrum.Fill className="text-emerald-500/15" />
  <Spectrum.Peak className="text-white/30" />
  <Spectrum.Line className="text-emerald-400" />
</Spectrum.Root>

A spectrum takes the bins of an FFT: levels in dB, evenly spaced from 0 Hz to half the sample rate, as AnalyserNode.getFloatFrequencyData fills them, or as your audio engine sends them. sampleRate tells which bin is which frequency. read is called once per animation frame, on the loop meters share, and the parts draw on canvas; nothing renders. For a spectrum that does not change, such as a whole sample's or a reference to compare with, pass bins instead.

It is an image: name it with aria-label, in your application's language. Size it with CSS; the parts fill it, and draw in their CSS color.

Axes

Across, frequency from min to max hertz (20 Hz … 20 kHz), on scales.log by default, so that each octave takes the same width; up, level from floor to ceiling dB (−90 … 0). A Slider or an XY pad with the same min, max and scale lines up with it: their thumbs sit over the frequencies they set.

Where a column of pixels covers many bins, at the high end, it shows the loudest of them, so that a narrow peak shows; where it covers less than one, at the low end, a smooth curve runs through the bins around it, so that the bass is not a staircase.

tilt adds that many dB per octave above 1 kHz and takes as many below it: at 4.5, pink noise, and most music, looks flat, as in FabFilter Pro-Q.

Ballistics

An AnalyserNode smooths its bins already (smoothingTimeConstant), so the line follows them by default. For the ballistics of a meter, set the analyser's smoothing to 0 and fall to the dB per second the line may fall; it rises at once. Spectrum.Peak holds each column's highest level for hold milliseconds, then lets it fall at its own fall.

How it stays fast

The bins each column covers are worked out once per size and axis. Each frame, the spectrum turns the bins into one level per column, applies the ballistics, and each part draws one path on its own canvas, at the screen's resolution. Out of sight, it reads and draws nothing. Eight spectra of 2048 bins, live, render nothing in React; see performance.

API reference

Root

Holds the bins and the axes. Renders a <div> with role="img".

Prop

Type

Line

The spectrum as a line. Renders a <canvas>.

Prop

Type

Fill

The area under the spectrum. Renders a <canvas>.

Prop

Type

Peak

The highest levels lately, as a line. Renders a <canvas>.

Prop

Type

On this page