首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

改进型归一化混音算法

  • 23-09-22 20:23
  • 4530
  • 12931
blog.csdn.net

改进型归一化混音算法

linear PCM格式的音频混音

音频混音的原理: 量化的语音信号的叠加等价于空气中声波的叠加。

反应到PCM音频数据上,也就是把同一个声道的数值进行简单的相加,但是这样同时会产生一个问题,那就是相加的结果可能会溢出,当然为了解决这个问题已经有很多方案了.

假设音频文件采样率、通道数、采样精度一样。

另外要注意的是,在源音频数据中是按照little-endian的顺序来排放的,PCM值为0表示没声音(振幅为0)。

源码如下:

bufferA 音频A的首地址

bufferB 音频B的首地址

  1. static void pcmAudioMix(SInt16 *bufferA, SInt16 *bufferB, UInt32 bufferLength){
  2. char * sourseFile[2];
  3. sourseFile[0] = (char *)bufferA;
  4. sourseFile[1] = (char *)bufferB;
  5. bufferLength *= 2;
  6. Mix(sourseFile, 2, (char *)bufferB, bufferLength);
  7. }
  8. static void Mix(char ** sourseFile,int number,char *objectFile, UInt32 bufferLength){
  9. //归一化混音
  10. int const MAX = 32767;
  11. int const MIN = -32768;
  12. double f = 1;
  13. int output;
  14. for (int i = 0; i < bufferLength/2; i++)
  15. {
  16. int temp = 0;
  17. for (int j = 0; j < number; j++)
  18. {
  19. char *point = sourseFile[j];
  20. if (j == 0) {
  21. int mixTemp = *(short *)(point + i*2);
  22. temp += (int)(mixTemp);
  23. }else{
  24. temp += *(short *)(point + i*2);
  25. }
  26. }
  27. output = (int)(temp * f);
  28. if (output > MAX)
  29. {
  30. f = (double)MAX / (double)(output);
  31. output = MAX;
  32. }
  33. if (output < MIN)
  34. {
  35. f = (double)MIN / (double)(output);
  36. output = MIN;
  37. }
  38. if (f < 1)
  39. {
  40. //此处取SETPSIZE 为 32
  41. f += ((double)1 - f) / (double)32;
  42. }
  43. *(short *)(objectFile + i*2) = (short)output;
  44. }
  45. }

算法如下所述:

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.


SETPSIZE为f的变化步长,通常的取值为(1-f)/VALUE  其中(1-f)为固定值只是后面的VALUE值可以取 8, 16, 32,64,128. SETPSIZE取值较大时,运算复杂度低,但语言平滑度不够细腻,STEPSIZE取值较小时,运算复杂度高,但语言平滑度比较细腻。


  特别的, 就是在衰减以后的值溢出的情况下,求新的衰减因子 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), 相邻的数据变化不会特别大,所以跳跃的现象不会特别明显.

参考文章:

http://iyenn.com/rec/327360.html

http://iyenn.com/rec/327361.html

http://iyenn.com/index/link?url=http://www.cnblogs.com/caosiyang/archive/2012/07/16/2594029.html

http://iyenn.com/index/link?url=http://soundfile.sapp.org/doc/WaveFormat/

http://iyenn.com/index/link?url=https://my.oschina.net/daxia/blog/636074



文章知识点与官方知识档案匹配,可进一步学习相关知识
算法技能树首页概览51048 人正在系统学习中
注:本文转载自blog.csdn.net的jeffasd的文章"https://blog.csdn.net/jeffasd/article/details/77335874"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2024 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top