4 Fast Fourier Transform

Fast Fourier Transform

Review all the signal processing topics from part IB.

The key idea of the Fast Fourier Transform (FFT) is divide and conquer

  • The Discrete Fourier Transform (DFT) can be represented as a matrix multiplication

  • Sum the odd and even terms separately, i.e. the problem of size $N$ is divided into $$ \begin{aligned} x(k) &= \sum_0^{N-1} x_n e^{2\pi i k n/N}\\ x(k) &= \sum_0^{N/2-1} x_{2n} e^{2\pi i k 2n/N}+ \sum_0^{N/2-1} x_{2n+1} e^{2\pi i k (2n+1)/N}\\ x(k) &= \sum_0^{N/2-1} x_{2n} e^{2\pi i k n/(N /2)}+ e^{2\pi i k /N}\sum_0^{N/2-1} x_{2n+1} e^{2\pi i k n/(N/2)}\\ x(k) &= x_\text{even} (k)+ e^{2\pi i k /N}x_\text{odd}(k)\end{aligned} $$

    Notice that the discrete $x_\text{even}$ and $x_\text{odd}$ are respectively periodic over $\frac{N}{2}$. The problem of size $N$ has been reduced to $$ S(N) = 2 \times S\left(\frac N 2\right) +1$$ where $S$ is the cost function. Explicitly, $$ S(N) \propto O\left(N \log(N)\right) $$

Using $2^N$ for array size is important.

import numpy as np
import matplotlib.pyplot as plt

dt = 0.01
fftsize = 256
t=np.arange(fftsize)*dt

y = np.cos(2*np.pi*12*t) + 0.5* np.sin(2*np.pi*34*t)

plt.plot(t,y)

Y = np.fft.fft(y)

plt.subplot(2,1,1); plt.plot(np.abs(Y))

f = np.fft.fftfreq(fftsize,dt) # get the array of frequencies that correspond to elements of Y
plt.subplot(2,1,2); plt.plot(f, np.abs(Y)) # this creates flop-back lines

Y2 = np.fft.fftshift(Y) # rolls the array from + -> - to increasingly positive
f2 = np.fft.fftshift(f)

plt.subplot(f2, Y2) # no flop-back