我试图了解matlab中的FFT如何工作,特别是如何定义绘制它的频率范围。碰巧我从matlab帮助链接和其他讨论中读到了这些,我认为(猜测)我对此感到困惑。 在matlab链接中: http://es.mathworks.com/help/matlab/math/fast-fourier-transform-fft.html 他们定义了这样一个频率范围:
f = (0:n-1)*(fs/n)
以n
和fs
为:
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
但另一方面,在上一篇文章中Understanding Matlab FFT example (基于以前版本的matlab),得到的频率范围定义为:
f = fs/2*linspace(0,1,NFFT/2+1);
NFFT
为上述n
(信号长度x
的下一次幂为2)。
那么,基于此,这些不同的向量(方程1和最终方程)如何相同?
如果你可以看到,向量是不同的,因为前者有n
个点而后者有NFFT/2
个点!事实上,因素(fs/n)
与fs/2
不同。
答案 0 :(得分:2)
那么,基于此,这些不同的向量(方程1和最终方程)如何相同?
example in the documentation from Mathworks绘制FFT的整个n
点输出。这涵盖了从0到接近fs
(确切地为(n-1)/n * fs
)的频率。然后他们进行以下观察(对FFT的实际输入有效):
频率范围的前半部分(从0到奈奎斯特频率
fs/2
)足以识别数据中的分量频率,因为后半部分只是上半部分的反映。
other post you refer to只是选择不显示冗余的下半场。然后它使用的点数的一半也覆盖了频率范围的一半。
事实上,因子(fs / n)与fs / 2不同。
理解它的最简单方法可能是将两个表达式的输出与n
的一些小值进行比较,比较n=8
并设置fs=1
(因为{{1}两个表达式相乘)。一方面,第一个表达式fs
的输出将是:
[0:n-1]*(fs/n)
而0.000 0.125 0.250 0.500 0.625 0.750 0.875
的输出为:
fs/2*linspace(0,1,n/2+1)
正如您所看到的那样,在奈奎斯特频率0.000 0.125 0.250 0.500
之前,频率组完全相同。
答案 1 :(得分:1)
这种混淆可能是因为你引用的两个例子正在以不同的方式绘制fft的结果。有关此说明中的参考,请参阅以下代码。
在第一个示例中,绘图是频率范围内的功率谱(周期图)。请注意,在第一个图中,周期图不以0为中心,这意味着频率范围似乎是奈奎斯特采样频率的两倍。正如数学工作链接中所提到的,通常的做法是将周期图居中,以避免这种混淆(图2)。
对于第二个例子,采用相同的参数,原始图是具有与第一个例子中不同的归一化的傅里叶谱的幅度(图3)。使用Matlab的全频率排序语法(如代码中所述),将这个看似不同的fft结果转换为示例1的结果是微不足道的。 0中心周期图的相同结果在图4中重复。
因此,要具体回答您的问题,两种情况下的频率范围都是相同的,最大频率等于奈奎斯特采样频率,如下所示:
f = fs/2*linspace(0,1,NFFT/2+1);
理解dfft如何工作的关键(也在Matlab中)是要理解你只是将离散数据集投影到傅立叶空间中,其中matlab中fft()函数返回的是系数。通过以下公式给出每个频率分量的扩展和系数的阶数(在Matlab中,如例2):
f = [f(1:end-1) -fliplr(f(1,2:end))];
有关其他详细信息,请参阅DFT上的Wikipedia页面: https://en.wikipedia.org/wiki/Discrete_Fourier_transform
将fft省略为2参数的幂可能也有帮助
y = fft(x).
在这种情况下,您会看到y中只有少数非零分量对应于输入信号的精确系数。 mathworks页面声称以下是使用或不使用此长度的动机:
"使用2的幂来获得变换长度可以优化FFT算法,但实际上,与使用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')