Unity 中 AudioMixer 的音量调节与分贝(DB)之间的关系
问题描述项目中的声音系统没有使用第三方的声音库,而是走的 Unity 原生的那一套 AudioSource。然后策划提出了需求:要求用户可以调节音量的大小。于是我在项目中加入了混音器(AudioMixer),让所有的 AudioSource 的 OutPut 指向这个 AudioMixer 来实现统一的声音管理。UI 上调节声音的 Slider (0.0~1.0] 则映射到了 AudioMixer 的 Volume 参数 (-80DB~0DB] 来实现音量调节。
但是很快测试发来了反馈:这个 Slider,在调节到 50% 的时候,就几乎听不到声音了。
问题分析
在查阅了一些资料后得知,计算机里传统上对声音音量的调节,并不与分贝成线性关系,而是而是遵循一个 log 函数。
在详细理解这句话之前,先要搞明白分贝的定义。
分贝(Decibel) 实际上不是一个单位,而是表示两个相同单位的数量之间的比例,常用 db 表示。分贝的分(deci-)指十分之一,所以它表示的是十分之一个贝(Bel),贝常用 B 表示。
1B = 10db
所以单独的分贝或贝并不能指代具体的含义,因为它只是一个比例,具体的含义要看它表示的是谁的比例。
分贝和贝常用于表示功率之比和场量之比。1B 的两个功率量的比值为10:1,1B 的两个场量的比值为\sqrt{10}:1。常用的功率有能量密度、发光强度;常用的场量有电压、电流、声压、速度等。所以分贝和贝的计算,依赖于具体是场量还是功率而有所不同。
考虑功率时,这是通过把测量值与参考量值之比计算基于 10 的对数,再乘以 10。因此功率值P1与另一个功率值P0之比用分贝表示为L_{dB}。
L_{db} = 10 \log_{10}{\left(\frac{P_0}{P_1}\right)}
考虑到场量的幅值时,通常使用 A1(度量到的幅值)的平方与 A0(参考幅值)的平方之比。这是因为对于大多数应用,功率与幅值的平方成比例,并期望对同一应用采取功率计算的分贝与用场量的幅值计算的分贝相等。
L_{db} = 10 \log_{10}{\left(\frac{A_0^2}{A_1^2}\right)}\\ = 20 \log_{10}{\left(\frac{A_0}{A_1}\right)}
搞清楚了分贝是什么之后,接下来回到我们最开始的问题。
在声学中,声音的强度定义为声压(Acoustic Pressure),声压的单位为帕斯卡(Pa),这是一个场量。计算分贝值时采用 20 微帕斯卡为参考值,这一参考值是人类对声音能够感知的阈值下限。因此使用声压计算分贝时使用下述版本的公式,其中的P_{ref}就是标准参考声压值 20 微帕。
L_{db} = 20 \log_{10}{\left(\frac{P_{rms}}{P_{ref}}\right)}
这样算出来的分贝值被叫做声压级(Sound Pressure Level),缩写为 SPL。我们一般用分贝表示声音大小的时侯,指代的就是这个声压级,即 dB(SPL)。
在计算机里,传统上对声音音量的调节,一般是对音量的减益,即将原始音量减小多少。比如 Unity 这里的 AudioMixer,显示的音量区间就是[-80db(SPL), 20db(SPL)],其中[-80db(SPL), 0db(SPL)]就是最常用的减益的部分,一般滑动条调节的就是这个范围;(0db(SPL), 20db(SPL)]则是不常用的增益部分。
但是实际调节中,并不是将滑动条的值(即(0.0, 1.0]的范围,注意左边是开区间)线性映射到声压级 db(SPL) 上,而是去调节\left(\frac{P_{rms}}{P_{ref}}\right)这个比值。
此处推测一下,在这里的参考值P_{ref}应该指的是音源的原始值,P_{rms}指的应该是我们要调节到的目标值,因为是减益,所以比值在(0.0, 1.0]的范围。
到这里已经差不多足够解决代码中的问题了,想进一步研究可阅读参考链接部分。
解决问题
所以代码应该这么写,添加如下重映射函数。注意自变量 x 不能小于等于 0,这里加一个简单的 Magic Number 就足够了。
private float Remap01ToDB(float x) {
if (x <= 0.0f) x = 0.0001f;
return Mathf.Log10(x) * 20.0f;
}
界面上滑块的 Slider 的值首先要通过这个函数,然后重映射后,其返回值再作为audioMixer.SetFloat的参数即可解决问题。
参考链接
[*]https://zh.wikipedia.org/zh-cn/分貝
[*]https://zh.wikipedia.org/zh-cn/声压
[*]https://www.bilibili.com/video/BV1pP41137H8/?vd_source=5feccac55678f60d2348199bb99e3d37
[*]https://forum.unity.com/threads/changing-audio-mixer-group-volume-with-ui-slider.297884/
[*]https://johnleonardfrench.com/the-right-way-to-make-a-volume-slider-in-unity-using-logarithmic-conversion/
[*]https://www.zhihu.com/question/393959990
[*]https://zhuanlan.zhihu.com/p/22821588
本文使用 Zhihu On VSCode 创作并发布
页:
[1]