一、最简单的混音算法 现在一般的软件混音算法是对输入的音频数据进行线性叠加, 即: (1) 或者叠加以后再取平均值: (2) 其中, m 为输入音频流的个数, n 为一帧的样本数目, ·[i] 为一帧中的第i 个样本, ·[j] 为第j 个音频流, 所以, output[i] 为混音后的一帧中第i 个样本, input[j][i] 为第j 个输入音频流当前帧的第i 个样本(若经过编码则输入音频流应在混音前通过解码等还原成线性的PCM音频流).通常的语音数据为16 bit(或者更少, 如8 bit), 即可以用C 语言中的short 类型表示, 其取值范围是−32768 ≤ 采样值≤ 32767, 可以预想到多个音频流直接线性叠加以后就有可能溢出, 所以式(1) 最后的结果可能会有溢出, 产生噪音. 两个连续平滑的波形叠加, 其结果也应该是平滑的. 所以产生噪音的地方就是由叠加溢出的地方引入的. 我们需要采用滤波来处理这些溢出部分, 改善由于溢出所造成的质量下降.为了解决溢出的问题, 一个常用的方法就是使用更多的位数来表示音频数据的一个样本, 在混音完毕以后,再使用一些算法来降低其振幅, 使其分布在16 bit 所能表示的范围之内, 这种方法叫做归一化(Normalize). 通常使用32 bit 来表示线性叠加以后的数据, 也就是C 语言中的int 类型, 实现简单, 运算也比较快, 更能满足很多路音频同时进行混音的需要. 式(2)对叠加的和值作平均, 解决了溢出的问题, 但是混音以后的声音会总体衰减,特别是某一路音频流的能量与其他路音频流的能量反差很大的情况下, 音量非常小, 效果非常不理想. 进行滤波处理的另外一种常用方法就是“箝位”, 当发生上溢时, 箝位以后的值为所能表示的最大值, 当发生下溢时, 箝位后的值为所能表示的最小值, 如式(3) 所示: (3) 其中, sample 为叠加以后的样本值, 为 32 bit, MAX 是最大输出值, 这里为32767, MIN 为最小输出值, 为−32768. 现在很多现有的论文和系统都是采用箝位方法, 因为实现简单, 快速, 效率很高. 但是可以看出, 这种箝位方法相当于在最大和最小的临界值处切强行切断波形, 非常生硬, 会造成较大的波形失真, 听觉上引起如嘈杂, 出现突发刺耳的爆破音等.采用时域叠加作为基本的处理手段, 由于数字音频信号存在量化上限和下限的问题,则因叠加运算肯定会造成结果溢出. 通常的处理手段是进行溢出检测, 然后再进行饱和运算(如 4 式的方法), 即超过上限的结果被置为上限值, 超过下限的值置为下限值. 这种运算本身破坏了语音信号原有的时域特征, 从而引入了噪声. 这就是出现爆破声和语音不连续现象的原因. 同时, 随着参与混音的人数增加, 出现溢出的频率也不断上升, 所以这类方法存在一个上限, 而且这个上限值很低, 实验证明, 采用这种时域直接叠加的方式进行混音, 一般不能突破 4 路输入音频流的限制, 否则将无法分辨语音流的内容了.
二、改进的混音算法 混音的时候, 还需要屏蔽某一路的本地音频数据, 这样就不会听到本地的声音, 只能听到其他 n − 1 路的声音, 也就是说, 对于第 t 路音频, 要发送给这个终端的混音后的数据如式(4): (4) 以下提出的算法主要思想就是使用一个衰减因子, 对音频数据进行衰减, 衰减因子会随着数据而变化. 当溢出时, 衰减因子比较小, 使溢出的音频数据衰减以后处于临界值以内, 当没有溢出时, 衰减因子会慢慢增加, 尽量保持数据的平滑变化. 而不是对于整帧使用同一个衰减因子来进行, 这是不同于式(2) 和式(3) 的地方, 既保证了整体的声强不至于衰减太快, 又保证了较小的失真度. 算法如下所述:
1. f 初始化为1.
2. 对于一帧中的样本按顺序处理: (a) output[i] = mixing[i] × f. (b) 如果output[i] > MAX, 求得最大的 f0 满足 output[i] × f0 < MAX, 然后 f = f0, output[i] = MAX. (c) 如果output[i] < MIN, 求得最大的 f0 满足 output[i]×f0 > MIN, 然后 f = f0, output[i] = MIN.
3. 如果f < 1, 则f = f + STEPSIZE. 继续处理下一帧, 转2. 其中f 为衰减因子, f0 为新的衰减因子; mixing[] 为所有音频流的某一帧线性叠加值, 实际实现的时候如式(4) 所示; output[] 为归一化以后的输出帧. MAX 为正的最大值; MIN 为负的最大值. STEPSIZE 为f 变化的步长, 通常取为 (1 − f)/16 或者 (1 − f)/32. 特别的, 就是在衰减以后的值溢出的情况下, 求新的衰减因子 f0 的方法不同, 新的 f0 需要满足 output[i] × f0 < MAX 或者 output[i] × f0 > MIN, 而不是直接使用mixing[i]. 也就是说, 使用衰减以后的值output[i] 来计算f0, 而不是原始值mixing[i], 这样将使得衰减因子的变化更为平滑. 用数学来表达, S 为溢出的一个样本值, 在S × f 仍然溢出的情况下, 可以比较一下计算出来的新衰减因子的大小:假设是上溢, forig 是原始算法计算出的新的衰减因子, 则f`orig < (MAX/S) , 我们改进的算法得出的新衰减因子 f`new < (MAX/(S×f)) , 因为 S > (S × f), 所以(MAX/S) < (MAX/(S×f)) , 那么 f`new 很大程度上要大于f`orig. 衰减因子大了(更接近1), 相邻的数据变化不会特别大, 所以跳跃的现象不会特别明显. 上述改进过的混音方案在实测中,与常规的混音算法(直接线性叠加的方式)比较, 常规算法在混入 4 路音频流的结果, 已经明显听到背景噪音, 波形会突变失真, 出现比较轻微的爆破音, 少量出现语音不可以辨认的情况; 如果混入 5 路或者 5 路以上的音频流, 则输出的音频流质量已经不能从听觉上接受, 语声模糊并且爆破音明显, 噪音大, 难以辨别语音内容. 采用衰减因子的方式进行调整以后, 混入 4 路音频流从听觉上基本感觉不到背景噪音, 混入 5 路的情况下, 仍然能清晰辨别各路的语音内容, 不出现爆破音; 混入 6 路到 9 路的情况下仍然能保证语音质量, 不会发生突变的爆破音, 能够满足视频会议的要求. 从算法执行效率上看, 与常规的混音算法比较, 其时间复杂度并没有增加而具有同等的时间复杂度, 只是调和系数法在计算过程中叠加时需要进行一次额外的乘法运算(如上述算法描述的 2.a), 并且发生溢出的情况下需要重新计算新的调和系数(整数除法运算), 最后在算法的第三步需要进行一次加法运算(浮点数加法). 因为涉及的数值不会很大, 同时音频流的数据量较之视频等要小得很多, 在视频会议的应用中, 采用调和系数方法进行混音完全在 MCU 承载的能力范围内, 实测与常规混音算法比较, 格式为 linear PCM raw, 16 bit, 单声道, 采样率为8000 HZ, 时间30 秒, 帧长30 毫秒的情况下, 其差别不会超过 17ms , 并不会由此产生很大的延迟, 其实时性仍然得到保证, 而从混音的质量来说较常规混音算法要好很多.
分享到:
相关推荐
现有的混音算法主要分为几种类型:平均混音算法、对齐混音算法、自对齐混音算法以及箝位混音算法。这些算法各有优缺点: - **平均混音算法**:随着参与混音的声音数量增加,最终输出音量逐渐降低,导致声音过小的...
### 音频混音算法详解 #### 一、引言 在数字信号处理领域,音频混音技术是一项非常重要的技术,被广泛应用于音乐制作、广播、电影制作等多个领域。混音算法可以将多个声音源合成单一的声音输出,使得音频内容更加...
"高质量音频混音算法及应用"的主题聚焦于如何有效地将多个音频信号混合在一起,同时保持高音质,避免数据溢出等问题。本文将深入探讨相关知识点。 1. **PCM音频数据**:PCM(Pulse Code Modulation)是一种模拟信号...
通过自动对齐算法,newlc算法,平均加权算法,自适应混音加权算法等进行简单的混音测试
### 一种混音算法:对数动态范围压缩(Logarithmic Dynamic Range Compression) #### 概述 在数字音频处理领域,混音(Mixing)是一项重要的技术。它涉及到将多个声音源合并成一个单一的音频流的过程。在此过程中,...
在IT领域,音频处理是重要的一环,尤其是对于游戏开发、音乐制作软件或者实时通信应用。...对于想要学习音频处理的程序员来说,这个项目提供了很好的学习材料,通过实际操作,可以加深对音频混音算法的理解。
这个压缩包"多路混音算法源码"包含了实现这一功能的核心算法,以及相关的测试代码和音频源文件。下面我们将详细探讨多路混音的关键概念和技术。 1. **混音算法**: - **时间对齐**:混音的第一步是确保所有音频源...
【标题】"mixerlib:音频混音demo基于归一化混音算法和软运算的音量调节方法",揭示了这是一个使用C++语言开发的音频处理库,专注于音频混音功能,特别是采用归一化混音算法和软运算技术进行音量控制。在深入探讨...
多路混音算法是数字语音教室中的关键技术之一,它允许在教学过程中实时混合同步多路音频信号,以实现音频的双向或多向交流。这种技术在数字语音教室的设计和应用中扮演着重要的角色。本文将探讨数字语音教室的结构...
### DSP通用音频算法研究 #### 一、引言 随着数字信号处理器(DSP)技术的发展,DSP已经成为现代信号处理领域不可或缺的一部分。DSP芯片因其高效能处理能力而在多种应用中发挥着重要作用,特别是在音频处理领域。DSP...
本话题主要涉及的是C语言实现的归一化混音技术,它包括了源代码和相关的音频文件,同时也提供了一个用于在Linux环境下使用ALSA库播放PCM(脉冲编码调制)音频的示例。下面我们将深入探讨这两个核心概念:归一化混音...
Lt/Rt模式的混音算法为: Lt = L + 0.707 * C - 0.707 * Ls - 0.707 * Rs; Rt = R + 0.707 * C + 0.707 * Ls + 0.707 * Rs; 这里,C代表中心声道,Lt和Rt分别是左Total和右Total声道。在混音到单声道时,只需将Lt和...
* 其他混音算法:为了解决溢出的问题,人们找了不少的办法,这里主要介绍几种我用过的,并给出相关代码实现和最终的混音效果对比结果。 五、结论 * Android 中一种效果奇好的混音方法详解主要给大家介绍了关于在 ...
5. **混音算法设计**:根据实际需求设计合适的混音算法。例如,可以通过调整背景音乐的音量来适应角色语音的插入,或者采用更为复杂的动态范围压缩技术来保持整体音质的一致性。 #### 实现步骤 1. **初始化DSP资源...
在本文中,我们将深入探讨如何将两个G.729语音流文件混合成一个WAV文件,这涉及到G.729编码的理解、语音解码、混音算法以及C++编程技术。G.729是一种高效的声音压缩标准,常用于语音通话和VoIP系统,以减少带宽需求...
4. **混音算法**:混音算法决定了如何合并音频信号。简单的方法是直接相加,但可能会导致音量过大(溢出)。更高级的算法会考虑动态范围压缩、增益控制等,以避免失真。 5. **通道管理**:处理立体声、环绕声等多...