基本公式
其中 是 的周期延拓, 是 的主值序列, 与 的关系也是如此。因而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');
运行结果如下:
探讨“补零”和“增加周期重复数”的区别
我们知道在傅里叶变换的世界中,在变换前后,
周期<—>离散,非周期<—>连续
因此需要注意,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');
得到结果如下:
可以看出,
有限长序列本身的频谱可以由补零提升精度(谱分辨率),得到的频谱也愈加接近通过DTFT得到的连续频谱(如下图所示),这将有利于单频信号的频率估计等应用;而
以15位周期进行周期延拓,得到的是更加标准的离散频谱,这种精度的提升有利于辨别出周期信号中蕴含的所有的频率分量,保证没有缺漏。
本文系个人理解,如有不当之处欢迎指出。