• Android 4.4 音量调节流程分析(二)


      之前在Android 4.4 音量调节流程分析(一)里已经有简单的分析音量控制的流程,今天想接着继续分析下音量大小计算的方法。对于任一播放文件而言其本身都有着固定大小的音量Volume_Max,而在AudioPolicyManagerBase.cpp文件中音量调节可以理解为在Volume_Max的基础上乘以系数κ(0≤κ≤1)。

      现在对AudioPolicyManagerBase.cpp中volIndexToAmpl函数做具体分析,volIndexToAmpl的函数定义如下:

     1 float AudioPolicyManagerBase::volIndexToAmpl(audio_devices_t device, const StreamDescriptor& streamDesc,
     2         int indexInUi)
     3 {
     4     device_category deviceCategory = getDeviceCategory(device);
     5     const VolumeCurvePoint *curve = streamDesc.mVolumeCurve[deviceCategory];
     6   
     7     // the volume index in the UI is relative to the min and max volume indices for this stream type
     8     int nbSteps = 1 + curve[VOLMAX].mIndex -
     9             curve[VOLMIN].mIndex;
    10     int volIdx = (nbSteps * (indexInUi - streamDesc.mIndexMin)) /
    11             (streamDesc.mIndexMax - streamDesc.mIndexMin);
    12 
    13     // find what part of the curve this index volume belongs to, or if it's out of bounds
    14     int segment = 0;
    15     if (volIdx < curve[VOLMIN].mIndex) {         // out of bounds
    16         return 0.0f;
    17     } else if (volIdx < curve[VOLKNEE1].mIndex) {
    18         segment = 0;
    19     } else if (volIdx < curve[VOLKNEE2].mIndex) {
    20         segment = 1;
    21     } else if (volIdx <= curve[VOLMAX].mIndex) {
    22         segment = 2;
    23     } else {                                                               // out of bounds
    24         return 1.0f;
    25     }
    26 
    27     // linear interpolation in the attenuation table in dB
    28     float decibels = curve[segment].mDBAttenuation +
    29             ((float)(volIdx - curve[segment].mIndex)) *
    30                 ( (curve[segment+1].mDBAttenuation -
    31                         curve[segment].mDBAttenuation) /
    32                     ((float)(curve[segment+1].mIndex -
    33                             curve[segment].mIndex)) );
    34 
    35     float amplification = exp( decibels * 0.115129f); // exp( dB * ln(10) / 20 )
    36 
    37     return amplification;
    38 }

      在该段代码内,主要是获取以下的7个变量值:

      1.deviceCategory:Android系统中设备种类有如下三种,即DEVICE_CATEGORY_HEADSET,DEVICE_CATEGORY_SPEAKER & DEVICE_CATEGORY_EARPIECE。若当前使用Speaker播放音频流时,则deviceCategory即对应DEVICE_CATEGORY_SPEAKER;

      

      2.curve:音量曲线是由Audio_Stream & device_Category两者共同决定,所有匹配类型都可以在sVolumeProfiles矩阵中获得,以Audio_Stream = AUDIO_STREAM_MUSIC & device_Category = DEVICE_CATEGORY_SPEAKER为例,则其对应的音量曲线为 sSpeakerMediaVolumeCurve;

    sSpeakerMediaVolumeCurve:(以该音量曲线为例作数值计算)

    1 const AudioPolicyManagerBase::VolumeCurvePoint
    2     AudioPolicyManagerBase::sSpeakerMediaVolumeCurve[AudioPolicyManagerBase::VOLCNT] = {
    3     {1, -59.1f}, {20, -48.3f}, {60, -24.4f}, {100, 0.0f}
    4 };

      从sSpeakerMediaVolumeCurve数组可以知道是由4个点来将音量曲线分为4个部分,分别为1~20、20~60、60~100。其中每个点中参数含义为:

    class VolumeCurvePoint
    {
    public:
        int mIndex;//百分制下标
        float mDBAttenuation;//衰减
    };

      

      3.nbSteps:为了避免计算时出现循环小数,系统中将UI界面VolumeIndex转化为0~100,以sSpeakerMediaVolumeCurve为例,curve[VOLMAX].mIndex = 100,curve[VOLMIN].mIndex = 1,所以nbSteps = 1 + 100 -1 = 100;

      4.volIdx:volIdx的求解过程其实就是将UI界面的音量Index转化为百进制的过程,其中AudioStream对应的indexInUi_Max可以在AudioService.java中获得,STREAM_MUSIC对应数值为15,故streamDesc.mIndexMax = 15,streamDesc.mIndexMin = 0,则volIdx = (20/3)*indexInUi

    //AudioService.java
    /** @hide Maximum volume index values for audio streams */
    private static final int[] MAX_STREAM_VOLUME = new int[] {
         5,  // STREAM_VOICE_CALL
         7,  // STREAM_SYSTEM
         7,  // STREAM_RING
         15, // STREAM_MUSIC
         7,  // STREAM_ALARM
         7,  // STREAM_NOTIFICATION
         15, // STREAM_BLUETOOTH_SCO
         7,  // STREAM_SYSTEM_ENFORCED
         15, // STREAM_DTMF
         15  // STREAM_TTS
    };

      

      5.segment:是用来确定UI音量界面上的VolumeIndex转化为百进制处于哪一个区间内。

      6.decibels:VolumeIndex对应的音量衰减,单位为dB。其计算公式如下图所示:

                        

      若想实现speaker每音阶之间的衰减差为M(dB),其计算方法就是计算decibels_Index_N & decibels_Index_(N+1)之间的差值。为了方便计算,可以默认N & N+1属于同一segment,这样

                                                          

      因为curve[VOLMAX].mDBAttenuation一般为0,即不衰减状态(当然也有可能为负数,但不管怎样,curve[VOLMAX].mDBAttenuation是最容易确定的值),所以一般计算是从segment = 2开始计算,这样在60~100区间内Δdecibels的值就为:

      Δdecibels = (20/3)*((0 - curve[2].mDBAttenuation)/(100 - 60)) = -(curve[2].mDBAttenuation/6)

      令Δdecibels = M,则curve[2].mDBAttenuation = -6M,依次类推curve[1].mDBAttenuation = -12M,curve[0].mDBAttenuation = -15M。

      7.amplification:放大/缩小倍数。将求得的decibels带入公式就可以直接求到,没有什么特别要说的。

      总结:该篇文章以sSpeakerMediaVolumeCurve为例,描述了音量衰减值的计算过程。其它音量曲线调节可以按照该方法同样实现。

  • 相关阅读:
    【selenium学习高级篇 -31】Jenkins中Project的相关配置
    【selenium学习高级篇 -30】Jenkins新建一个Project
    【selenium学习高级篇 -29】Jenkins的简单介绍和安装
    【selenium学习中级篇 -28】封装一个日志类
    【selenium学习中级篇 -27】Python读取配置文件
    JVM类加载机制
    Java虚拟机JVM及垃圾回收机制
    数组在内存中的分配
    wait 和 sleep 的区别
    Cloneable 接口实现原理
  • 原文地址:https://www.cnblogs.com/Peter-Chen/p/3859498.html
Copyright © 2020-2023  润新知