我在前面的文章《音频开源代码中重采样算法的评估与选择 》中说过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函数的乘累加。如果此时去看相关的代码实现,很大可能是一头雾水,下篇将讲怎么基于原理去做软件实现以及实现中的一些细节。