我在前面的文章《音頻開源代碼中重采樣算法的評估與選擇 》中說過sinc方法是較好的音頻重采樣方法,缺點是運算量大。https://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, 從而
考慮到有上下采樣,文檔(https://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函數並離散化,來獲得近似信號。在文檔(https://ccrma.stanford.edu/~jos/resample/)中,使用Kaiser window加窗截斷,通過線性插值采樣后的樣本來模擬脈沖響應的連續性,獲得很好的效果。
至此基於sinc方法的重采樣原理就講完了,即新的采樣率下的值是原采樣率下的值和相對應的sinc函數的乘累加。如果此時去看相關的代碼實現,很大可能是一頭霧水,下篇將講怎么基於原理去做軟件實現以及實現中的一些細節。