Lesson 15 of 15

Spectral Analysis

Spectral Analysis

Spectral analysis extracts perceptual and statistical features from the frequency representation of a signal. Two fundamental descriptors are the spectral centroid and spectral flatness.

Spectral Centroid

The spectral centroid is the "center of mass" of the spectrum. It correlates with perceived brightness — a higher centroid sounds brighter.

C=kfkX[k]kX[k]C = \frac{\sum_k f_k \cdot |X[k]|}{\sum_k |X[k]|}

where fkf_k is the frequency (in Hz) of bin kk and X[k]|X[k]| is its magnitude.

Example: With magnitudes [1,2,3,4][1, 2, 3, 4] at frequencies [0,1,2,3][0, 1, 2, 3] Hz:

C=01+12+23+341+2+3+4=2010=2.0 HzC = \frac{0 \cdot 1 + 1 \cdot 2 + 2 \cdot 3 + 3 \cdot 4}{1+2+3+4} = \frac{20}{10} = 2.0 \text{ Hz}

Spectral Flatness

Spectral flatness (also called Wiener entropy) measures how noise-like vs tonal a signal is:

F=geometric mean of X[k]arithmetic mean of X[k]F = \frac{\text{geometric mean of } |X[k]|}{\text{arithmetic mean of } |X[k]|}

  • F1F \approx 1: white noise (flat spectrum, all bins equal)
  • F0F \approx 0: pure tone (energy concentrated in one bin)

If any magnitude is zero or the arithmetic mean is zero, return 00.

Your Task

Implement:

  • spectral_centroid(magnitudes, freqs) — weighted average frequency
  • spectral_flatness(magnitudes) — geometric mean / arithmetic mean
import math

def spectral_centroid(magnitudes, freqs):
    total = sum(magnitudes)
    if total == 0:
        return 0.0
    return sum(f * m for f, m in zip(freqs, magnitudes)) / total

def spectral_flatness(magnitudes):
    n = len(magnitudes)
    arith = sum(magnitudes) / n
    if arith == 0:
        return 0.0
    if any(m <= 0 for m in magnitudes):
        return 0.0
    geo = math.exp(sum(math.log(m) for m in magnitudes) / n)
    return geo / arith
Python runtime loading...
Loading...
Click "Run" to execute your code.