Matlab,FFT频率范围差异还是相同?

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

我正在尝试了解matlab中FFT的工作原理,尤其是如何定义频率范围以对其进行绘制。 碰巧,我已经从matlab帮助链接和此处的其他讨论中阅读了内容,我认为(猜测)对此感到困惑。
在matlab链接中:
http://es.mathworks.com/help/matlab/math/fast-fourier-transform-fft.html
他们将频率范围定义为:

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

其中nfs为:

1
2
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

但是,另一方面,在上一篇了解Matlab FFT示例中
(基于Matlab的先前版本),结果频率范围定义为:

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

NFFT作为前述的n(从信号x的长度开始的下一个2幂)。
那么,基于此,这些不同的向量(方程式1和最终方程式)如何相同?
如您所见,向量是不同的,因为前者具有n点,而后者具有NFFT/2点! 实际上,因子(fs/n)fs/2不同。


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

Mathworks文档中的示例绘制了FFT的整个n点输出。这涵盖了从0到几乎fs(恰好是(n-1)/n * fs)的频率。然后,他们进行以下观察(对于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.

您引用的另一篇文章只是选择不显示多余的后半部分。然后,它使用的点数的一半也覆盖了一半的频率范围。

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

n=8说,也许最容易理解的方法是比较两个表达式的输出和一个较小的n值并设置fs=1(因为fs将两个表达式相乘)。一方面,第一个表达式[0:n-1]*(fs/n)的输出为:

1
0.000  0.125  0.250  0.500  0.625  0.750  0.875

fs/2*linspace(0,1,n/2+1)的输出将是:

1
0.000  0.125  0.250  0.500

如您所见,频率集与奈奎斯特频率fs/2完全相同。


您所引用的两个示例在绘制fft的结果时有所不同,这可能是造成混淆的原因。请参阅下面的代码以获取此说明中的参考。

在第一个示例中,该图是整个频率范围内的功率谱(周期图)。请注意,在第一个图中,周期图并未以0为中心,这意味着该频率范围似乎是奈奎斯特采样频率的两倍。如mathworks链接中所述,通常的做法是将周期图的中心设置为0,以避免这种混淆(图2)。

对于第二个示例,采用相同的参数,原始图的傅立叶频谱幅度与第一个示例中的归一化不同(图3)。使用Matlab的全频率排序语法(如代码中所述),将这种看似不同的fft结果转换为示例1的结果并不容易。以0为中心的周期图的相同结果如图4所示。

因此,为具体回答您的问题,两种情况下的频率范围都相同,最大频率等于奈奎斯特采样频率,如下所示:

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

理解dfft的工作原理(也是在Matlab中)的关键是要了解,您只是将离散数据集投影到傅立叶空间中,而matlab中的fft()函数返回的是展开系数。每个频率分量和系数的阶数通过以下方式给出(在Matlab中,如示例2所示):

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

有关其他详细信息,请参见DFT上的Wikipedia页面:
https://zh.wikipedia.org/wiki/Discrete_Fourier_transform

将fft省略长度作为2参数的幂也可能对您有所帮助

1
y = fft(x).

在这种情况下,您将仅在y中看到一些与输入信号的确切系数相对应的非零分量。 mathworks页面声称以下是使用或不使用此长度的动机:

"对变换长度使用2的幂可以优化FFT算法,尽管在实践中,使用n = m通常执行时间几乎没有差异。"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
%% 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')