Matlab 計算 FFT 的方法及幅值問題

歡迎轉載,但請一定要給出原文鏈接,標註出處,支持原創! 謝謝~
https://blog.csdn.net/qq_29225913/article/details/105467006

1、Matlab FFT 函數介紹

  FFT (Fast Fourier Transform) 中文爲快速傅里葉變換,作用是將離散的時域信號變換到頻域,在一般情況下,時域信號都比較難看出特徵,但是轉換成頻域後,就比較容易看出來,因此,很多信號分析都會採用FFT變換,然後對信號進行頻譜分析。
  Matlab 中,FFT 函數的語法如下:
  Y = fft(X)
  Y = fft(X,n)
  Y = fft(X,n,dim)
推薦直接在命令行使用 help fft看到更加詳細的描述信息與例程,這裏主要記錄一下用法以及注意事項。
  N個採樣點,經過FFT之後,就可以得到N個點的FFT結果。爲了方便進行FFT運算,通常N取2的整數次方,但是這裏直接取讀取出來的樣本數作爲N。

  • FFT 計算公式如下:
    在這裏插入圖片描述
  • Xk 長度與 N 相同。
  • 根據奈科斯特定律,只有 f=fs/2 範圍內的信號纔是被採樣到的有效信號,因此得到的頻譜肯定是關於 N/2 對稱的(就是隻看前一半的波形就好)。
  • 第k點的實際頻率的計算爲 f(k) = k * (fs / n) — — (橫軸的頻率範圍爲 :f = n * fs / N;)
  • X[0] 爲直流分量 ,幅值 = 模值(X[0]) / N
  • X[k] 爲個點的頻率分量(除X[0]外),幅值 = 模值(X[k]) / (N / 2)

2、Matlab FFT 程序

  • 先擺上代碼,運行一下看效果。

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %   功能:FFT 運用方法(例程)                  % 
    %   作者:Mr-Ma Technology(馬健維)             %
    %   時間:2020.04.12                           %
    %   轉載請註明出處                             %
    %   https://blog.csdn.net/qq_29225913/article/details/105467006                
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    
    %% 描述
    % 使用 Matlab 的 FFT,有一個注意事項,採樣數量是採樣頻率的整數倍,且最好是 2 的 n 次冪。
    % 否則會導致採樣分辨率匹配不上,表現爲在對應的頻點處沒有采樣到,出現偏移,因此會導致
    % 描繪圖像時,發現所需要的頻點處顯示出來的幅度值小於預期的值。
    % 可以通過修改參數定義的值得定義來直觀的看FFT的效果
    
    %% 參數定義
        A1 = 2;             % 信號1 幅值(A)
        f1 = 11;            % 信號1 頻率(f)
        A2 = 0.5;           % 信號2 幅值(A)
        f2 = 29;            % 信號2 頻率(f)
        A3 = 1;             % 信號3 幅值(A)
        f3 = 51;            % 信號3 頻率(f)
        Dc = 0;             % 直流分量
        Noise = 0;          % 噪聲大小
        fs = 128;           % 採樣頻率 (fs)
        N = 1024;           % 採樣點數(樣本數量)
    
     %% 運算(生成時域曲線、FFT計算)
        n = 0:N-1;          % 等差生成序列,
        t = n / fs;         % 時間序列,用於下式
        RA = rand(1,N);     % 隨機噪聲(0~1)
        RA = RA - mean(RA); % 減去噪聲均值(-0.5~0.5),去除噪聲中的直流分量。
        x = Dc + A1 * sin(2*pi*f1*t) + A2 * sin(2*pi*f2*t) + A3 * sin(2*pi*f3*t)+ Noise * RA ; % 兩個正弦信號、直流分量、噪聲 相疊加    
       
        y = abs(fft(x,N));  % 對上式進行 N 點 FFT 計算 ,並取模值
        A = y * 2 / N;      % 模值轉換爲幅值 
        A(1) = A(1) / 2;    % 根據公式 ,X[0] 不用乘以 2 
        f = n * fs / N;     % 轉換爲頻率區間
        
    %% 繪圖
        subplot(2,1,1);
        plot(t,x);
        xlabel('時間/s');ylabel('振幅');
        title('時域曲線') 
        subplot(2,1,2);
        plot(f(1:N/2),A(1:N/2)); % 描繪圖像 
        xlabel('頻率/Hz');ylabel('振幅');
        title(['幅頻特性曲線 :Fs = ',num2str(fs),', N = ',num2str(N)]) 
    
  • 運行圖片:
    在這裏插入圖片描述

3、FFT 程序分析

  通過運行上面的代碼,可以得到與上圖一致的運行效果,該程序中,原函數是由 直流分量信號1信號2信號3噪聲分量 疊加而成的(上圖中暫時將直流分量與噪聲分量設置爲0),在實際工程使用中,將例程中生成的原函數替換成需要進行分析的序列就可以了。
  上面的圖片中,每一個信號的幅值就剛好等於所設置的振幅,此處有一個地方需要注意的就是,一般情況下,採樣點 N 都不固定,都是隨輸入的因素影響,例如對一首採樣率爲 44.1KHz 的歌來分析,讀取出來的數據長度 N 就不一定是 2 的n次方了,如果直接送入進行 FFT 計算,到 N 點結算數據,在FFT內由於使用蝶形運算,所以是需要 N 是 2 的 n 次方,因此會導致在 N 個採樣點後方補零, 可能在某些頻點出看到的賦值,會比預想值要小,這就是能量泄露。如果只需要考慮各頻譜值得比例(即只看頻率分佈情況),不考慮實際 FFT 後的幅值的話,可以直接傳入N進去,如果需要進行頻譜分析,就要要考慮實際的幅值對分析結果的影響,此處就可以選擇加窗,還有一種情況就是 N 足夠大,並且是均勻分佈,就可以考慮截取 N 的值,使得滿足 N 等於 2 的 n 次方。

3.1 fs 、N 對 FFT 圖像幅值的影響。

  上述程序中,fs = 128;N = 4096;(N 是 fs 的整數倍,且 N 是 2 的 n 次方),下面來分析下不同的 fs 與 N 對實際 FFT 結果的影響。

  • 1、 fs = 100,N = 100(這個情況下,信號 3 不滿足 fs ≥ 2f 的情況,因此信號 3 不會顯示出來)
    在這裏插入圖片描述
  • 2、 增大 N ,fs = 100,N = 150,由於補零了,所以存在能量泄漏,計算出來的幅值會變小。
    在這裏插入圖片描述
  • 3、 增大Fs,fs = 200,N=150,此時由於 N 與 fs 仍然是非整數倍關係,且樣本數量不足夠大,導致分辨率不足,使得不能夠將所有的頻率都能夠對應上,造成頻率泄漏,導致幅值變小。
    在這裏插入圖片描述
  • 4、 繼續加大 N ,直接擴大10倍,fs = 200,N = 1500,可以觀察到隨着樣本數量增加的時候,幅頻特性曲線會變窄,與實際的頻率越接近,即精度越高。但是由於 fs 與 N 仍然非整數倍關係,因此仍然會有上一點存在的問題。
    在這裏插入圖片描述
  • 5、 這一步,減少 N ,但是設置爲 fs 的整數倍(往上滑,與第1點對比),fs = 100, N = 200,可以看出,與第 1 點對比的時候,幅值依然是實際值,但是精度更高了(由於N 的數多了一倍)
    在這裏插入圖片描述
  • 6、 (對照組)擴大 N 爲 fs 的 2 倍(與第 3 、5 點對比)fs = 200,N= 400,因爲同樣 N 是 fs 的整數倍,幅值爲實際值。
    在這裏插入圖片描述
  • 7、 最後,設置 fs、N 均爲 2 的 n 次方,這裏的 fs 根據最高信號頻率來選擇即可,比如信號 3 是頻率最高的信號(51Hz),因此 fs 選擇128,N儘量的大,因此 N 選擇 4096,此時時域信號中的頻率信息,都能夠很好的表示出來。
    在這裏插入圖片描述

3.2 直流分量、噪聲分量對 FFT 圖像的影響

在這一節考慮將直流分量,與噪聲信號加入,通過改變以下兩項來加入。其他值使用默認的參數(fs = 128,N = 1024)
在這裏插入圖片描述

  • 設置直流分量爲1,可以看到 FFT 圖像 x = 0 處有一個直流分量。(實際使用中,直流分量對信號的分析用處不大,所以一般都會將此值設爲0,或者將 用 x = x - mean(x)的方法,將直流分量過濾掉)
    在這裏插入圖片描述按照直流分量的計算公式,需要在程序裏對該值進行修改(幅值 = 模值 / N ; 當 x = 0)
    在這裏插入圖片描述
  • 修改噪聲分量的值 爲10,(即疊加一個 幅度爲 ±5 的噪聲信號),使用噪聲前,需要對噪聲進行消除直流處理。
    在這裏插入圖片描述
    可以看出來,在時域的圖像上,已經看不清信號的內容了,但是在頻域上,仍然能夠分辨的出有3個主要信號,並且在採樣範圍內,均勻分佈着噪聲信號。後面可以通過設計帶通濾波器,將3個有用信號的頻段提取出來,其他頻段的信號進行過濾,在利用 IFFT 還原出降噪後的波形。
    在這裏插入圖片描述

3.3 總結

  • 在能夠自己選定 fs 的情況下,儘量選擇 fs 爲 2 的 n 次方,且 N 取 fs 的倍數,這樣可以在幅頻特性曲線上,得到與實際相符的幅度值。
  • fs 固定的情況下,(如音頻文件,44.1K/48K/…),不能修改fs,則選擇 N 爲 fs 的整數倍,通常這種情況下 N 的數量都會足夠大,因此 N 向前截取(即N值 ≤ 實際採樣點)默認信息是隨機分佈,最後的一節信號不會對整體的頻譜產生較大的影響。(若要考慮全部採樣點,則可忽略對實際幅值的影響,實際幅值不一定需要)
  • 疊加噪聲的分析,可以轉換到頻域上進行處理。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章