我是靠谱客的博主 丰富航空,最近开发中收集的这篇文章主要介绍PCM音量控制(高级篇),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

声学中的分贝

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

分贝声音变化范围

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

 

1

dB = 20 * log(A1 / A2)

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

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

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

了解了分贝的相关概念我们通过图表说下为什么要用对数关系描述声音大小。
1)音量滑块与声音增幅大小线性变化。

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

2)音量滑块与声音振幅大小对数关系变化。

左图中,音量滑块位置与声音振幅对数关系增长。右图中无论哪个位置,移动相同距离滑块,感知到的声音变化都是相同的。

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

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

在最新版的windows系统中,音量滑块控制的声音变化范围也是96分贝。如下表所示,是不同版本windows的音量范围以及默认音量值。
windows系统音量范围

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

程序实现

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

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

 

1

A1 = A2 * pow(10 , db/20)

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

 

1

A1 = A2 * pow(10 , -48/20)

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

 

1

2

3

4

5

6

7

8

9

10

11

12

13

int16_t pcm[1024] = read in some pcm data;

int32_t pcmval;

float multiplier = pow(10,db/20);

for (ctr = 0; ctr < 1024; ctr++) {

    pcmval = pcm[ctr] * multiplier;

    if (pcmval < 32767 && pcmval > -32768) {

        pcm[ctr] = pcmval

    } else if (pcmval > 32767) {

        pcm[ctr] = 32767;

    } else if (pcmval < -32768) {

        pcm[ctr] = -32768;

    }

}

windows音量滑块和db之间的联系

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

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

3)套入公式:db = 20 * log(pcmval  / pcm[ctr]),其中db取值-96~0db

在windows中调节滑块,音量并不是根据dB线性变化的,以总步进数为100为例,总步进数越小,每个步进的dB数要大,总步进数接近100的时候,每个步进数越来越小。

这些控件非常适合显示音量滑块的Windows应用程序。对于与音频音量调节控件绑定的音量滑块,滑块位置的每次变化都会导致感知响度的变化,该变化与滑块行进的距离成正比。对于特定的行驶距离,无论滑块移动范围的下部,上部还是中间发生移动,感知响度增加或减小的量都大致相同。感知的响度大约随音频信号功率的对数线性变化。

术语音频锥度最初是指电位计中电阻元件的锥形形状,该电位计用作音频电子设备中的音量控制。锥形音频电阻元件在零音量位置最宽,在最大音量位置最窄。电位器控制设备通过扬声器播放的音频信号的电压电平。锥度设计为在电位计抽头的位置和扬声器的响度之间产生近似线性的关系。抽头位置与扬声器电压之间的关系是非线性的。

相反,具有线性锥度的电阻元件在电位计抽头的运动范围内具有均匀的宽度。结果,扬声器上的电压随抽头位置线性变化。雨刮器位置和响度之间的关系是非线性的。

同样,显示音量滑块的Windows应用程序定义了滑块位置和扬声器上的输出信号电平之间的关系。该关系实际上可以是线性锥形或音频锥形。

下图显示了线性渐变音量控制的滑块位置到输出电压以及所感知响度的映射。

线性锥形音量控制的输出图

在上图的左侧,随着音量滑块从其最小位置(标记为Min)移动到最大位置(标记为Max),音频数模转换器(DAC)的输出电压电平线性增加。垂直轴上的标签V FS代表满量程DAC输出电压。

但是,如上图的右侧所示,感知到的响度大约随音频信号功率的对数而变化。因此,滑块在最小设置附近的间隔上的移动导致感知响度的较大变化,但是滑块在最大设置附近的相同宽度的间隔上的移动导致感知响度的较小的变化。

在上图的右侧,垂直轴上的响度以分贝(dB)为单位,相对于满量程功率设置(0分贝)。响度曲线在负无穷大处与垂直轴相交,但是曲线中从0分贝到–96分贝的部分仅出现在图中。仅显示曲线的这一部分的决定在某种程度上是任意的,但是–96分贝代表了16位DAC相对于满量程功率的倒数第二个最低输出电平的功率。该值计算为20 。log₁₀(1/65535)。

由于上图中最小设置附近的滑块位置发生细微变化会导致响度发生较大变化,因此用户可能会发现难以控制该区域的音量。相对较小的滑块移动可以将音量推到高于或低于所需水平。改进的音量控制将在滑块位置和响度之间提供更线性的关系。

下图显示了滑块位置到输出电压以及感知到的音量变化的映射。

音频音量控制的输出图

如上图的右侧所示,感知的响度随滑块位置的变化近似线性变化。为此,DAC电压必须随位置非线性变化,如图表左侧所示。当滑块从最大设置向左移动时,曲线渐近接近0伏。最小滑块位置的电压很小,但可能不完全为零。

参考

[2]https://blog.jianchihu.net/pcm-vol-control-advance.html

[1] Audio-Tapered Volume Controls.https://docs.microsoft.com/en-us/windows/win32/coreaudio/audio-tapered-volume-controls

 

最后

以上就是丰富航空为你收集整理的PCM音量控制(高级篇)的全部内容,希望文章能够帮你解决PCM音量控制(高级篇)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(42)

评论列表共有 0 条评论

立即
投稿
返回
顶部