目录
循环卷积原理
设x(n)和h(n)是两个长度分别为N和M的有限长序列,它们的L点循环卷积y(n)定义为:
其中
所以h((n-m))L可以看做将序列h(n)以L为周期进行周期延拓得到周期序列h((n)L,再将h((n))L右移m位得到h((n-m))L,即:
RL(n)为矩形窗函数。由公式(3)可进一步得到:
我们知道有限长线性卷积公式:
由此我们可以得知(4)式中:
进而得到:
我们可以看出公式(7)是循环卷积另一种表示方式,而且它诠释了循环卷积与线性卷积的关系,即线性卷积以yl(n)以L为周期进行周期延拓得到周期序列后求和再乘以L点长度的矩形窗函数得到周期序列的主值序列(第一个周期的序列)。
循环卷积与线性卷积的联系
根据第一部分的公式推导我们已经知道了循环卷积和线性卷积之间的联系,其实它们之间的关系可总结为以下三个要点:
(1)当L<N+M-1,循环卷积是线性卷积长度为L 的时域混叠,一般要求L>=max(N,M),N+M-1是线性卷积结果新序列的长度。
(2)当L=N+M-1,循环卷积就是线性卷积。
(3)当L>N+M-1,循环卷积是线性卷积结果末尾补L-(N+M-1)个零。
对位相加法计算循环卷积
我们知道图解法是最为普遍的方法来求解线性卷积,当然它对循环卷积也依然适用,此处不予详细说明,本节我们介绍一种新的计算循环卷积的方法叫做对位相加法。基本原理可以概括为先依照对位相乘法计算出线性卷积,然后根据循环区间修正结果,若循环区间L为2,则把2之后的序列搬到前面,两序列相加求和即得最终结果。举个例子,依然使用序列x(n)=[1 2 3]和h(n)=[1 1 1 1],我们知道它的线性卷积结果为[1 3 6 6 5 3],下图介绍不同点数的循环卷积对位相加法如何操作:
我们看到2点循环卷积的结果为[12 12],以4点为循环区间:
依次类推,我们知道以6点为循环区间时截余线就在元素3之后,由此我们知道[1 3 6 6 5 3]就是循环卷积的结果,以8点为循环区间:
我们可以看到此时只有N位保留序列,并无截余序列。此时需要在N位线性卷积序列后补上L-N个零。 上述结果都可以在Matlab里面使用cconv函数验证正确性。
Matlab 实操
源代码
%% =========================================================================================================
% 程序说明:本程序在依照对位相乘法而自定义线性卷积函数的基础上依据循环卷积的原理和对位相加法自定义循环卷积函数,替代Matlab自带cconv函数和y=ifft(fft(x).*fft(h)),供大家参考
% 程序名称:Cicular Convolution 循环或圆周卷积
% 作者: hill5678
% 当前版本:1.0
%% =========================================================================================================
clear all;
close all;
clc;
%% ==================================================主函数部分==============================================
X=input('enter a arbitrary discrete-time sequence here:');
H=input('enter a arbitrary discrete-time sequence here:');
L=input('enter the desired circular convolution data points here:');
Y=circular_convolution(X,H,L);
display(Y);
%% ================================================定义循环卷积函数============================================
function y=circular_convolution(x,h,L)
%L为计算循环卷积的数据点数或者为输出序列的长度
n=length(x);m=length(h);% 输入离散时间序列的长度
y1=[];y2=[];y3=[];y4=[];y5=[];y6=[];y7=[];y8=[];y9=[];
a=m;
N=n+m-1;% 卷积后新序列的长度
b=N;
M=N-n;% 矩阵形成并移位后每行需要补零的个数
for i1=0:a-2
for i=0:m-1
for k=0:n-1
y1(i+1,k+1)=h(i+1)*x(k+1);% 按照对位相乘法将两个序列左端对齐,依次对位相乘
end
y2=y1;% 将结果矩阵赋给y2
end
y3=[y2,zeros(m,M)];%将y2后面加入零矩阵
y4=circshift(y3(i1+2,:),i1+1,2);% 循环移位函数,将y4从第二行开始向右按行移位。第二行移一位,第三行移两位,按此规律依次类推
y5=[y5;y4];
end
y6=[y3(1,:);y5];% y3的第一行不变
y7=sum(y6);% 将矩阵y6按列相加得到卷积结果
disp(y7);
figure(1)
stem(y7,'fill')
title('linear convolution result:sequence y7(n)');
grid on;
%%此处开始定义循环卷积函数
y10=[];y11=[];y=[];
J=ceil(N/L);%对位相加后所形成矩阵的行数
for i2=L:L:(J-1)*L%矩阵从第2行开始基于第一行元素即线性卷积结果一共做(J-1)*L次向左循环移位
z=zeros(1,i2);
y8=circshift(y7,-(i2),2);
y8(N-i2+1:N)=z;
y9=[y9;y8];
end
y10=[y7(1,:);y9];
for i3=0:L-1
%%当L<N,循环卷积是线性卷积长度为L的时域混叠;当L=N,循环卷积就是线性卷积;当L>N,循环卷积是线性卷积末尾补上L-N个零
if L<N
y11=[y11,sum(y10(:,i3+1))];
y=y11;
elseif L==N
y=y7;
else
y=[y7,zeros(1,L-N)];
end
end
disp(y)
figure(2)
stem(y,'fill')
title('circular convolution result:sequence y(n)');
grid on;
end
此代码前一段还是产生线性卷积结果,故在仿真结果里面不再显示。
仿真结果
使用序列x=[1 2 3]和h=[1 1 1 1],求4点循环卷积,Matlab命令窗口:
Matlab仿真图:
参考文献