Skip to content

CQT

constant-Q transform of an exponential chirp

Constant-Q transform: geometrically spaced bins with a constant frequency-to-bandwidth ratio [brown1991], computed by recursive octave decimation [schorkhuber2010]. The log-frequency axis matches musical pitch (an exponential chirp renders as a straight line), which is why it is the front end of choice for music analysis. The VQT generalizes it with a bandwidth offset; Chroma folds its bins onto pitch classes.

specux.cqt(x, *, sr, hop_length=512, fmin=None, n_bins=84,
bins_per_octave=12, filter_scale=1.0, sparsity=0.01,
tuning=0.0, output="magnitude", eps=1e-10, backend="auto")
import numpy as np
import specux
x = np.random.randn(8, 4 * 22050).astype(np.float32)
C = specux.cqt(x, sr=22050, n_bins=84)
C.shape # (8, 84, 173) = (..., n_bins, n_frames)

Bin k is centered on fmin * 2**(k / bins_per_octave) Hz; frame t is centered on t * hop_length. Leading dimensions pass through.

How it computes

The signal pyramid halves per octave (a zero-phase half-band FIR), so every octave runs at its natural rate: one boxcar complex STFT per octave, reduced by that octave’s frequency-domain wavelet basis [brown1992]. The analysis window lives inside the basis, each wavelet is L1-normalized, and the per-bin 1/sqrt(length) scaling is folded into the basis rows, so a unit sinusoid at a bin center responds with 1/(2*sqrt(length)) at every octave.

Parameters

  • sr: sample rate in Hz (required; bin frequencies are absolute).
  • hop_length: frame advance at the full rate. Must be divisible by 2**(n_octaves - 1) so every pyramid level advances by an integer; anything else raises with the nearest valid value.
  • fmin: lowest bin frequency; None means C1 (32.70 Hz).
  • n_bins, bins_per_octave: bin count and density. Any values that fit under Nyquist work, including hundreds of bins per octave.
  • filter_scale: Q scaling; below 1 trades frequency resolution for time resolution.
  • sparsity: fraction of each basis row’s magnitude trimmed from the tails (0 keeps the full rows).
  • tuning: bin offset in fractions of a bin.
  • output: "magnitude" (the CQT convention, default), "complex", "power", or "db".
  • backend: "auto", "cuda", "cpu", or "metal" for the per-octave transforms.

The configured form

t = specux.CQT(sr=22050, n_bins=84)
C = t(x) # (..., n_bins, n_frames)
assert specux.CQT(**t.to_dict()) == t

The torch Module for training pipelines is specux.transforms.CQT.

References