Professional Documents
Culture Documents
It's finally time to start looking at the relationship between the discrete Fourier transform
(DFT) and the discrete-time Fourier transform (DTFT). Let's look at a simple rectangular
pulse, for . The DTFT of is:
M = 8;
w = linspace(-2*pi, 2*pi, 800);
X_dtft = (sin(w*M/2) ./ sin(w/2)) .* exp(-1j * w * (M-1) / 2);
plot(w, abs(X_dtft))
title('|X(\omega)|')
It turns out that, under certain conditions, the DFT is just equally-spaced samples of the
DTFT. Suppose is the P-point DFT of . If is nonzero only over the finite
domain , then equals at equally spaced intervals of :
The MATLAB function fft computes the DFT. Here's the 8-point DFT of our 8-point
rectangular pulse:
x = ones(1, M);
X = fft(x)
X =
8 0 0 0 0 0 0 0
One 8 and a bunch of zeros?? That doesn't seem anything like the DTFT plot above. But
when you superimpose the output of fft in the right places on the DTFT plot, it all
becomes clear.
P = 8;
w_k = (0:P-1) * (2*pi/P);
X = fft(x);
plot(w, abs(X_dtft))
hold on
plot(w_k, abs(X), 'o')
hold off
Now you can see that the seven zeros in the output of fft correspond to the seven places
(in each period) where the DTFT equals zero.
You can get more samples of the DTFT simply by increasing P. One way to do that is to
zero-pad.
x16 =
Columns 1 through 15
1 1 1 1 1 1 1 1 0 0 0 0
0 0 0
Column 16
P = 16;
X16 = fft(x16);
w_k = (0:P-1) * (2*pi/P);
X = fft(x);
plot(w, abs(X_dtft))
hold on
plot(w_k, abs(X16), 'o')
hold off
Another way to increase P is to use the fft(x,P) syntax of the fft function. This syntax
computes the P-point DFT of x by using zero-padding. Let's try a 50-point DFT.
P = 50;
Xp = fft(x, P);
w_k = (0:P-1) * (2*pi/P);
X = fft(x);
plot(w, abs(X_dtft))
hold on
plot(w_k, abs(Xp), 'o')
hold off
If you've ever wondered what that whole zero-padding business was all about with Fourier
transforms, now you know. When you tack on a bunch of zeros to a sequence and then
compute the DFT, you're just getting more and more samples of the DTFT of the original
sequence.
I think the next logical place to go in our Fourier exploration is to start considering some of
the reasons why many people find the output of fft so surprising or puzzling. Here's a
sample:
Why isn't the zero frequency (or "DC" frequency) in the center of the output from
fft?
Why isn't the output of fft real when the input is symmetric?
You can follow any responses to this entry through the RSS 2.0 feed. Both comments and pings are currently
closed.
I am enjoying this series of blogs & encourage you to continue. This latest entry
was very helpful. I suspect that most users who use the fft function are really after a
dft with good calculation performance & really dont care how much of Cooley &
Tukeys genius is incorporated in the routine.
I think most users are happy to trust that World Class experts in signal processing
have ensured that these functions in MatLab do the right thing & perform
efficiently.
However, for folks like me who dont have a graduate exposure to signal
processing, Im interested in an fft type function because I want some frequency
domain insight into some real, time domain data. As such, the single detail that
always trips me up is how to relate the output of the fft function to a vector of real
frequencies that are meaningful to me. Im not talking about the difference between
Hertz & radians per second. Im talking about how the frequencies are non-
dimensionalized in the world of signal processing.
Both the FRP for fft & this blog entry are good examples of this issue. No where in
this blog do you mention units at all. Your frequency vector w spans / + 2pi, so
most of us would assume it is radians per second. But, this isnt specified and you
dont label the X axis of your plots. So, we are left guessing.
Lay users like me are further tripped up by this concept of negative frequencies. The
FRP for fft is just as bad in that it only addresses the frequency issue by inference in
the single example wherein they use the common shorthand of taking advantage of
the complex-conjugate nature of the fft output, throw away last half of the fft output
and generate a vector of only positive frequencies.
Certainly an fft function is more general & powerful than just for understanding
frequency domain characteristics of time domain data, so it is appropriate for
MatLab to provide this generality. However, since many, if not most, uses are for
understanding time domain data, the FRP should address this frequency detail
specifically.
Further, the FRP should include several more examples including ones that
specifically demonstrate the effect of real vs complex input data.
2. Amit replied on March 17th, 2010 at 15:00 UTC :
The high value output from the fft is carried forward till my end result.
Thanks Steve ,ill try reading more on fft and using different scale factors
Hi Steve,
Thanks for this excellent series of blogs on the FT. I feel its one of those topics that
cannot be revisited enough. I use the DFT in matlab a lot for image processing tasks
but I can still manage to get confused about some of the concepts involved every so
often.
I have a question so far- you mention here that zero-padding is effectively for
increasing the sampling of the FT but isnt it also for preventing wraparound error
when filtering too?
Thanks,
Fen
FenI appreciate the encouragement, thanks. You are right that there is a different
way to think about zero-padding when you are doing frequency-domain based
filtering. I imagine Ill get to that, but Im not sure when. I touched briefly on
windowing back in December, and Ill come back to that topic again. I havent
really thought much yet about how to talk about Gibbs phenomenon. Thanks for
taking the time to make good suggestions.
In my Fourier transform series I've been trying to address some of the common points of
confusion surrounding this topic. For today's espisode I want to look at how to use the fft
function to produce discrete-time Fourier transform (DTFT) magnitude plots in the form
you might see in a textbook. Recall that the fft computes the discrete Fourier transform
(DFT). I described the relationship between the DFT and the DTFT in my March 15 post.
For my example I'll work with a sequence that equals 1 for and equals 0
elsewhere.
Here's a plot of the DTFT magnitude of this sequence:
x = ones(1, 5)
x =
1 1 1 1 1
X = fft(x);
plot(abs(X))
Wow, that's not anywhere close to the DTFT magnitude plot above. And why does it look
like it's only got two points? Well, take a look at the actual values of X:
X =
5 0 0 0 0
We have a 5 and four 0s. What's going on? I explained this back in my March 15 post when
I discussed the relationship between the DFT and the DTFT. The outputs of the DFT are
samples of the DTFT, and in this case the sample locations just happen to align with the
locations of four zeros in the DTFT.
You can get a finer sampling (and a much nicer-looking DTFT plot) by zero-padding. Here
I'll use the zero-padding syntax of fft.
N = 256;
X = fft(x, N);
plot(abs(X))
That's a smoother-looking curve, but it still looks quite a bit different than the DTFT
magnitude plot above. To explain the MATLAB output we're looking at, let me show a
DTFT magnitude plot that shows three periods instead of just one.
You can see that the output from MATLAB is one period of the DTFT, but it's not the
period normally plotted, which is from to . Instead, it's the period from 0 to . To get a
plot from to , use the fftshift function.
plot(abs(fftshift(X)))
That leaves us with the question of labeling the frequency axis. We want a plot in radians
from to .
The way I always remember the frequency scaling between the DFT and the DTFT is this:
the length of the DFT corresponds to the frequency in the DTFT.
w = 2*pi * (0:(N-1)) / N;
But we're calling fftshift to plot the magnitude of the DTFT, so we have to perform a
similar shift on our frequencies:
w2 = fftshift(w);
plot(w2)
Now our frequencies start at and have a discontinuity in the middle. Here's one way to
fix that up:
w3 = unwrap(w2 - 2*pi);
plot(w3)
Now we can redo our magnitude DTFT plot with the x-axis labels.
plot(w3, abs(fftshift(X)))
xlabel('radians')
Often I like to see the multiples of more clearly along the x-axis. One way to accomplish
this is to normalize the frequency variable by .
plot(w3/pi, abs(fftshift(X)))
xlabel('radians / \pi')
Another option is to try Alan's pilabels contribution on the MATLAB Central File
Exchange.
For the next time, I'm thinking of tackling the question of why the following output is
complex:
fft([1 2 3 2 1])
ans =
You can follow any responses to this entry through the RSS 2.0 feed. Both comments and pings are currently
closed.
Steve,
I went through the Fourier articles yesterday, and theyre very helpful. Thanks
Steve.
Fs = 20;
N=100;
F=[0:N-1]/N*Fs;
plot(unwrap(fftshift(F)-Fs))
SanguineCatOops, I didnt explain that quite right. The function unwrap fixes
discontinuities by adding multiples of 2*pi. The thing you are trying to unwrap isnt
made up of phase angles and the discontinuity isnt close to a multiple of 2*pi, so
unwrap is the wrong thing to use.
Nice Post, Steve. I learned something from the use of unwrap function here.
Regarding to labeling the frequency axis of FFT spectrum output, there might be a
much easy way like this:
w4=2*pi*(-N/2:N/2-1)/N;
figure
plot(w4/pi,abs(fftshift(x)));
xlabel(radians / \pi);
My first introduction to the unwrap function its one I use so often Id created a
subfunction of my own to do it, without discovering unwrap. I can at least console
myself that my custom version is faster but I rarely call it multiple times, so might
just switch to the greater redundancy of unwrap.
Interesting to see that you can get the DTFT from the DFT; oddly using DFTs all
the time I was looking for a fast way to calculate the DTFT recently.
Dings code, as implied, would need a separate definition of w4 in the case of odd
N, eg for unpadded DFTs.