使用python进行音频滤波器操作
滤波器
大家好,我是EYS的张森。最近业务多了。这次讲讲如何用python实现简单的音频滤波器。在信号处理的领域,我们经常会碰到滤波器(Filter)。简单地说,滤波器对信号进行一系列运算,从而过滤杂音或提取想要的成分。图像领域著名的卷积神经网络,也可以看作是用神经网络学习(自动寻找)最适合当下任务的过滤器。
IIR滤波器
音乐等时间序列数据常用IIR(infinite impulse response filter)滤波器,如下
x指原信号,y指处理后的信号,右边出现y[n-1]等等,表示当前的y受此前y的影响。
用python设计滤波器
python的scipy在scipy.signal(https://docs.scipy.org/doc/scipy/reference/signal.html)中提供了一系列关于滤波器的功能。这里我们以巴特沃斯滤波器(Butterworth filter)为例看看其基本用法。巴特沃斯滤波器尽量平均地留下指定的频率带,削减以外的频率。首先,设计巴特沃斯滤波器,用signal.butter。比如说想留下300Hz以下的频率时用
b_digi, a_digi = butter(9, 300, 'low', fs=sr, output='ba')
这里output=”ba”指定输出为上文定义的b和a,此外还可以指定‘zpk’和‘sos’,不明确指定的时候,output自定义为‘ba’。sr指音频采样率,第一参数是滤波器的次数,第二参数是频率,第三参数是过滤器的种类。
滤波器的频率响应
滤波器的频率效果可以如下确认
w_digi, h_digi = signal.freqz(b_digi, a_digi, fs=sr, worN=fq)
w_digi是频率带,h_digi是滤波器对该频率的效果,通常为复数。过滤器不仅强调或减弱某频率,还改变频率的相位。画图,可得
实际对信号进行滤波器操作时用
arr_filter_ba_digi = signal.lfilter(b_digi, a_digi, arr)
看到这里或许很多人会有疑问,既然有频率响应函数,那直接在傅立叶空间捣鼓不久行了?干嘛还用这种看起了似乎原始又似乎高端的玩意?
https://stackoverflow.com/questions/34581355/frequency-domain-filter-vs-iir-and-fir-filter
原因有几个。一,通常处理信号用stft把信号人为地分割处理,这就使你得到的结果受分割窗口的长短影响,由于人为分割,傅立叶转换的结果还可能会受端点影响,因此你还要选择窗函数。这里面有很多人为因素,而滤波器的定义如上文所讲,相对来说“干净”。二,不用stft了,处理速度会比较快。
实际比较
我们实际找段音频看看效果吧。
- 原音频:https://freesound.org/people/Lemoncreme/sounds/186942/
- 300 LowPass:https://drive.google.com/open?id=1wldw7WfO7t1QTYtMLV3oeNikALRoF8EB
- 300 LowPass(在傅立叶空间处理,不包括phase):https://drive.google.com/open?id=1Scr9wXE46HsFMCfFxCqshi33N1rRV121
- 300 LowPass(在傅立叶空间处理,不包括phase):https://drive.google.com/open?id=1skO4yXWAT0Uvu3tyAEJbo3zVOZGS4Ydu
在用滤波器和频率处理的音频,在波普图上可以找到略微的不同,但听起来似乎没啥不一样。
- 300~3000 BandPass:https://drive.google.com/open?id=18Ip6U-t2YbksfoaUP7igUwwBXQdXP2Tu