The Discrete Fourier Transform
Contents
5.5. The Discrete Fourier Transform#
In this section, we will formally introduce the Discrete Fourier Transform (DFT). The DFT is the digital version of the Fourier transform, which was originally developed by Joseph Fourier in the early 19th century as a way to model heat flow with differential equations [Fou22]. The Fourier transform proved to be useful for many different applications, especially in audio and signal processing.
Many texts introduce the DFT by first starting with the continuous Fourier transform (using integral calculus), and then show the DFT as a discrete-time approximation of the continuous Fourier transform. We’ll take a different approach here, motivating the DFT from first principles entirely in the discrete time domain.
5.5.1. Dealing with phase#
Recall that in the previous section, when we compare a sinusoid
the resulting similarity score
In the worst case, if
then the similarity score will be 0 even if the frequency matches one of our reference signals.
This representation therefore cannot distinguish an out-of-phase sinusoid from a null signal
5.5.1.1. Comparing to multiple references#
In the specific case above, we could try to resolve the problem by changing the reference signals
But what if we try both?
Let’s see what happens if we take
In the following example, we’ll continue with the settings from the previous section: [samples / sec]
, [samples]
, and [cycles/sec]
).
This gives an input signal
where
We’ll compare to reference signals
Fig. 5.13 A sinusoid
Fig. 5.13 illustrates what happens to similarity scores as we vary the phase
Recall from (5.8) that the similarity score for
If
Otherwise, if
Combining this with the derivation above, we get the total similarity score:
5.5.1.2. Combining terms#
Stepping back, if we take
.
If we additionally scale
.
This is starting to look pretty interesting.
However, it would be better if both scores had the same sign.
We can accomplish this by changing which signals we compare to: instead of comparing to
.
Now this is interesting.
We started with a sinusoid
Fig. 5.14 Left: three different waves of the form
Rather than carry around two coordinates for each frequency comparison, we can combine them into a single complex number.
We will associate the comparison to
5.5.2. The Discrete Fourier Transform#
Finally, we can formally define the discrete Fourier transform (DFT).
The DFT takes as input a signal
Definition 5.2 (The discrete Fourier transform (DFT))
For an arbitrary input signal
or, equivalently using Euler’s formula (4.1),
The DFT equation (5.11) can be implemented in code as follows:
import numpy as np
def dft(x):
'''The Discrete Fourier Transform
Parameters
----------
x : np.ndarray
The input signal
Returns
-------
X : np.ndarray, same shape as x
The DFT sequence: X[m] corresponds to analysis frequency index m
'''
# Get the number of samples = number of frequencies
N = len(x)
# Allocate the output array
X = np.zeros(N, dtype=np.complex)
# For each analysis frequency
for m in range(N):
# For each sample
for n in range(N):
# Compare to cos and -sin at this frequency
X[m] = X[m] + x[n] * (np.cos(2 * np.pi * m / N * n)
- 1j * np.sin(2 * np.pi * m / N * n))
# Return the DFT array
return X
Note that this code will be extremely slow, and should not be used for long signals.
Instead, you should probably use a fast Fourier transform (FFT) implementation, like the one provided by numpy
:
import numpy as np
X = np.fft.fft(x)
5.5.2.1. Some facts about the DFT#
In the coming chapters, we will devote a significant amount of time to understanding everything we can about the DFT. For the time being, here is a brief list of basic facts that can be derived by a close examination of our process in building up the DFT.
For convenience, we will write
The DFT sequence
does not index time like the sample array does. Instead, each measures the contribution of a sinusoid at a particular frequency to the entire signal .The DFT sequence always has the same number of analysis frequencies as the number of samples
. The first correspond to positive frequencies, the last correspond to negative frequencies.The
component is always a real number—this follows immediately from (5.10). It is known as the direct current (DC) component, and always equals the sum of the sample values.For each
, the magnitude (np.abs(X[m])
) corresponds to the amplitude of a sinusoid at frequency present in the signal. Similarly, its angle in the complex plan, (np.angle(X[m])
), corresponds to the phase of the sinusoid.The sequence of values
is known as the magnitude spectrum of .The magnitude
is not the same as the real part . Remember that for a complex number ,
Both the real and imaginary parts of the number contribute to both magnitude and phase.
5.5.3. Summary#
Developing the DFT takes a lot of work. So does understanding it completely. Don’t panic if this section was difficult to get through.
To finish off this chapter, the next section will show several examples signals and their corresponding DFTs.