|
miniDSP
A small C library for audio DSP
|
This tutorial walks through examples/phase_spectrum.c, which generates a three-component test signal, computes its phase spectrum with MD_phase_spectrum(), and visualises both the magnitude and phase with an interactive Plotly chart.
If you haven't read Computing the Magnitude Spectrum yet, start there – it covers the DFT fundamentals this tutorial builds on.
Every DFT coefficient \(X(k)\) is a complex number with a magnitude and an angle. The magnitude spectrum \(|X(k)|\) tells you how much energy is at frequency \(k\). The phase spectrum \(\phi(k)\) tells you the timing of that frequency component:
\[ \phi(k) = \arg X(k) = \mathrm{atan2}\!\bigl(\mathrm{Im}\, X(k),\,\mathrm{Re}\, X(k)\bigr) \qquad \phi(k) \in [-\pi,\, \pi] \]
| Signal | Phase at its bin |
|---|---|
| \(\cos(2\pi k_0 n / N)\) | \(\phi(k_0) = 0\) |
| \(\sin(2\pi k_0 n / N)\) | \(\phi(k_0) = -\pi/2\) |
| \(\cos(2\pi k_0 n / N + \varphi)\) | \(\phi(k_0) = \varphi\) |
| Impulse delayed by \(d\) samples | \(\phi(k) = -2\pi k d / N\) (linear) |
A time-delayed signal is the most important case: the DFT shift theorem says delaying a signal by \(d\) samples adds a linear phase ramp of slope \(-2\pi d / N\) radians per bin. This is the basis of the GCC-PHAT delay estimator (see MD_get_delay()).
Phase is only meaningful at bins where the magnitude is significant. At bins dominated by noise or leakage, \(\phi(k)\) is numerically unreliable – always examine MD_magnitude_spectrum() alongside the phase spectrum.
The test signal has three components at exact integer-bin frequencies (N = 1024, sample rate = 1024 Hz, so bin \(k\) corresponds to exactly \(k\) Hz). With exact bins there is no spectral leakage, so no windowing is needed and the phase values are bit-exact.
The three components and their expected phase values:
| Component | Bin | Expected \(\phi\) |
|---|---|---|
cos(50 Hz) | 50 | 0 |
sin(100 Hz) | 100 | \(-\pi/2\) |
cos(200 Hz, \f$\pi/4\f$ offset) | 200 | \(\pi/4\) |
MD_phase_spectrum() reuses the same cached FFT plan as MD_magnitude_spectrum() and MD_power_spectral_density(). Calling both in sequence costs only one plan lookup:
The output phase[k] is in radians, range \([-\pi, \pi]\). The magnitude output mag[k] lets you distinguish signal bins from noise bins when interpreting the phase.
The magnitude plot (top) confirms that energy is concentrated at bins 50, 100, and 200. The phase plot (bottom) shows:
At all other bins the phase is numerically arbitrary (magnitude is zero).
carg(), which calls atan2(Im, Re) and returns values in \([-\pi, \pi]\).The phase vocoder uses phase differences between consecutive STFT frames to track the instantaneous frequency of each bin, enabling high-quality time-stretching and pitch-shifting of audio. MD_phase_spectrum() provides the per-frame phase needed as input to such an algorithm.