# 重叠-储存之折积法

{\displaystyle {\begin{aligned}y[n]=x[n]\star h[n]\ {\stackrel {\mathrm {def} }{=}}\ \sum _{m=-\infty }^{\infty }h[m]\cdot x[n-m]=\sum _{m=1}^{M}h[m]\cdot x[n-m]\end{aligned}}}

## 算法

${\displaystyle x_{k}[n]\ {\stackrel {\mathrm {def} }{=}}{\begin{cases}x[n+kL-M]&1\leq n\leq L+M-1\\0&{\textrm {otherwise}}.\end{cases}}}$
${\displaystyle y_{k}[n]\ {\stackrel {\mathrm {def} }{=}}\ x_{k}[n]\star h[n]\,}$

{\displaystyle {\begin{aligned}y[n]=\sum _{m=1}^{M}h[m]\cdot x[n-m]=\sum _{m=1}^{M}h[m]\cdot x_{k}[n+M-kL-m]&=x_{k}[n+M-kL]\star h[n]\\&{\stackrel {\mathrm {def} }{=}}\ y_{k}[n+M-kL].\end{aligned}}}

${\displaystyle x_{k,N}[n]\ {\stackrel {\mathrm {def} }{=}}\ \sum _{k=-\infty }^{\infty }x_{k}[n-kN],}$

${\displaystyle y_{k}[n]={\textrm {IFFT}}\left({\textrm {FFT}}\left(x_{k}[n]\right)\cdot {\textrm {FFT}}\left(h[n]\right)\right)}$

### 准程式码

   (Overlap-save algorithm for linear convolution)
//////// revised by fantastic ////////
N = length(x), M = length(h)
O = M – 1;	// overlap length must be M-1
L = M;	// >=1 is OK
P = O + L;
H = FFT(h, P);	// just calc once
idx = - (O - 1);	// starting index which is offset M-1 in matlab
while (idx <= N)
i1 = max(1, idx);	// must be >= 1
i2 = min(N, idx+P-1);	// must be <= N
yt = IFFT( FFT(x(i1:i2), P).*H, P );
y(idx:idx+P-M) = yt(M:P);	// discard first M-1 values and concatenate the remaining
idx = idx + L;
end
y = y(1:M+N-1);	// the first M+N-1 values are the convolution result


## 区块长度的选择

x[n] 的长度 N' h[n] 的长度 M 相差太大时（例如 M < log2N' ），直接折积（不透过圆周折积FFT ）反而最快。而当 N' M 差不多在同一个数量级时，不用分割，也就是只有一块长度 L = N' 的区块去做 FFT 即可。而当 N' M 大了不少，却没大太多时，区块长度 L 就需要选择。除了与 N' M 相关以外，也要考虑当两者相除有馀数时，剩下一小段的输入可能会造成浪费。