基於sinc的音頻重採樣(一):原理
我在前面的文章《音頻開源代碼中重採樣算法的評估與選擇 》中說過sinc方法是較好的音頻重採樣方法,缺點是運算量大。//ccrma.stanford.edu/~jos/resample/ 給出了sinc方法的原理文檔和軟件實現。以前是使用這個算法,沒太關注原理和實現細節。去年(2020年)由於項目的需要和組內同學把這個算法的原理和軟件實現細節搞清楚了。本文先講講sinc方法的原理,後面文章會講講軟件實現的細節。
1,sinc函數和信號的採樣與重建
在數字信號處理中,sinc函數定義為:

當x = 0時,sinc函數值為1,當x為整數時sinc函數值為0(這些整數點x稱為過零點)。可以畫出sinc函數的波形圖如下:

可以看出sinc函數是連續無限且關於Y軸對稱的(即sinc函數是偶函數)。
採樣定理說如果模擬信號x(t)包含的最大頻率是Fmax且以Fs> 2Fmax的頻率被採樣,那麼x(t)可以用插值函數:

從它的樣本重建。這裡的插值函數就是sinc函數。重建後的x(t)可表達為:

這裡x(n/Fs) = x(nTs) = x(n)是x(t)的採樣點值。Fs是採樣頻率,Ts是採樣間隔,Fs = 1/Ts。
2,重採樣
把數字信號的採樣率從一個頻率轉換為一個另不同頻率的過程稱為重採樣(sampling rate conversion,SRC)。上面採樣定理說過如果信號的帶寬小於採樣率的一半,就可以用插值從樣本重建信號。用新的採樣率採樣這個重建的信號,就可以實現重採樣。
假設以Fx=1/Tx採樣一個連續信號x(t),生成離散信號x(nTx)。使用插值公式:

可以從樣本x(nTx)生成連續信號y(t)。如果x(t)的帶寬小於Fx/2且

那麼y(t) = x(t)。為了實現重採樣,只需要以時間間隔t=mTy對y(t)進行求值即可,Fy=1/Ty是新的採樣率。

重新組織g(t)的參數:

mTy/Tx可以分解成整數部分km和分數部分

所以

令k=km-n,所以 n =km – k, 從而

考慮到有上下採樣,文檔(//ccrma.stanford.edu/~jos/resample/)給出插值函數為:

其中Fx為原採樣率,Fy為新採樣率。
令 A= min(1, Fy / Fx), B = min(Fx, Fy), ρ = Fy / Fx = Tx / Ty, 則g(t)可表示為

所以 
在上式中,x和y信號離散化後,在x信號和y信號中的Tx,Ty可以去掉了。式子就變成了如下:

上式中BTx在Fx,Fy已知的情況下是個常數。
令D=BTx,上式就變成了:

當上採樣時B=Fx,則D=FxTx=1,A=1,所以式子重寫為:

當下採樣時B=Fy, 則D= FyTx = ρ A= ρ,所以式子重寫為:

從上面的式子可以看出,新的採樣率下的值是原採樣率下的值和相對應的sinc函數的值的乘累加。由於sinc函數是連續且無限的,真正實現時是無法做到的,所以這兒通過截斷sinc函數並離散化,來獲得近似信號。在文檔(//ccrma.stanford.edu/~jos/resample/)中,使用Kaiser window加窗截斷,通過線性插值採樣後的樣本來模擬脈衝響應的連續性,獲得很好的效果。
至此基於sinc方法的重採樣原理就講完了,即新的採樣率下的值是原採樣率下的值和相對應的sinc函數的乘累加。如果此時去看相關的代碼實現,很大可能是一頭霧水,下篇將講怎麼基於原理去做軟件實現以及實現中的一些細節。

