Lab: Deconstructing Audio with Fourier Transforms

Inspired by the Avery Wang (Shazam) Landmark Algorithm

Learning Objectives

1. The Mathematical Foundation

The Fourier Transform allows us to see which frequencies are present in a signal. However, music changes over time. To capture this, we use the STFT, which applies the Fourier Transform to small, overlapping windows of time.

$X(m, \omega) = \sum_{n=-\infty}^{\infty} x[n] w[n - m] e^{-j \omega n}$
(Where $w[n]$ is a window function like Hamming or Hann)

2. Lab Procedures

Step 1: Visualizing the Waveform vs. the Spectrum

Load a 5-second clip of a song. Notice how the raw waveform (Amplitude vs. Time) tells us nothing about the melody or pitch.

import numpy as np
import matplotlib.pyplot as plt
from scipy.io import wavfile

fs, data = wavfile.read('sample_audio.wav')
plt.plot(data[:fs*5])
plt.title("Time Domain: Signal Amplitude")

Step 2: Generating the Spectrogram

Use the Discrete Fourier Transform (DFT) repeatedly across the signal to create a Spectrogram. This is the "Heat Map" of music.

plt.specgram(data, Fs=fs, NFFT=2048, noverlap=1024)
plt.ylabel('Frequency [Hz]')
plt.xlabel('Time [sec]')

Step 3: Peak Extraction (The Constellation Map)

Shazam doesn't store the whole spectrogram—it’s too much data. It only stores the strongest frequency peaks. These peaks are robust against background noise.

Exercise:

  1. Find local maxima in the spectrogram.
  2. Filter out frequencies below 300Hz (bass) and above 5000Hz (harmonics) to focus on the "information-rich" zone.
  3. Plot these points on a coordinate plane (Time vs. Frequency). This is your Constellation Map.

Step 4: Combinatorial Hashing

Pick an "Anchor Point" in your constellation map. Pair it with several "Target Points" in a window ahead of it. Create a hash for each pair:

Hash = [Freq_Anchor | Freq_Target | Delta_Time]

This hash is unique to the song's structure and remains the same even if the song starts playing at a different time.

3. Analysis Questions

  1. Frequency Resolution: If you increase the sampling rate, what happens to the number of bins in your Fourier Transform?
  2. Noise Robustness: Why does the algorithm still work in a noisy bar? (Hint: Think about what happens to the highest peaks when low-level white noise is added).
  3. The Uncertainty Principle: Why can't we have perfect resolution in both time and frequency simultaneously?