**重疊-儲存之摺積法** ( *Overlap-save method*, *Overlap-discard method* ) 是一種區塊摺積 ( block convolution, sectioned convolution )，可以有效的計算一個很長的信號 *x*[*n*] 和一個 FIR 濾波器 *h*[*n*] 的離散摺積。

{\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}}}
其中 *h*[*m*] 在 [1, *M*] 之外為零。

與重疊-相加之摺積法不同之處在於，**重疊-儲存之摺積法**所算出的輸出區塊並不重疊 (因此計算上少了將輸出區塊相加所需的加法)，而是每次用的輸入區塊有所重疊。因此實作時每次讀取輸入後需將和下一個輸入重疊的部分儲存起來，作為下一輸入區塊的開頭部份，因此稱為*重疊*-*儲存*之摺積法。另外重疊-儲存之摺積法也不需補零。

算法
--

概念上，這個做法是選用一個較短的適當長度 *L* 來切割 *y*[*n*] ，則因為 *h*[*n*] 是有限長度，因此在某一區塊內的 *y*[*n*] 也只被有限長的 *x*[*n*] 區塊（會比 *y*[*n*] 分割成的區塊長一點）所決定。因此只要選擇有影響的輸入區塊和 *h*[*n*] 摺積，再選擇結果中適當的部分即可得到正確的輸出區塊。

  

{\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 [kL+1,(k+1)L]} 內的 *n* ， 輸出 *y*[*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}}}
所以只需計算 *n* 在 {\displaystyle [kL+1,(k+1)L]} 中的 *y**k*[*n* + *M* - *kL*] ，亦即 *n* 在 {\displaystyle [M+1,L+M]} 的 *y**k*[*n*] 部份即可。因此每一段輸出區塊 *y**k*[*n*] 的前 *M*-1 點可丟棄（discard）。

  

儘管一時看不出切割成區塊的好處為何，但將 *x**k*[*n*] 做  {\displaystyle N\geq L+M-1\,}  的週期延伸，

{\displaystyle x\_{k,N}[n]\ {\stackrel {\mathrm {def} }{=}}\ \sum \_{k=-\infty }^{\infty }x\_{k}[n-kN],}
則  {\displaystyle (x\_{k,N})\star h\,}  和  {\displaystyle x\_{k}\star h\,}  這兩個摺積在 {\displaystyle [M+1,L+M]} 的部份相等。所以可以將線性摺積改以 {\displaystyle N\,} 點圓周摺積計算，結果的 {\displaystyle [M+1,L+M]} 部分作為輸出 *y*[*n*] 在 {\displaystyle [kL+1,(k+1)L]} 的部份。由於每段 *x**k*[*n*] 原本就有  {\displaystyle L+M-1\,}  長，所以選擇  {\displaystyle N=L+M-1\,}  的話輸入 *x*[*n*] 就不需補零。
改以圓周摺積計算後即可藉圓周摺積定理

{\displaystyle y\_{k}[n]={\textrm {IFFT}}\left({\textrm {FFT}}\left(x\_{k}[n]\right)\cdot {\textrm {FFT}}\left(h[n]\right)\right)}
轉換成三次 {\displaystyle N\,} 點快速傅立葉變換和 {\displaystyle N\,} 次乘法，使原本每段 *O*(*N*2) 的運算量減少至 *O*(*N* *logN*)，速度大幅增加。

### 準程式碼

```
   (*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* < log2*N'*  ），直接摺積（不透過圓周摺積和 FFT ）反而最快。而當 *N'*  和 *M* 差不多在同一個數量級時，不用分割，也就是只有一塊長度 *L* = *N'*  的區塊去做 FFT 即可。而當 *N'*  比 *M* 大了不少，卻沒大太多時，區塊長度 *L* 就需要選擇。除了與 *N'*  和 *M* 相關以外，也要考慮當兩者相除有餘數時，剩下一小段的輸入可能會造成浪費。

相關條目
----

* 離散摺積
* 圓周摺積
* 快速傅立葉變換
* 重疊-相加之摺積法

參考文獻
----

* Rabiner, Lawrence R.; Gold, Bernard.. Englewood Cliffs, N.J.: Prentice-Hall. 1975: pp 65–67. ISBN 0-13-914101-4.  引文格式1维护：冗余文本 (link)
* Helms, H. IEEE Transactions on Audio and Electroacoustics, 1967, **15(2)**: 85–90  [2008-06-23], （原始内容存档于2019-06-30）

外部連結
----

* DSP class Fall 2005 Lecture08[永久] at The University of Texas at Arlington]