因项目需求实现混音效果,故学习记录了一下。
算法调研
常见混音方式:
- 加和后再除以混音通道数,防止溢出
- 加和并箝位,如有溢出就设最大值
- 饱和处理,接近最大值时进行扭曲(“软件混音的实现”一文算法就是这类)
- 归一化处理,全部乘个系数,使幅值归一化。(只适用于文件)
- 衰减因子法,用衰减因子限制幅值。
- newlc 算法
音频混音算法原理
混音原理简单说一下:声音是由于物体的振动对周围的空气产生压力而传播的一种压力波,转成电信号后经过抽样,量化,仍然是连续平滑的波形信号,量化后的波形信号的频率与声音的频率对应,振幅与声音的音量对应,量化的语音信号的叠加等价于空气中声波的叠加,所以当采样率一致时,混音可以实现为将各对应信号的采样数据线性叠加。而问题的关键就是如何处理叠加后溢出问题。
混音的原理其实很简单,只要多路语音数据做线性叠加即可,但是叠加后的音频数据容易产生溢出,而且混合的路数越多,溢出的可能性越大,所以要做溢出处理,其实如何完美的处理混音叠加后溢出问题才是混音算法的关键;以下是常见算法:
1、平均权重算法
叠加以后再取平均值(除以混音路数),这样不容易产生溢出,但是会造成音质衰减过大,各路音量会逐步变小,影响通话质量,所以一般不采取求平均这种方式;但是可以扩展一下,考虑参与混音的多路音视频信号自身特点,以它们自身的比例作为权重,比如如果是背景音乐可以适当权重低一些,领导讲话可以适当权重高一些,这样混合后的效果也会随着场景的应用会更合适一些。
2、边界值法
将每一路的语音线性相加进行溢出检测,如果溢出,以最大值或最小值来替代。这样会造成声音波形的人为削峰,在破坏语音信号特性;
3、自适应混音加权(衰减因子)
为了更好的解决溢出问题,可以使用一个衰减因子, 对音频数据进行逐渐衰减, 衰减因子会随着数据而变化.当数据溢出时,则相应的使衰减因子变小,使后续的数据在衰减后处于临界值以内,没有溢出时,让衰减因子慢慢增大,使数据变化相对平滑。(随着会话成员增多也会出现溢出问题);采用衰减因子的方式进行调整以后, 混音的数据从听觉上基本感觉不到背景噪音,会感觉很舒适,也基本上不会出现爆破音,这种方式比较推荐;
4、自动对齐算法
考虑参与混音的多路音视频信号自身特点,以它们自身的比例作为权重,从而决定它们在合成后的输出中所占比重。(测试发现高频信号损失严重)
5、箝位算法
时域叠加,进行溢出检测,然后进行饱和运算.(一般通用使用,但是容易溢出).
6、newlc算法
网上普遍提到 newlc 算法,但【1】中提到,该算法并没有什么数学根据,而且从两路扩展到多路效果并不好。一篇论坛帖子(但与原文中引文并不一致)回贴的没有一个赞同这一算法的。
该算法的出处:http://newlc.com/topic-10064 作者自己说,该算法对于5个通道以上就不太好,算法的好处是不会溢出。但有人反映声音有饱和的趋向。
【算法原型】
Y = A + B - (A * B / (-(2 pow(n-1) -1)))
Y = A + B - (A * B / (2 pow(n-1))
【算法简述】
算法简述如下:
For n-bit sampling audio signal
If both A and B are negative Y = A + B - (A * B / (-(2 pow(n-1) -1)))
Else Y = A + B - (A * B / (2 pow(n-1))
注意具体实现与算法稍有不符。实现中两种情况都除以(-(2 pow(n-1) -1))),根据算法,大部分情况下都应该除以(2 pow(n-1))。是否减1有什么作用?如果不必减1,对于整数运算就可以用移位实现。