在Android系统中,音量曲线通常指的是将用户的音量等级(比如0到15级)映射到实际的硬件增益或分贝值的曲线。
1. 音量曲线加载
上一节分析,解析Engine文件时最终调用到loadAudioPolicyEngineConfig() 方法,该方法在加载Engine文件之前,也会加载解析音量曲线文件,该文件在开发板上位于/vendor/etc/audio_policy_volumes.xml或/system/etc,厂商也可以根据自己的需求进行扩展。在代码中路径为: /frameworks/av/services/audiopolicy/config/。
以下是与该xml文件中元素对应的对象
2.音量曲线分析
文件将在audio_policy_configuation.xml中引用:
<!-- Volume section:
IMPORTANT NOTE: Volume tables have been moved to engine configuration.
Keep it here for legacy.
Engine will fallback on these files if none are provided by engine.
-->
<xi:include href="audio_policy_volumes.xml"/>
<xi:include href="default_volume_tables.xml"/>
<!-- End of Volume section -->
在audio_policy_volumes.xml中,规定了音频流类型(stream)、输出设备(deviceCategory)和音量曲线(ref)的关系,在default_volume_tables.xml中规定了具体的音量曲线的值
audio_policy_volumes.xml:
<volumes>
<volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_HEADSET"
ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
<volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_SPEAKER"
ref="DEFAULT_DEVICE_CATEGORY_SPEAKER_VOLUME_CURVE"/>
<volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_EARPIECE"
ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
<volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA"
ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
...
</volumes>
default_volume_tables.xml:
<volumes>
<reference name="DEFAULT_MEDIA_VOLUME_CURVE">
<!-- Default Media reference Volume Curve -->
<point>1,-5800</point>
<point>20,-4000</point>
<point>60,-1700</point>
<point>100,0</point>
</reference>
...
</volumes>
例如:DEFAULT_MEDIA_VOLUME_CURVE曲线上的(index、db)值。定义的index范围是1到100, 而db的范围为-5800 到0。音量等级分成4段为100、60、20、1就是音量百分比;0,-1700,-4000,-5800就是对应百分比时衰减的音量,代表衰减-17db,-40db,-58db。
其中,point表示<等级,分贝值>,分贝值单位为 厘贝(cB)(1 dB = 100 cB),<point>20,-4000</point>表示第2等级20对应的音量为-40db。
在audio_policy_volume.xml中,引用DEFAULT_MEDIA_VOLUME_CURVE曲线的device有headset,speaker,earpiece等。
用户的音量等级通常为0~15级,如何通过传入的用户音量级别来查找音量的位置,需要两个步骤。
(1)根据用户的index,找到音量曲线的index。
根据用户传入的index(0~15),找到对应音量曲线(1,100)的位置,加入传入的为x,对应的y,那么x/(15-0)=y/(100-1), 例如用户配置了音量为7,那么对应音量曲线的index为46。
(2)寻找曲线index对应的分贝
46在区间【20~60】,这个区间对应的db区间是【-4000,-1700】。先求这个区间一个index对应多少db 将总的index(60-20)除于总的db(-1700 - (-4000)) 为单位index对应的db。那46对应的有多少index,46对应为 46-20。 将这两者相乘就是46对应在这个区间内的db值, 加上起始的-4000就是最终的db。
db就在这个区间里面算。 所求的db = -4000 + (((- 1700 - (-4000))/(60 -20) x(46 -20)) = -2505。
也等比例计算的一个方式。 相对于一个个区间是独立。起始点是最靠近的上一个区间的index,然后计算区间内一个index对应多少db。传递进去的index相对于起始index的值。
3.调试工具与命令
# 查看当前音量曲线
adb shell dumpsys audio | grep -A 15 "Volume curves"
# 示例输出:
Volume curves for stream MUSIC:
Speaker: (0%, -60dB) -> (50%, -30dB) -> (100%, 0dB)
Headphones: (0%, -55dB) -> (100%, -5dB)
# 强制重载配置
adb shell cmd media.audio_policy reload-volumes
# 测试音量转换
adb shell cmd media.audio_policy volume-to-db --stream MUSIC --device speaker --level 70
# 返回: -15.2 dB
4.常见问题解决方案
问题现象 |
原因分析 |
解决方案 |
音量调节不灵敏 |
曲线点过少 |
增加中间点(如每10%一个点) |
最大音量太小 |
maxDb限制过低 |
调整<point max="值"> |
蓝牙设备音量突变 |
曲线与手机不匹配 |
为蓝牙设备单独定义曲线 |
插入耳机后音量过大 |
不同设备曲线差异过大 |
统一各设备0%和100%的dB基准 |
重启后音量重置 |
持久化配置错误 |
检查/data/system/audio目录权限 |