DEV Community

Tania Alwan
Tania Alwan

Posted on

Spectrogram Explained: How to Read One and Make Your Own (With a Python Example)

By Tania Alwan

A spectrogram is the picture most audio tools look at before they do anything clever. Noise removers, pitch trackers and stem splitters all start from some version of it. If you can read one, you can spot a hum, a harsh "s", a clipped take or a buried vocal in seconds. This post explains what the axes mean, how the picture is computed, and gives a short Python example you can run.

What a spectrogram shows

A spectrogram plots sound as an image:

  • Horizontal axis: time, left to right.
  • Vertical axis: frequency, low pitches at the bottom, high at the top.
  • Colour or brightness: how much energy is present at that time and frequency, usually in decibels.

A sung note appears as a stack of horizontal lines: the fundamental at the bottom and its harmonics above it, evenly spaced. A drum hit appears as a short vertical smear, because it contains many frequencies at once for a brief moment.

How it is computed: the short-time Fourier transform

The standard method is the short-time Fourier transform (STFT):

  • Cut the signal into short overlapping frames, for example 2048 samples each.
  • Multiply each frame by a window function (such as Hann) to reduce edge artefacts.
  • Run a Fourier transform on each frame to get the energy per frequency bin.
  • Stack the results side by side, one column per frame.

The trade-off you cannot escape

Frame length controls a fixed compromise between time and frequency detail:

  • Long frames give fine frequency resolution (good for telling close pitches apart) but blur fast events.
  • Short frames show transients sharply but smear pitch.
  • The frequency spacing between bins equals the sample rate divided by the frame length. At 22,050 Hz with 2048-sample frames, that is about 10.77 Hz.

A small Python example

This script builds a test signal (one second of 440 Hz, then one second of 880 Hz), computes its spectrogram with SciPy and prints the strongest frequency over time. You need numpy and scipy.

import numpy as np
from scipy.signal import spectrogram

sr = 22050                      # sample rate in Hz
t = np.arange(0, 2.0, 1 / sr)   # two seconds of time stamps
# 1 s of A4 (440 Hz), then 1 s of A5 (880 Hz)
audio = np.where(t < 1.0, np.sin(2 * np.pi * 440 * t), np.sin(2 * np.pi * 880 * t))

freqs, times, power = spectrogram(audio, fs=sr, nperseg=2048, noverlap=1536)
power_db = 10 * np.log10(power + 1e-12)   # convert to decibels

# strongest frequency in a few time slices
for i in range(0, len(times), 10):
    peak = freqs[np.argmax(power_db[:, i])]
    print(f"{times[i]:.2f} s -> {peak:.0f} Hz")

print("frequency resolution:", round(freqs[1] - freqs[0], 2), "Hz")
print("time step:", round(times[1] - times[0], 4), "s")
Enter fullscreen mode Exit fullscreen mode

On my machine it prints peaks of 441 Hz for the first second and 883 Hz for the second, a frequency resolution of 10.77 Hz and a time step of about 0.0232 s. The peaks are not exactly 440 and 880 because the answer snaps to the nearest bin. That is the resolution trade-off in action. To plot the image, pass power_db to matplotlib.pyplot.pcolormesh(times, freqs, power_db).

Reading real recordings

Once you have a spectrogram of your own vocal, look for these patterns:

  • A steady line at 50 or 60 Hz (and multiples): mains hum from cables or gear.
  • A haze across the whole height between phrases: broadband noise such as fans or air conditioning.
  • Bright patches around 5 to 10 kHz on "s" and "t" sounds: sibilance a de-esser can tame.
  • Faint copies of the voice trailing after each phrase: room reverb.
  • Flat tops in the waveform with energy smeared upward: clipping, which no filter fully undoes.

Where AI tools come in

Many separation and clean-up models work on spectrogram-like representations: they estimate which parts of the picture belong to the voice and which belong to the rest, then rebuild audio from that. Tools such as Demucs (open source), iZotope RX and the Voicestars stems splitter package this for people who do not want to train anything. Whatever you use, compare the spectrogram before and after: leftovers and artefacts are often easier to see than to hear.

Takeaways

  • Spectrogram = time on X, frequency on Y, energy as colour.
  • It is built with the STFT, and frame length trades time detail for frequency detail.
  • Learn the visual signatures of hum, noise, sibilance and reverb, and you will fix recordings faster.

Disclosure: this article was written in partnership with Voicestars.

Top comments (0)