Introduction
对一段音频信号进行处理,例如添加一个音效,有时候我们要考虑这样的处理对音频的影响是什么?是提高了低频,还是提高高频?或者频率做周期变化?
当然,你完全可以用耳朵来听,但是这么做难度太大了,毕竟并不是每个人都有一副金耳朵。即使你的耳朵非常好使,能够分辨最为细微的差别,但是你如何用人类能够理解的方式描述这种区别呢?毕竟并不是每个人都有莫言般的描述能力。
综上,我们需要一种可以量化的方式来描述”处理“的过程。毋庸置疑,我们只能借助数学来描述这种复杂过程。这篇文章中,我们将以多个视角来观察”处理“过程。
一些知识铺垫
下面介绍一些基础的信号处理知识,并不会很详细,都是点到为止,目的是将整体内容串起来,形成自我闭环。更多深入的介绍,大家有兴趣的话找本 dsp 的书来看吧。
信号表示
首先,如何表示一个音频信号(我们只讨论离散信号)?很简单,我们用一个数组来描述它,一个长度为 N 的信号,可以表示为:
我们称 x[n] 为离散时间序列
单位脉冲信号
它的数学表示是这样的:
也就是长这样:
线性时不变滤波器
所谓滤波器,其实就是对信号”操作“:一个信号,经过滤波器,变成了另一个信号。我们这里关注的是线性时不变(Linearity and time-invariance; LTI)滤波器。LTI滤波器应用广泛,是滤波器家族中最为壮大的一簇。我们可以差分方程来表示一个 LTI 滤波器:
其中 x 为输入序列,y为输出序列。和 为系数。
脉冲响应
将单位脉冲信号输入到一个 LTI 滤波器中得到的结果,我们称之为脉冲响应,通常表示为
卷积
信号经过 LTI 滤波器后得到 ,这个过程可以表示为脉冲响应与的卷积:
Z 变换
接下来我们介绍下 Z 变换,它非常重要。
Z变换可将离散时间序列变换为在复频域的表达式。额...好吧,前面那句话是百度百科抄的,对于那些从没有接触过 Z 变换的同学而言,这句话简直了。我们还是通过具体的例子,从感性的角度来理解下它。
Z变换的公式很简单的,如下:
举个例子,离散时间序列为:x[0]=1, x[1]=2, x[2]=3,那么:
通过 Z变换,我们将一组序列(N个值)转换为一个关于z的表达式(一个值)。 Z变换可以看成是线性变换,就比如上面的例子,可以改写为两个向量相乘:
关于 Z变换有一个重要的性质,卷积。两个信号在时域上做卷积,等于在 z变换域中相乘
在前面提到,信号经过滤波器可以表示为卷积过程(5),那么对进行Z变化得到:
从这个公式的角度来看,其实是进行了一次线性变换得到的,其中 被我们成为 传递函数(Transfer function; TF)
上面的公式同时表明,脉冲响应的Z变化 等于 转换方程 。这也是求 的一种方法,通过计算 ,然后做 z变换的逆变换,求得
关于 Z 变换还有一些性质我们需要掌握:
因此对于一个 LTI 滤波器(3),我们对其进行 Z变换得到:
合并同类项得:
如果 ,我们添加一些 0 系数进去,让左右两边的个数一直。
可得传递方程 :
多角度描述一个滤波器
差分方程 Difference equation
如公式(3),这就是差分方程。让我们举两个例子来感受下它。
和
将一个脉冲信号输入至 (14) 中,可得脉冲响应,的值逐渐接近 0,我们这样的滤波器是稳定的。
将一个脉冲信号输入至 (15) 中,可得脉冲响应,的值逐渐无穷大,我们称这样的滤波器是不稳定的。
块状图 Block diagram
有时候用图形的形式来展示滤波器更加符合人类的认知过程,以公式(3)为例,它的块砖图如下:
好吧,它看起比较复杂,我们看一个简单的例子,延迟信号:
它的块状图如下:
脉冲响应 Impulse response
正如前面提到的那样,将一个脉冲信号(公式(3))输入至滤波器中,然后观察输出,就能得到脉冲响应。
例如有个滤波器为:
你可以用下面这段 MATLAB 代码来画出该滤波器的脉冲响应
g1 = 0.5^3; B = [1 0 0 g1]; % Feedforward coeffs
g2 = 0.9^5; A = [1 0 0 0 0 g2]; % Feedback coefficients
h = filter(B,A,[1,zeros(1,50)]); % Impulse response
% h = impz(B,A,50); % alternative in octave-forge or MSPTB
% Matlab-compatible plot:
clf; figure(1); stem([0:50],h,'-k'); axis([0 50 -0.8 1.1]);
ylabel('Amplitude'); xlabel('Time (samples)'); grid;
复制代码
当然,我们还有更为精确的计算 的方法:对 进行 z变换可以得到传递函数 ,因此对 做逆 z变化得到 。
可以通过公式(13)得到,相当的容易。逆 z变换我还没学会,所以没法和大家解释了。但是我们可以来验证的z变换就是公式(13)的结果。
对公式(16)做z变换,得到传递方程:
取 ,可得
然后我们在代码中计算 H(z) 的值,也是得到 0.9972,完全一致。
g1 = 0.5^3; B = [1 0 0 g1]; % Feedforward coeffs
g2 = 0.9^5; A = [1 0 0 0 0 g2]; % Feedback coefficients
h = filter(B,A,[1,zeros(1,50)]); % Impulse response
z_value = 2; % z = 2
z = zeros(1,length(h)) + z_value;
Z = z.^-(0:length(h)-1);
HZ = h*Z'; %计算 H(z),结果为 0.9972
复制代码
传递方程 Transfer function
传递方程已经在上面说过了,对 做z变换可以得到,也可用公式(13)得到。在分析 LTI 滤波器时,传递方程是一种重要的方法。
极点、零点及增益 Poles zeros gain
我们对公式(13)上下同时乘上 ,得到一组多项式,并因式分解
我们称 为 增益(Gain)
我们称 为极点(Poles),当 ,
我们称 为 零点(Zeros),当 ,
我们将所有极点和零点画在一个复平面上,如果所有极点都在单位圆内,那么滤波器是稳定的;如果所有零点在单位圆内,那么我们称这个滤波器是最小相位滤波器。
频谱响应 Frequency Response
频谱响应指的是,信号经过滤波器后,在频域发生的变化,定义为:输出信号的频谱除以输入信号的频谱
一个信号经过傅里叶变化(DTFT)便可以得到其频谱信息:
你看DTFT是不是很像 z变换?公式(5)中 ,那么就完美对应上了 DTFT。 又有 ,因此得到:
那么频谱响应其实就是
其中 ,其中为信号频率其范围在 ,因此
频谱响应又分 幅度响应(Amplitude response) 和 相位响应(Phase response)
幅度响应其实就是 ,取个绝对值就ok了。幅度响应能够说明滤波器对每个频率幅度的影响。
相位响应其实就是 ,它说明了滤波器对每个频率相位的影响
实际的例子
千言万语不如一个实际的例子,假设我们有这样一个滤波器:
做z变换的:
计算传递方程:
做因式分解
得到两个极点: 和
得到两个零点,它们都在 ,将它们画在复平面上,可以发现所有极点都在单位圆内,因此这个滤波器是稳定的;所有零点都在单位圆内,因此它是最小相位的
当时,且,计算其幅度响应和相位响应,直接上代码计算:
w = 0:0.001:pi;
E = exp(1j*w);
Hz = (4*(E.^2) - 4*E + 1) ./ ((E.^2) + E + 0.5);
amplitude_Hz = abs(Hz);
phase_Hz = angle(Hz);
figure(1);
plot(20*log10(amplitude_Hz));
figure(2);
plot(phase_Hz*180/pi);
复制代码
其结果大概长这样:
从图可以看出,这个滤波器抑制信号中的低频信息,增益高频信息。在 (在 44.1kHz 采样率下为 17.3kHz)增益最大。 对于特别高和特别低的频率信息,这个滤波器在相位上只有很小的影响。但是在 (在 44.1kHz 采样率下为 11.025kHz)处,其相位信息偏移了 116度
总结
本文介绍了多种方式来认识一个滤波器,
- 差分方程
- 块状图
- 脉冲响应
- 传递方程
- 极点、零点和增益
- 频谱响应
并列举相关例子,让大家有更为深入的理解和体会。
转载请注明出处 juejin.im/post/5e709c…