首页 > 音视频 > PCM音量控制(高级篇)
2017
05-14

PCM音量控制(高级篇)

去年写过一篇文章,有关PCM的音量控制:http://blog.jianchihu.net/pcm-volume-control.html。那时阐述了一些概念,对一些细节没有详细描述。因为有人问到使用对数关系调节音量,故开此篇文章。

声学中的分贝

因为人耳的特性,我们对声音的大小感知呈对数关系。所以我们通常用分贝描述声音大小,分贝(decibel)是量度两个相同单位之数量比例的单位,主要用于度量声音强度,常用dB表示。声学中,声音的强度定义为声压。计算分贝值时采用20微帕斯卡为参考值(通常被认为是人类的最少听觉响应值,大约是3米以外飞行的蚊子声音)。这一参考值是人类对声音能够感知的阈值下限。声压是场量,因此使用声压计算分贝时使用下述版本的公式:
PCM音量控制(高级篇) - 第1张  | 剑痴乎
其中的pref是标准参考声压值20微帕。

分贝声音变化范围

在编程中,我们可以用以下公式计算两个声音之间的动态范围,单位为分贝:

其中 A1 和 A2 是两个声音的振幅,在程序中表示每个声音样本的大小。声音采样大小(也就是量化深度)为1bit时,动态范围为0,因为只可能有一个振幅。采样大小为8bit也就是一个字节时,最大振幅是最小振幅的 256 倍。因此,动态范围是 48 分贝,计算公式如下:
dB = 20 * log(256)

48 分贝的动态范围大约是一个安静房间和一台运行着电动割草机之间的区别。如果将声音采样大小增加一倍到16bit,产生的动态范围则为 96 分贝,计算公式如下:
dB = 20 * log(65536)

这非常接近听力最低阈值和产生痛感之间的区别,这个范围被认为非常适合还原音乐。

了解了分贝的相关概念我们通过图表说下为什么要用对数关系描述声音大小。
1)音量滑块与声音增幅大小线性变化。
PCM音量控制(高级篇) - 第2张  | 剑痴乎

上述左图中,音量滑块位置与声音振幅为线性增长关系,右图是我们人耳感受的音量大小与滑块位置关系。可知,在左侧移动相同距离的滑块,感知到的声音变化范围很大,在右侧接近声音最大值移动相同距离滑块,感知到的声音大小变化就很小了。

2)音量滑块与声音振幅大小对数关系变化。
PCM音量控制(高级篇) - 第3张  | 剑痴乎
左图中,音量滑块位置与声音振幅对数关系增长。右图中无论哪个位置,移动相同距离滑块,感知到的声音变化都是相同的。

需要说明的是滑块最小位置只是接近0,不能为0,因为对数函数y=logx中x>0。

windows系统中音量滑块控制的声音变化范围

在最新版的windows系统中,音量滑块控制的声音变化范围也是96分贝。如下表所示,是不同版本windows的音量范围以及默认音量值。
PCM音量控制(高级篇) - 第4张  | 剑痴乎

从表中我们可以看到默认值都是0分贝,根据分贝公式:dB = 20 * log(A1 / A2),当A1,A2相等时,db为0。

程序实现

了解了分贝以及Windows中音量滑块是在哪个范围变化,我们的程序实现起来也很简单。

这里我们规定音量大小变化范围也是96分贝,每个声音采样大小为16位。对于分贝公式:dB = 20 * log(A1 / A2),我们取参考声音振幅A2为原始声音振幅,A1为调节后的声音振幅大小。可知调节后的声音:

看过一篇文章说理想的声音调节步长最好是2db,对于96db范围,我们按2db步长进行分割,可以分成48份,这样我们得到的声音变化为[-96db,-94db,-92db,…-4db.-2db,0db],假设我们要调节一半音量大小,也就是-48db,由上述公式可知:调节后音量A1大小:

程序伪代码如下,具体db大小与滑块位置对应关系的实现这里就不写出:

最后编辑:
作者:Jeff
Avatar
管理员——代码为剑,如痴如醉

17 Responses to PCM音量控制(高级篇)

  1. Avatar Vincenzo says:
    Google Chrome 48.0.2564.97 Google Chrome 48.0.2564.97 Windows 7 x64 Edition Windows 7 x64 Edition

    可以算音量大小吗

  2. Avatar parcool says:
    Google Chrome 62.0.3202.94 Google Chrome 62.0.3202.94 Mac OS X  10.12.6 Mac OS X 10.12.6

    不知道为什么,会有杂音。。。。

    • Avatar Jianchihu says:
      Google Chrome 62.0.3202.94 Google Chrome 62.0.3202.94 Windows 10 x64 Edition Windows 10 x64 Edition

      调整前就有杂音还是调整后?

      • Avatar He.ToSion says:
        Google Chrome 59.0.3071.9 Google Chrome 59.0.3071.9 Windows 7 x64 Edition Windows 7 x64 Edition

        调整后

        • Avatar Jianchihu says:
          Google Chrome 62.0.3202.94 Google Chrome 62.0.3202.94 Windows 10 x64 Edition Windows 10 x64 Edition

          话说调整音量并做溢出处理并不会引入噪音,我怀疑还是你的原始数据有问题。看下你pcm数据格式是否转换正确,比如:整形非整形数据转换,不同精度数据转换,字节序等等。这些都可能造成部分音频数据丢失,从而引入噪音。

  3. Avatar sens says:
    Firefox 61.0 Firefox 61.0 Windows 10 x64 Edition Windows 10 x64 Edition

    你好,我看了几遍文章,还是没明白最后代码中的db该怎么计算获得。比如我想将当前PCM数据的音量调小到80%(降低20%),按照以前的方式就是 pcmval = pcm[ctr] * 80%。按照您这种方式应该怎么把这个80%转换成合理的multiplier呐?

    • Avatar Jianchihu says:
      Google Chrome 67.0.3396.79 Google Chrome 67.0.3396.79 Windows 10 x64 Edition Windows 10 x64 Edition

      db这个单位是相对值,得有一个参考,对于公式:dB = 20 * log(A1 / A2),我们取参考声音振幅A2为原始声音振幅,A1为调节后的声音振幅大小。按你的说法,A2 = pcm[ctr],A1 = pcmval 。

       

      • Avatar sens says:
        Firefox 61.0 Firefox 61.0 Windows 10 x64 Edition Windows 10 x64 Edition

        是的,这个理解了。但是滑块怎么和db关联起来呐?您最后给出了:

        float multiplier = pow(10, db/20);。比如说我滑块的取值范围是M=[0,100],0表示静音,100表示原始声音大小。这个db该怎么跟随滑块的变化而变化呐?

        • Avatar Jianchihu says:
          Google Chrome 67.0.3396.99 Google Chrome 67.0.3396.99 Windows 10 x64 Edition Windows 10 x64 Edition

          1)我们声音取值范围一般是-96db~0db(参考windows系统设计),0db就是原始声音大小,-96db是声音最小

          2)滑块取值范围0~100,0就对应-96db,100对应0db,其他滑块值对应的db值按线性关系类推

          3)套入公式:db = 20 * log(pcmval  / pcm[ctr]),其中db取值-96~0db,其他的你应该明白了吧

          • Avatar sens says:
            Firefox 61.0 Firefox 61.0 Windows 10 x64 Edition Windows 10 x64 Edition

            谢谢你的解释,大致明白了。但是我发现这样子计算的变化弧度还是有些问题。比如我想把音量调到70%(在原来的基础上降低30%):  

            db = -96 * (1 – 0.7) ≈ -29

            multiplier = pow(10, db / 20) = pow(10, -29 / 20) ≈ 0.03

            也就是音量只想减小到70%,但是通过上面的计算,振幅则只有原来的3%了。这个减小的幅度太大了吧。这样小于60%后基本就听不到声音了。

            • Avatar Jeff says:
              Google Chrome 72.0.3626.109 Google Chrome 72.0.3626.109 Windows 10 x64 Edition Windows 10 x64 Edition

              我说的滑块值对应的db值按线性处理只是个参考,你可以通过计算multiplier大小得到合适的对应关系

  4. Pingback: PCM音量控制 | Jianchihu

  5. Pingback: 【Android】pcm音频数据调节音量大小 - 算法网

  6. Pingback: PCM音量控制 | 剑痴乎

  7. Avatar 廖生 says:
    Microsoft Edge 18.17763 Microsoft Edge 18.17763 Windows 10 x64 Edition Windows 10 x64 Edition

    如果需要将已有的pcm数据做增幅,需要如何处理呢?

留下一个回复

你的email不会被公开。

This site uses Akismet to reduce spam. Learn how your comment data is processed.