重叠保留法和重叠相加法,均适用于计算短序列h(n)和长序列x(n)的线性卷积结果,通过将长序列x(n)进行先分段再卷积,并使用FFT对分段卷积过程进行加速。
下面截图节选自《MATLAB数字信号处理85个实用案例精讲 入门到进阶 宋知用》P75-P78,并附上自己编写的matlab验证这两种长短序列线性卷积的代码以及运行结果。
1,重叠相加法
Matlab代码:
1. 首先将长序列x(n)按照长度M进行分段,并求出需要进行循环的次数block_num;
2. 将分段之后的结果xn_和短序列hn进行补零至长度为M+N-1,并通过FFT求出两个补零之后的序列的线性卷积结果,长度为L=M+N-1,并将结果在时间轴上进行偏移移动至指定位置,保存至yn2;
3. yn与yn2进行重叠相加,如上面示意图所示。
代码:
% 重叠相加法计算短序列与长序列的线性卷积
clc;clear;close all;
hn = [1, 2, 3];
xn = exp(1:0.3:3.3);
N = length(hn);
M = 5; % xn进行分段卷积时候的每一段段长
L = M + N -1;
block_num = floor(length(xn)/M);
xnn = [xn, zeros(1, (block_num+1)*M-length(xn))]; % 若xn不能整分成block_num段,则在其最后面补0,使其能整分为没段长度为M的小段
yn = zeros(1, M * (block_num+1)+N-1); % 保存每次每段卷积完成并叠加之后的结果序列
yn2 = zeros(1, M * (block_num+1)+N-1); % 暂存每两个小段的分段卷积结果,除了中间L个值外其他均为0,用来和之前的结果序列叠加
for i = 1:block_num+1
xn_ = xnn(((i-1) * M+1):((i-1)*M+M));
xn_ = [xn_, zeros(1, L-M)];
hn_ = [hn, zeros(1, L-N)];
yn_ = ifft(fft(xn_) .* fft(hn_));
yn2(((i-1) * M+1):((i-1)*M+L)) = yn_;
yn = yn + yn2;
yn2 = zeros(1, M * (block_num+1)+N-1);
end
yn = yn(1:length(xn)+length(hn)-1);
figure;
subplot(211);stem(conv(xn,hn));title("matlab conv函数结果")
subplot(212);stem(yn);title("重叠相加法结果")
结果:
2,重叠保留法
Matlab代码:
1. 首先将长序列x(n)进行前端补零,补N-1个,得到xnn,并对原序列xn按照长度M进行分段,并求出需要进行循环的次数block_num;
2. 将补零之后的xnn进行长度为L的截取得到长度为L的分段xn_,并将短序列hn进行补零,至长度为L=M+N-1,通过FFT求出分段xn_和补零至长度为L之后的序列hn_的线性卷积结果,长度为L=M+N-1,保存至yn_;
3. yn与yn_进行拼接,注意去掉前面N-1个点的值,如上面示意图所示。
代码:
% 重叠保留法计算短序列与长序列的线性卷积
clc;clear;close all;
hn = [7, 2, 3];
xn = exp((1:10)/3);
N = length(hn);
M = 5;
L = M + N -1;
xnn = [zeros(1, N-1), xn, zeros(1,M - mod(length(xn), M))]; % 前面补N-1个0,后面补0是为了使其能每段长度未M进行整段截取
block_num = floor(length(xn)/M);
yn = zeros(1, (block_num+1)*M);
block_num = length(xn)/M;
for i = 1:block_num+1
xn_ = xnn(((i-1)*M+1):((i-1)*M+L));
hn_ = [hn, zeros(1, L-N)];
yn_ = ifft(fft(xn_) .* fft(hn_));
yn(((i-1) * M+1):((i-1)*M+M)) = yn_(N:L);
end
yn = yn(1:length(xn)+length(hn)-1);
figure;
subplot(211);stem(conv(xn,hn));title("matlab conv函数结果")
subplot(212);stem(yn);title("重叠保留法结果")
结果: