Gohann
Gohann

Reputation: 155

Matlab, FFT frequency range differences or are they the same?

I'm trying to understand how the FFT in matlab works, particularly, how to define the frequency range to plot it. It happens that I have read from matlab help links and from other discussions here and I think (guess) that I'm confused about it. In the matlab link: http://es.mathworks.com/help/matlab/math/fast-fourier-transform-fft.html they define such a frequency range as:

f = (0:n-1)*(fs/n)

with n and fs as:

n = 2^nextpow2(L); % Next power of 2 from length of signal x
fs = N/T; % N number of samples in x and T the total time of the recorded signal

But, on the other hand, in the previous post Understanding Matlab FFT example (based on previous version of matlab), the resulting frequency range is defined as:

f = fs/2*linspace(0,1,NFFT/2+1);

with NFFT as the aforementioned n (Next power of 2 from length of signal x). So, based on that, how these different vectors (equation 1 and final equation) could be the same? If you can see, the vectors are different since the former has n points and the later has NFFT/2 points! In fact, the factor (fs/n) is different from fs/2.

Upvotes: 2

Views: 1727

Answers (2)

PZwan
PZwan

Reputation: 101

The confusion is perhaps arising from the fact that the two examples which you have referenced are plotting results of the fft differently. Please refer to the code below for the references made in this explanation.

In the first example, the plot is of the power spectrum (periodogram) over the frequency range. Note, in the first plot, that the periodogram is not centered at 0, meaning that the frequency range appears to be twice that of the Nyquist sampling frequency. As mentioned in the mathworks link, it is common practice to center the periodogram at 0 to avoid this confusion (figure 2).

For the second example, taking the same parameters, the original plot is of amplitude of the fourier spectrum with a different normalization than in the first example (figure 3). Using the syntax of Matlab's full frequency ordering (as commented in the code), it is trivial to convert this seemingly different fft result to that of example 1; the identical result of the 0-centered periodogram is replicated in figure 4.

Thus, to answer your question specifically, the frequency ranges in both cases are the same, with the maximum frequency equal to the Nyquist sampling frequency as in:

f = fs/2*linspace(0,1,NFFT/2+1);

The key to understanding how the dfft works (also in Matlab) is to understand that you are simply performing a projection of your discrete data set into fourier space where what is returned by the fft() function in matlab are the coefficients of the expansion for each frequency component and the order of the coefficients is given (in Matlab as in example 2) by:

f = [f(1:end-1) -fliplr(f(1,2:end))];

See the Wikipedia page on the DFT for additional details: https://en.wikipedia.org/wiki/Discrete_Fourier_transform

It might also be helpful for you to take the fft omitting the length as a power of 2 parameter as

y = fft(x).

In this case, you would see only a few non-zero components in y corresponding to the exact coefficients of your input signal. The mathworks page claims the following as a motivation for using or not using this length:

"Using a power of two for the transform length optimizes the FFT algorithm, though in practice there is usually little difference in execution time from using n = m."

%% First example:
% http://www.mathworks.com/help/matlab/math/fast-fourier-transform-fft.html

fs = 10;                                % Sample frequency (Hz)
t = 0:1/fs:10-1/fs;                      % 10 sec sample
x = (1.3)*sin(2*pi*15*t) ...             % 15 Hz component
  + (1.7)*sin(2*pi*40*(t-2));            % 40 Hz component 
% Removed the noise

m = length(x);          % Window length
n = pow2(nextpow2(m));  % Transform length
y = fft(x,n);           % DFT
f = (0:n-1)*(fs/n);     % Frequency range
power = y.*conj(y)/n;   % Power of the DFT

subplot(2,2,1)
plot(f,power,'-o')
xlabel('Frequency (Hz)')
ylabel('Power')
title('{\bf Periodogram}')

y0 = fftshift(y);          % Rearrange y values
f0 = (-n/2:n/2-1)*(fs/n);  % 0-centered frequency range
power0 = y0.*conj(y0)/n;   % 0-centered power

subplot(2,2,2)
plot(f0,power0,'-o')
% plot(f0,sqrt_power0,'-o')
xlabel('Frequency (Hz)')
ylabel('Power')
title('{\bf 0-Centered Periodogram} Ex. 1')

%% Second example:
% http://stackoverflow.com/questions/10758315/understanding-matlab-fft-example

% Let's redefine the parameters for consistency between the two examples

Fs = fs;                      % Sampling frequency
% T = 1/Fs;                   % Sample time (not required)
L = m;                        % Length of signal
% t = (0:L-1)*T;              % Time vector (as above)
% % Sum of a 3 Hz sinusoid and a 2 Hz sinusoid
% x = 0.7*sin(2*pi*3*t) + sin(2*pi*2*t); %(as above)

NFFT = 2^nextpow2(L); % Next power of 2 from length of y
                      % NFFT == n (from above)
Y = fft(x,NFFT)/L;
f = Fs/2*linspace(0,1,NFFT/2+1);

% Plot single-sided amplitude spectrum.
subplot(2,2,3)
plot(f,2*abs(Y(1:NFFT/2+1)),'-o') 
title('Single-Sided Amplitude Spectrum of y(t)')
xlabel('Frequency (Hz)')
ylabel('|Y(f)|')


% Get the 0-Centered Periodogram using the parameters of the second example
f = [f(1:end-1) -fliplr(f(1,2:end))]; % This is the frequency ordering used
                                      % by the full fft in Matlab

power = (Y*L).*conj(Y*L)/NFFT;

% Rearrange for nicer plot
ToPlot = [f; power]; [~,ind] = sort(f); 
ToPlot = ToPlot(:,ind);

subplot(2,2,4)
plot(ToPlot(1,:),ToPlot(2,:),'-o')
xlabel('Frequency (Hz)')
ylabel('Power')
title('{\bf 0-Centered Periodogram} Ex. 2')

Upvotes: 1

SleuthEye
SleuthEye

Reputation: 14579

So, based on that, how these different vectors (equation 1 and final equation) could be the same?

The example in the documentation from Mathworks plots the entire n-point output of the FFT. This covers the frequencies from 0 to nearly fs (exactly (n-1)/n * fs). They then make the following observation (valid for real inputs to the FFT):

The first half of the frequency range (from 0 to the Nyquist frequency fs/2) is sufficient to identify the component frequencies in the data, since the second half is just a reflection of the first half.

The other post you refer to just chooses to not show that redundant second half. It then uses half the number of points which also cover half the frequency range.

In fact, the factor (fs/n) is different from fs/2.

Perhaps the easiest way to make sense of it is to compare the output of the two expressions for some small value of n, says n=8 and setting fs=1 (since fs multiplies both expressions). On the one hand the output of the first expression [0:n-1]*(fs/n) would be:

0.000  0.125  0.250  0.500  0.625  0.750  0.875

whereas the output of fs/2*linspace(0,1,n/2+1) would be:

0.000  0.125  0.250  0.500

As you can see the set of frequencies are exactly the same up to Nyquist frequency fs/2.

Upvotes: 2

Related Questions