Introduction

Every time you tune a guitar or sing a scale, you're navigating a logarithmic world. The note A4 vibrates at 440 Hz; A5, one octave higher, vibrates at 880 Hz — twice as fast. Go up another octave to A6 and you reach 1760 Hz. Each octave doubles the frequency, so the jumps grow larger and larger in absolute terms, even though to your ear every octave sounds like the same-sized step.

The classical Fast Fourier Transform (FFT) knows nothing of this. It carves the frequency axis into evenly spaced bins: 0 Hz, 10 Hz, 20 Hz, … If your bin width is 10 Hz you get the same resolution at 100 Hz as at 10 000 Hz — lousy near the bass, absurdly fine near the treble, and completely misaligned with how pitch perception works.

In 1978, the engineer Judith Brown (formalised in her 1991 paper) introduced the Constant-Q Transform (CQT) to fix exactly that mismatch. The "Q" stands for quality factor — the ratio of a bin's centre frequency to its bandwidth — and the key insight is to keep Q the same for every bin. That single constraint forces the frequency axis to become logarithmic, so every octave occupies the same number of bins no matter where on the keyboard you are.

The result is a spectral representation that is naturally aligned with musical notation: the same chord pattern looks identical in any key, transposition just shifts the pattern up or down by a fixed number of bins.

Try It

The demo below plots a one-octave frequency axis two ways: the linear FFT scale (left) and the logarithmic CQT scale (right). Click any piano key to light up where that note lands on each axis.

<!-- {{c_main_comment}} -->
<p class="hint">{{hint_para}}</p>
<div class="axes-wrap">
  <div class="axis-block">
    <div class="axis-label">{{label_fft}}</div>
    <div id="linear-axis" class="axis linear-axis" title="{{title_linear}}"></div>
    <div class="axis-desc">{{desc_linear}}</div>
  </div>
  <div class="axis-block">
    <div class="axis-label">{{label_cqt}}</div>
    <div id="log-axis" class="axis log-axis" title="{{title_log}}"></div>
    <div class="axis-desc">{{desc_log}}</div>
  </div>
</div>
<!-- {{c_keyboard_comment}} -->
<div id="keyboard" class="keyboard" aria-label="{{aria_keyboard}}"></div>
<div class="status" id="status">{{status_default}}</div>
/* {{c_css_comment}} */
* { box-sizing: border-box; }
body { font-family: system-ui, sans-serif; color: #222; margin: 0; padding: 14px; }
.hint { font-size: .88rem; color: #444; margin: 0 0 .8rem; line-height: 1.5; }
.axes-wrap { display: flex; gap: 1rem; margin-bottom: .8rem; }
.axis-block { flex: 1; display: flex; flex-direction: column; gap: .3rem; }
.axis-label { font-size: .75rem; font-weight: 700; color: #1d3557; text-transform: uppercase; letter-spacing: .05em; }
.axis { position: relative; height: 180px; background: #eef1f5; border-radius: 8px; overflow: hidden; border: 1px solid #cdd9e3; }
.axis-desc { font-size: .72rem; color: #666; line-height: 1.35; }
/* {{c_tick_comment}} */
.tick { position: absolute; width: 100%; border-top: 1px solid #cdd9e3; }
.tick-label { position: absolute; right: 4px; font-size: 9px; color: #888; transform: translateY(-50%); white-space: nowrap; }
/* {{c_dot_comment}} */
.note-dot { position: absolute; width: 10px; height: 10px; border-radius: 50%; background: #e63946; left: 50%; transform: translate(-50%, -50%); transition: opacity .25s; }
.note-dot.active { box-shadow: 0 0 6px 3px rgba(230,57,70,.4); }
/* {{c_keyboard_css_comment}} */
.keyboard { display: flex; gap: 3px; margin-bottom: .6rem; }
.key { flex: 1; height: 60px; border-radius: 6px; cursor: pointer; border: none; font-size: 9px; font-weight: 700; color: #555; display: flex; align-items: flex-end; justify-content: center; padding-bottom: 4px; transition: background .12s; user-select: none; }
.key.white { background: #f5f7fa; border: 1px solid #c5ccd5; }
.key.black { background: #2d3748; color: #ddd; flex: 0.65; }
.key.white:hover { background: #dce6f0; }
.key.black:hover { background: #1a2030; }
.key.active { background: #e63946 !important; color: #fff; }
.status { font-size: .95rem; font-weight: 600; min-height: 1.4em; color: #1d3557; }
// Code not found

Notice that on the linear axis the lower notes cluster together and the higher ones spread out — just the opposite of what your ear hears. On the log axis every semitone is exactly the same distance from the next, mirroring the equal-tempered scale you'd see on sheet music. The Constant-Q Transform is simply the mathematical machinery that computes spectrum values at those logarithmically placed centre frequencies.

The Real Math

The defining equation of the CQT for bin kk is:

X[k]=1Nkn=0Nk1x[n]Wk(n)e2πiQn/NkX[k] = \frac{1}{N_k} \sum_{n=0}^{N_k - 1} x[n] \, W_k(n) \, e^{-2\pi i Q n / N_k}

where NkN_k is the window length for bin kk and WkW_k is a tapering window (Hann, Hamming, etc.). What makes this different from the FFT is that NkN_k varies:

  • The centre frequency of bin kk is fk=fmin2k/Bf_k = f_{\min} \cdot 2^{k/B}, where BB is the number of bins per octave (typically 12 for semitones).
  • The bandwidth of bin kk is Δfk=fk/Q\Delta f_k = f_k / Q.
  • Therefore the window length satisfies Nkfs/Δfk=fsQ/fkN_k \propto f_s / \Delta f_k = f_s \cdot Q / f_k — longer windows for low frequencies, shorter ones for high.

Keeping QQ constant across all bins is what forces the logarithmic spacing. In contrast, the FFT uses a single window length for every bin, giving uniform bandwidth Δf\Delta f and a linear frequency axis.

Computing the CQT naively costs O(NlogNBoctaves)O(N \log N \cdot B \cdot \text{octaves}), but efficient algorithms — introduced by Brown & Puckette (1992) and later by Schörkhuber & Klapuri (2010) — reduce this by cascading the FFT and subsampling at each octave, bringing the cost closer to that of a few FFTs.

A key theoretical point: the CQT is not an orthogonal transform. Its basis functions at different bins overlap, which means reconstruction requires a pseudo-inverse or iterative methods — unlike the FFT, which inverts perfectly with a single IFFT call. See also compression, where transform invertibility is a central design concern.

Where It Matters

Because the CQT is aligned with how humans hear pitch, it has become the standard front end for almost every music-understanding algorithm:

  • Automatic music transcription: identifying which notes are played at each moment is far easier when the spectrogram already places notes on a regular grid, exactly as in sheet music.
  • Chord and key detection: a chord looks the same in any key on a CQT spectrogram — the pattern simply shifts up or down, making template-matching straightforward.
  • Pitch shifting and time stretching: audio editors like Audacity and DAWs use log-frequency representations to move a note up or down without changing its timbre.
  • Genre and instrument classification: machine-learning models trained on CQT spectrograms generalise better across keys and tempos than those trained on plain FFT output.
  • Audio fingerprinting: services like Shazam use compact spectral landmarks derived from log-frequency representations to match a snippet against a vast database in milliseconds.

The same logarithmic idea also appears in the Mel scale (used in speech recognition) and chromagrams (which collapse all octaves onto a single 12-bin pitch class wheel). Both are relatives of the CQT, trading some frequency resolution for compactness. For a broader look at how transforms underpin compression and pattern matching, explore those articles next.

Conclusion

The Constant-Q Transform is a remarkably focused idea: hold the ratio of centre frequency to bandwidth fixed, and the entire frequency axis reorganises itself into the logarithmic ladder that music has always used. Notes an octave apart land on bins separated by a fixed count, chords look the same in every key, and the representation finally matches what our ears actually hear.

It is a reminder that the right coordinate system matters enormously. The FFT is not wrong — it is optimal for many things — but for music it asks the wrong question. The CQT simply asks: what if every frequency bin were as wide as the pitch perception it needs to capture? That one reframing has made a whole field of music-information retrieval possible.

Share this article

Pick a channel — or use your device's native share sheet.

Comments

Loading comments...

https://www.kipuhub.com/en/article/constant-q-transform/Content licensed under CC BY-NC 4.0.