1. 程式人生 > >MATLAB中通過fft計算訊號頻譜的問題

MATLAB中通過fft計算訊號頻譜的問題

之前一直在做聲音相關的一個專案,其中用到了很多訊號頻譜的問題,包括fft點數的選取、fft之後畫圖橫縱座標的問題、fftshift的用法等等。前面因為忙,也沒有仔細研究,現在將問題總結如下:

1.fft點數的選取。

眾所周知,fft是快速傅立葉變換,當訊號為2的整數冪時效率最高(當然還有基為3,4的fft,用的不多此處不表,下面提到的fft均為基是2的fft)。
而現實生活中的訊號往往並不是2的整數冪,那麼這時候應該怎麼辦呢?
個人認為解決方案有兩種:
(1)採用離散傅立葉變換(DFT)的定義來做,這樣就能保證對任意點數都能處理,但缺點就是計算量大,速度太慢。因此當資料量小的時候,可以這麼用。
(2)在原始訊號後面補零,使其長度變成2的整數冪。這是目前最常見的做法,matlab裡面的fft函式就是這樣做的。好處是有很多現成的fft演算法,當你訊號長度2的整數冪時,速度會很快、很方便,缺點則是精度上有點差距。

2.fft之後畫圖橫縱座標的問題以及fftshift的用法。

之前用matlab中的fft,只是用用函式,並未對其進行全面瞭解,但最近在畫頻譜圖的時候發現橫縱座標的意義根本不懂,fftshift又是怎麼用呢?下面通過一段程式碼和實驗說明。

Fs = 5000; % Sampling frequency
T = 1/Fs; % Sample time
N = 1000; % Length of signal
t = (0:N-1)/Fs; % Time vector

x = 0.5*sin(2*pi*50*t) + sin(2*pi*120*t);
X1=abs(fft(x))

xx1=abs(fft(x));
xx2=fftshift(abs(fft(x)));

figure
subplot(4,1,1)
plot(x);
title(‘x = 0.5*sin(2*pi*50*t) + sin(2*pi*120*t)’);
subplot(4,1,2)
plot(xx1);
title(‘abs(fft(x))’);
subplot(4,1,3)
plot(xx2);
title(‘fftshift(abs(fft(x)))’);
subplot(4,1,4)
plot((1:N/2-1)*Fs/N,X1(1:N/2-1))*2/N;;
title(‘plot((1:N/2-1) * Fs/N, X1(1:N/2-1) * 2/N)結果圖’);
這裡寫圖片描述

可以看出,
(1)經過matlab裡abs(fft(x))的結果即為訊號x的頻譜,而加上fftshift則是將訊號關於0頻進行對稱。
(2)abs(fft(x))取前半部分,fftshift(abs(fft(x)))取後半部分,則為正確的頻譜圖(但橫縱座標不對)。
(3)最終正確的頻譜圖為第四個子圖所示,橫縱座標均需要特殊處理:
縱座標: abs(fft(x))* 2 / N才為真實頻譜幅值。
橫座標: plot((1:N/2-1) * Fs/N, X1(1:N/2-1) ),只取一半,並且要乘以頻率解析度Fs/N才為真實的頻率值。