MATLAB 自編代碼實現DFS和IDFS,以及對DFT補零和週期重複的分析

基本公式

X~(k)=DFS[x~(n)]=n=0N1x~(n)ej2πNkn\tilde{X}(k)=DFS[\tilde{x}(n)]=\sum_{n=0}^{N-1} \tilde{x}(n) e^{-j \frac{2 \pi}{N} k n}

x~(n)=IDFS[X~(n)]=1Nk=0N1X~(k)ej2πNkn\tilde{x}(n)=IDFS[\tilde{X}(n)]=\frac{1}{N} \sum_{k=0}^{N-1} \tilde{X}(k) e^{j \frac{2 \pi}{N} k n}

X(k)=DFT[x(n)]=n=0N1x(n)ej2πNkn,k=0,1,...,N1X(k)=DFT[x(n)]=\sum_{n=0}^{N-1} x(n) e^{-j \frac{2 \pi}{N} k n} ,\quad k=0,1,...,N-1

x(n)=IDFT[x(n)]=1Nk=0N1X(k)ej2πNkn,n=0,1,,N1x(n)=IDFT[x(n)]=\frac{1}{N} \sum_{k=0}^{N-1} X(k) e^{j \frac{2 \pi}{N} k n}, \quad n=0,1, \ldots, N-1

其中x~(n)\tilde{x}(n)x(n)x(n)的週期延拓,x(n)x(n)x~(n)\tilde{x}(n)的主值序列,X~(k)\tilde{X}(k)X(k)X(k)的關係也是如此。因而DFS和DFT有着密切的聯繫,從MATLAB的角度來說,實現了DFS與實現DFT是基本等價的。

DFS

function [Xk] = dfs( xn, N )
%DFS 計算離散週期序列的傅里葉級數(其實也是DFT)
%   輸入:時域序列xn,變換點數N
%   輸出:頻域序列Xk
%   說明:暫不支持N<length(xn)的DFS運算
    n = 0:1:N-1;
    k = 0:1:N-1;
    if N > length(xn)
        xn = [xn, zeros(1, N-length(xn))];
    elseif N < length(xn)
        fprintf('ERROR! N should not be less than length of x(n)\n');
        Xk = zeros(1, length(xn));
        return
    end
    WN = exp(-1j*2*pi/N);
    nk = n'*k;
    Xk = xn * power(WN, nk);
end

IDFS

function [xn] = idfs(Xk, N)
%IDFS 計算離散傅里葉級數逆變換
%   輸入:頻域序列Xk,變換點數N
%   輸出:時域主值序列xn
%   說明:暫不支持N<length(Xk)的IDFS運算
    n = 0:1:N-1;
    k = 0:1:N-1;
    if N > length(Xk)
        Xk = [Xk, zeros(1, N-length(Xk))];
    elseif N < length(Xk)
        fprintf('ERROR! N should not be less than length of X(k)\n');
        xn = zeros(1, length(Xk));
        return
    end
    WN = exp(-1j*2*pi/N);
    nk = k'*n;					% 注意這裏與DFS應有區別
    xn = Xk* power(WN, -nk)/N;
end

使用示例

clear all; close all;
% 已知週期序列的主值x(n)=[7,6,5,4,3,2],求x(n)週期重複次數爲3次時的DFS和IDFS。
xn = [7,6,5,4,3,2];
xn3 = repmat(xn, 1, 3);
N = length(xn3);        % DFT點數

% ①畫出原信號序列的主值和週期序列的圖形;
subplot(2,3,1); stem(0:length(xn)-1, xn); title('原信號序列主值x(n)');
subplot(2,3,2); stem(0:length(xn3)-1, xn3); title('週期數爲3的序列x3(n)');

% ②畫出序列傅里葉變換對應的|X~(k)|和arg[X~(k)],的圖形。
Xk = dfs(xn3, N);
subplot(2,3,4); stem(0:N-1, abs(Xk)); title('幅頻特性|X^~(k)|');
subplot(2,3,5); stem(0:N-1, angle(Xk)); title('相頻特性arg[X^~(k)]');
xn_ = idfs(Xk, N);
subplot(2,3,3); stem(0:N-1, abs(xn_)); title('週期數爲3的序列依次經過DFT和IDFT');

運行結果如下:
在這裏插入圖片描述

探討“補零”和“增加週期重複數”的區別

我們知道在傅里葉變換的世界中,在變換前後,
\quad\quad\quad\quad\quad\quad\quad\quad週期<—>離散,非週期<—>連續
因此需要注意,DFT運算的補零與增加週期重複數是不同的,時域序列的補零對應頻域頻譜的插值,而時域的週期重複數增大對應頻域頻譜將顯示出更加明顯的離散特徵。兩種操作都可以使頻譜變得密集、但並不是都使頻譜變得趨於連續;補零可以使有限長序列的頻譜精度(頻率分辨率)提升(即補零等效爲延長觀測時間),而增加週期重複數可以使週期序列的頻譜精度提升,因而在使用時需要視情況而選擇合適的提升精度方法,下面舉一個例子。

clear all; close all;
xn = [1,1,1,1,1];
N = 100;            % DFT點數;
n = 0:N-1;
T = 15;				% 主值序列長度;
xn_ = [xn, zeros(1,T-length(xn))];

subplot(3,2,1); stem(0:length(xn_)-1, xn_); title('x(n)原始序列');
subplot(3,2,2); stem(0:length(xn_)-1, xn_); title('x(n)原始序列');

% 如果已知xn是以T爲週期的週期序列,那麼其頻譜如下:
xn_cycle = repmat(xn_, 1, 5);    % 矩陣重複函數
Xk_cycle = dfs(xn_cycle, length(xn_cycle));
subplot(3,2,3); stem(0:length(Xk_cycle)-1, abs(Xk_cycle)); title('週期序列—週期重複數爲5');
xn_cycle = repmat(xn_, 1, 20);
Xk_cycle = dfs(xn_cycle, length(xn_cycle));
subplot(3,2,5); stem(0:length(Xk_cycle)-1, abs(Xk_cycle)); title('週期序列—週期重複數爲20');

% 如果已知xn是長度爲T的有限長序列,則其頻譜如下:
xn_zeros = [xn_, zeros(1, (5-1)*T)];
Xk_zeros = dfs(xn_zeros, length(xn_zeros));
subplot(3,2,4); stem(0:length(Xk_zeros)-1, abs(Xk_zeros)); title('有限長序列—補零倍數爲5-1');
xn_zeros = [xn_, zeros(1, (20-1)*T)];
Xk_zeros = dfs(xn_zeros, length(xn_zeros));
subplot(3,2,6); stem(0:length(Xk_zeros)-1, abs(Xk_zeros)); title('有限長序列—補零倍數爲20-1');

得到結果如下:
在這裏插入圖片描述可以看出,R5(n)R_5(n)有限長序列本身的頻譜可以由補零提升精度(譜分辨率),得到的頻譜也愈加接近通過DTFT得到的連續頻譜(如下圖所示),這將有利於單頻信號的頻率估計等應用;而R5(n)R_5(n)以15位週期進行週期延拓,得到的是更加標準的離散頻譜,這種精度的提升有利於辨別出週期信號中蘊含的所有的頻率分量,保證沒有缺漏。
在這裏插入圖片描述
本文繫個人理解,如有不當之處歡迎指出。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章