计算谱Matlab的方法

时间:2014-01-21 10:45:47

标签: matlab fft time-series

在Matlab中计算时间序列的频谱时我有一个问题。我已经阅读了有关'fft'功能的文件。但是我已经看到了两种实现方式,并且都给了我不同的结果。我希望能得到一些关于这种差异的答案:

第一种方法:

nPoints=length(timeSeries);    
Time specifications:
Fs = 1; % samples per second
Fs = 50;
freq = 0:nPoints-1; %Numerators of frequency series
freq = freq.*Fs./nPoints;
% Fourier Transform:
X = fft(timeSeries)/nPoints; % normalize the data 
% find find nuquist frequency
cutOff = ceil(nPoints./2);
% take only the first half of the spectrum
X = abs(X(1:cutOff));
% Frequency specifications:
freq = freq(1:cutOff);
%Plot spectrum
semilogy(handles.plotLoadSeries,freq,X);

enter image description here

第二种方法:

NFFT = 2^nextpow2(nPoints); % Next power of 2 from length of y
Y = fft(timeSeries,NFFT)/nPoints;
f = 1/2*linspace(0,1,NFFT/2+1);
% % Plot single-sided amplitude spectrum.
% plot(handles.plotLoadSeries, f,2*abs(Y(1:NFFT/2+1)))     
semilogy(handles.plotLoadSeries,f,2*abs(Y(1:NFFT/2+1)));

enter image description here

我认为没有必要在Matlab中的'fft'函数中使用'nextpow'函数。最后,哪个好?

感谢

1 个答案:

答案 0 :(得分:4)

简答:您需要windowing进行频谱分析。

现在需要很长的答案...... 在第二种方法中,当输入向量的长度为2的幂时,您使用的是优化的FFT算法。让我们假设你的原始信号有一个无限长信号的401个样本(如下例所示); nextpow2()将为您提供NFFT = 512个样本。当您将较短的401样本信号馈送到fft()函数时,它会被隐式填零以匹配请求的512(NFFT)长度。但是(这里是棘手的部分):对信号进行零填充相当于将无限长信号乘以rectangular function,这是一种在频域转换为带sinc function的卷积的运算。这可能是半对数图底部噪声底限增加的原因。

避免噪音增加的一种方法是使用更平滑的window function代替默认的矩形信号,手动创建要输入fft()的512样本信号。窗口化意味着将信号乘以锥形对称的信号。关于选择良好的窗函数的文献很多,但通常精确的低旁瓣(低噪声增加)是Hamming function,在MATLAB中用hamming()实现。

这是一个说明问题的图(在频域和时域中):

Windowing and spectrum analysis

...以及生成此图的代码:

clear

% Create signal
fs = 40;           % sampling freq.
Ts = 1/fs;         % sampling period
t = 0:Ts:10;       % time vector
s = sin(2*pi*3*t); % original signal
N = length(s);

% FFT (length not power of 2)
S = abs(fft(s)/N);
freq = fs*(0:N-1)/N;

% FFT (length power of 2)
N2 = 2^nextpow2(N);
S2 = abs(fft(s, N2)/N2);
freq2 = fs*(0:N2-1)/N2;
t2 = (0:N2-1)*Ts;       % longer time vector
s2 = [s,zeros(1,N2-N)]; % signal that was implicitly created for this FFT

% FFT (windowing before FFT)
s3 = [s.*hamming(N).',zeros(1,N2-N)];
S3 = abs(fft(s3, N2)/N2);

% Frequency-domain plot
figure(1)
subplot(211)
cla
semilogy(freq,S);
hold on
semilogy(freq2,S2,'r');
semilogy(freq2,S3,'g');
xlabel('Frequency [Hz]')
ylabel('FFT')
grid on
legend( 'FFT[401]', 'FFT[512]', 'FFT[512] with windowing' )

% Time-domain plot
subplot(212)
cla
plot(s)
hold on
plot(s3,'g')
xlabel('Index')
ylabel('Amplitude')
grid on
legend( 'Original samples', 'Windowed samples' )