混音算法的学习与研究
金庆 2007.10.31
(转载请注明来源于金庆的专栏)
想把原来一个旧程序中的混音算法改善一下,就大致研究了一下混音算法。
原来的混音是直接加和,因为音源音量很小,连溢出也没考虑。
出来的效果只能是大概有个响动,不过程序应用的领域只需达到这点就足够了。
现在音源音质改善了一点,有必要也对混音算法做点改进了。
主要还是曾经看到这样一篇混音新算法的转载文章[3],一直想应用一下。
再次翻到那篇文章,算法很简单,表达也很清晰,就是不知道原理。
算法简述如下:
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,对于整数运算就可以用移位实现。
如果对多路混音该如何扩展算法呢?
算法的出处未注明,所以我搜索了一下,找到一篇论坛帖子(但与原文中引文并不一致):
http://www.dsprelated.com/showmessage/27372/1.php从中可以看到,算法并没有什么数学根据,而且从两路扩展到多路效果并不好。回贴的没有一个赞同这一算法的。
看来不能盲目照搬没有根据的算法。
[3]中还有一个NOKIA的代码下载,根据所附链接,下载了这个NOKIA的例子,其中混音的代码在CMixerThread::FillBuffer()中,发现只是简单的加和再限值,没有什么利用价值。
后来终于找到该算法的出处:
http://newlc.com/topic-10064作者自己说,该算法对于5个通道以上就不太好,算法的好处是不会溢出。但有人反映声音有饱和的趋向。
总结一下我对混音算法的学习,大概有以下几种方式:
1. 直接加和
2. 加和后再除以混音通道数,防止溢出
3. 加和并箝位,如有溢出就设最大值
4. 饱和处理,接近最大值时进行扭曲(“软件混音的实现”一文算法就是这类)
5. 归一化处理,全部乘个系数,使幅值归一化。(只适用于文件)
6. 衰减因子法,用衰减因子限制幅值[1]。
直接加和,或除以通道数的混音方法有严重缺陷,效果可能很差。箝位法最大混音数大约是4个,饱和处理最大混音数可能再高几个。对于大量的混音,应该采用衰减因子法。
文献[2]提出了一个自对齐权重法(align-to-self weighted,简称ASW),以一个时间帧为单位进行衰减,可能在帧之间有断续,效果应该不如平滑的衰减。
如果[1]中的衰减因子计算时能考虑整个时间片的数据,而不仅仅是当前点,那样效果会更好吧。
(转载请注明来源于金庆的专栏)
参考文献:
[1]
视频会议中关于混音算法的一些笔记[2]
多媒体会议中的快速实时自适应混音方案研究 (PDF)[3]
软件混音的实现