You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

120 lines
14 KiB
Markdown

2 years ago
# 14音效三剑客变调、均衡器、混响
你好,我是建元。
你是否很好奇《名侦探柯南》里的变声器在现实中能否实现?百万调音师能让本来唱歌跑调的人的歌声变得好听,这到底是用了什么神奇的方法?其实今天我们要讲的音频中的音效,就是为了实现这些变声、修音等特效而设计的一系列的音频处理算法。
为了实现某种特定的效果,音效算法的种类有很多,这节课我主要介绍三种常见的音效算法:变调、均衡器和混响的设计和使用方法。
## 变调
其实在之前讲弱网对抗部分的时候,我们在做快慢放操作时就使用到了变速不变调算法,这其实是变调算法中的一种用法。在讲算法具体实现之前我们先想一下,变调的物理含义是什么?
之前我们讲语音信号分析的时候说过不同的人发音的基频是不一样的。而音调和基频是直接相关的要变调其实就是要改变基频。而基频的本质是一个信号的循环周期的倒数比如基频是250Hz那么当前时间的语音信号就是以4ms为周期的信号。**我们要变调,其实就是把这个循环周期进行扩大或者缩小。**
如图1所示如果我们把语音信号的基频提升一倍或者说提升一个八度或者12个半音那么时域信号绿线部分上面为变调前下面为变调后语音的波形还是很相似的只是每一个周期都缩短了一半。
再看看频域信号红色部分是不是变得更稀疏了最下面的那根亮线代表的基频从250Hz左右提升到了大约500Hz的位置。由于谐波的频率是基频的倍数所以谐波之间的间隔也变大了。
![图片](https://static001.geekbang.org/resource/image/89/61/89e70eyy5132e033ec1e46a0aacbe661.png?wh=702x734 "图1 升调后的语音时域和频域图")
那么我们是如何实现音调提升的呢?
其实方法很简单,就是**把原来的信号进行重采样,但不改变播放信号的采样率**。简单来说比如把原来20ms的音频每两个点取一个点然后按照相同的采样率进行播放这样10ms内需要播放原来20ms的内容。这样一来原本的信号循环时间周期就变成了二分之一从而实现了升调。
但这里有个问题因为每一段时间内需要播放的音频信号的采样点是固定的。也就是说通过下采样的方法音频从原来的20ms缩短成了10ms。直观的感受就是这个人的音调变高了但说话的语速也变快了也就是变速又变调。
但我们想实现的变声只是改变音调,也就是所谓的“**变调不变速**”。其实实现的方法也很简单核心思想就是通过把音频中的信号按照一定的规律拼接起来把音频的长度拉长或者缩短这就是我们要讲的第一种变调算法OLAOverlap-and-Add
还记得之前我们讲的STFT吗**其实OLA的思想和STFT中的Overlap的思想很相似。**
如图2所示$x$为输入信号、$y$为输出信号。OLA的过程按照图2中b、c、d的顺序取一帧$x\_m$,选择间隔长度$H\_a$的下一帧$x\_{m+1}$,然后把这两帧加窗(汉宁窗)后,以步长$H\_s$把两帧重叠、相加在一起。很显然$H\_a$和$H\_s$的比值就是原始信号和输出信号长度的比值。这样我们就可以把原始音频拼接成不同长度的音频了,然后再经过重采样把音频恢复成和原始音频相同长度的音频再播放,这样就实现了变速不变调。
![图片](https://static001.geekbang.org/resource/image/92/2f/9229cff9c61f989d2536c6b7d110722f.png?wh=606x455 "图2 OLA算法的基本原理[br]图片来源 https://www.mdpi.com/2076-3417/6/2/57")
有趣的是,如果不进行重采样直接播放,由于拼接起来的音频没有改变原始语音的基频周期,只是改变了音频的长短,这就实现了我们弱网对抗中用的“变速不变调”的算法。
但是采用这种Overlap的方式虽然可以防止连接处的信号产生跳变但不能保证每一个窗内覆盖的信号都处于周期中的相同相位或者说**两个窗内信号周期的起始位置不相同**。这就会导致我们常说的“相位失真”。
如图3所示拼接的信号会出现时高时低的现象。所以如果我们能实时的根据信号本身的自相关属性也就是把信号中相似的两段直接拼接在一起这样就不会有相位的问题了。基于这样的思想于是就有了波形相似叠加WSOLAWaveform similarity Overlap-Add算法。
![图片](https://static001.geekbang.org/resource/image/cb/94/cb0a1479dd41aeebe1f88e2408597f94.png?wh=593x446 "图3 Overlap导致的幅度变化[br]图片来源 https://www.mdpi.com/2076-3417/6/2/57")
WSOLA算法的计算步骤如图4所示其实相比于OLAWSOLA会在$x\_{m+1}$帧的附近寻找和输入信号中如果也移动步长$H\_s$的信号$\\tilde{x}\_{m}$相似度最高的一段$x\_{m+1}$来做拼接。
![图片](https://static001.geekbang.org/resource/image/dd/b9/dd5b839fee9947397e3314f7b4fe53b9.png?wh=1151x866 "图4 WSOLA的计算步骤[br]图片来源 https://www.mdpi.com/2076-3417/6/2/57")
根据相似性原理其实WSOLA合成出来的变调杂音基本已经没有了WebRTC中的快慢放用的就是WSOLA。但WSOLA算法在实时变调中有一个问题那就是每一帧出现的位置由于需要相似性搜索所以需要更多的未来帧的信息也就是说需要引入更多的延迟。
在时域变调的算法中还有一种[PSOLA](http://articles.ircam.fr/textes/Schnell00a/index.pdf)Pitch Synchronous Overlap and Add顾名思义需要先计算pitch然后根据基音周期来改变Overlap的大小这样就直接实现了变调。但是基频检测的鲁棒性没有WSOLA的相似性搜索高所以PSOLA的生成可能会出现不稳定的情况你有兴趣的话可以根据[链接](http://articles.ircam.fr/textes/Schnell00a/index.pdf)自行了解一下。
其实变调算法除了在时域上做拼接还可以在频域上实现比如常见的LSEE-MSTFTM、Phase Vocoder等算法。
我们看到WSOLA等方法通过相似性来寻找拼接对象但是相似性说到底是通过计算两段时域信号的MSEmean squared error取最小值来得到的这种方法能尽量保持低频相位的连续性但高频信号的相位差异可能不能确保一致。
其中Phase Vocoder利用STFT中提供的相位信息在变调扩展的同时会对每个傅里叶频点做相位修正生成出的音质会比较高所以在实时变调中常被使用。有兴趣的话你可以查看[文献](https://www.jstor.org/stable/3680093)了解一下。
理解了变调,我们就可以通过算法来改变音频的音调了。比如电影《小黄人大眼萌》中“小黄人”的声音,就是通过变调算法把原本男声的音调提高来实现的。
那么电影《绿巨人》中浩克的那种低沉、怪异的音色又是怎么实现的呢?
## 均衡器
我们知道每个人都有自己独特的音色,比如有的人声音比较低沉,有的人声音比较清脆。其实对这些音色的感知主要是由于人们在发音时,频谱中不同频段的能量分布不同而导致的。
比如声音低沉的人可能低频分量比较低而唱高音、音色饱满的人可能高频的能量也能保持得比较多。而其中最直接的可以改变音色或者说改变声音在不同频率的能量分布的方法就是EQ也就是均衡器Equalizer
那么我们是如何实现一个均衡器来对不同频段的能量进行调整的呢?
**其实均衡器就是一组滤波器,比如常见的高通、低通、带通、带阻等形式。**这些可能你之前在大学里的数字信号处理课程里学过。看字面意思应该就可以理解高通、低通和带通就是让高频、低频或者某个频带的音频保留而其它的频带都加以削弱而带阻就是削弱某个频带的音频能量。比如我们觉得人声中齿音太多想要去齿音可以在10kHz14kHz左右加一个带通滤波器削减一下这部分的能量。
音频滤波器有很多种比如常用的FIRFinite Impulse Response和IIRInfinite Impulse ResponseFilter。如何根据你想要的频段和增益来设计FIR和IIR滤波器其实早已编入了教材不是信号处理专业的同学可以参考《数字信号处理》这本书。
当然EQ的处理经过多年的发展已经有很多通用的滤波器可以选用了比如椭圆、切比雪夫、巴特沃斯和贝塞尔滤波器等等。如果你想快速实现一个滤波器看看效果也可以直接使用Matlab中的[滤波器设计toolbox](https://ww2.mathworks.cn/help/signal/filter-design.html?s_tid=CRUX_lftnav) 来加速实现进程。
如果不想自己编程实现也可以利用一些音频处理软件来进行可视化的处理。比如在Adobe Audition中我们可以看到各种常见的EQ均衡器。如图5所示由上到下依次为FFT滤波器、图形均衡器以及科学滤波器。我们在离线自己做一些音频处理时可以选择其中的一个或者多个串行使用。
![](https://static001.geekbang.org/resource/image/d7/87/d7c41d40fd05eb7744255c66009b8a87.png?wh=707x1460 "图5 Audition中常见的均衡效果器")
## 混响
好的,知道了如何调节音色,我们再来看看和空间相关的混响。
其实在之前的课程中我们已经多次提及了混响的概念。在之前讲空间音频时我们知道可以通过采样的方式或者镜像法得到房间的混响RIR这样得到的混响叫做采样混响。采样混响真实但是不一定好听并且RIR需要和音频信号做卷积才能得到混响信号。当混响时间很长的时候需要的算力也是巨大的。在音乐制作时为了营造更好的听感经常会使用一些人工混响效果器来产生混响在实时音效里也可能因为要节省算力而采用人工混响效果器的方式来生成混响。
简单地理解,混响信号可以看作是直达声和许多逐步衰减、不断延迟的回声信号叠加而成的。假设一个衰减系数$a$和延迟$D$,那么混响信号$y(n)$可以用下面的等比数列来表示:
$$y(n)=x(n)+ax(n-D)+a^{2}x(n-2D)+…$$
其中 $x(n)$ 是输入信号,$D$为回声的延迟。而这种形式正是梳状滤波器的形式。如图6所示所谓梳状滤波器其实就是因为它的频率响应呈一个梳子的形状。**梳状滤波常被用来消除某些不需要的谐波,但这里主要是利用了它的拖尾效应。**
![图片](https://static001.geekbang.org/resource/image/15/ec/152f235816f7128dyy77e47663fb16ec.png?wh=922x347 "图6 梳状滤波器的频率响应")
但也如图6所示梳状滤波器的频谱曲线不平坦呈现明显的梳状效应。从而对不同的频率成分幅度会产生波动导致梳状滤波器的拖尾声音带有很强的金属染色效应。而且回声只在延迟为D和D的倍数的时候出现这就显得过于稀疏了。所以在梳状滤波器的基础上Schroeder使用多个梳状滤波器来解决混响不够密集的问题然后用全通滤波器Allpass filter来消除金属声。
![图片](https://static001.geekbang.org/resource/image/f9/da/f99af8748bd81e2c870b6049663125da.png?wh=1104x338 "图7 Schroeder混响模型流程[br]图片来源 http://freeverb3vst.osdn.jp/doc/Sun-Schroeders_Reverberator.pdf")
图7为Schroeder混响模型的结构图其中每个Comb代表一个梳状滤波器。**但Schroeder依靠全通滤波器生成的混响依旧不够密集。**
后续Moorer又对Schroeder模型进行了改良把混响的生成拆成了直达声、早期混响、晚期混响这三个部分。加入了FIR模块来模拟早期混响用6个梳状滤波器和一个全通滤波器来模拟晚期混响并可以控制各部分的增益。有兴趣的话你可以通过[链接](http://freeverb3vst.osdn.jp/doc/Elec407-HybridReverb.pdf)了解一下。
其实Moorer模型之后人们会用各种方式来对混响模型进行改造现在的混响生成器基本上也都是开放出很多参数可调节的混响效果器了。比如混响的初始延迟、干湿比、混响RT60时间等。这里介绍一个[Freeverb3](http://www.nongnu.org/freeverb3) 开源库,这里有很多基于不同算法的混响效果器实现方法,你可以根据自己的需求了解一下里面的内容。
## 小结
好的,今天的课程到这里就要结束了,我们来总结一下。
改变声音可以从三个基本的方向来修改,也就是改变音调、音色和混响,分别对应了变调、均衡器和混响这三种算法。
其中变调算法比较常用的有基于拼接的OLA、WSOLA以及频域的Phase Vocoder等。而均衡器主要是通过一个滤波器组对不同频段的能量来进行调节成熟的算法有很多但大多是FIR或者IIR滤波器的组合。人工混响则是可以采用多个梳状滤波器的滤波器组串联全通滤波器来实现比较常见的有Scheoeder和Moorer混响模型。
当然音效的种类还远不止这三种这节课只能算是音效的常见算法的入门。在这里再和你分享一个音效的网页demo里面有声网研发的各种声音效果。你可以通过[链接](https://www.agora.io/cn/audio-demo)感受一下,看看音效还能做出什么不同的效果。
## 思考题
其实知道了这些音效的基本原理结合常用的一些开源库或者音频处理软件就可以开始对音频进行音频效果调整了。比如我们之前说的绿巨人的音效实际上就是通过变调、均衡器和混响来整体调节的。绿巨人需要把原来的声音进行降调比如降八度然后可以使用10段均衡器绿巨人的均衡器参数如图8所示然后再加一个小房间的混响就可以实现了。你可以用Audition的效果模块自己试着调一调。
![图片](https://static001.geekbang.org/resource/image/0f/dc/0f4b314b534dcddd000bff4683e379dc.png?wh=488x261 "图8 绿巨人均衡器参数")
期待你的动手实践,过程中遇到任何问题,都可以到留言区中与我交流讨论。也欢迎你把这节课分享给你的朋友,邀请他一同尝试。我们下节课再见!