[RK3288][Android6.0] Audio的音量计算过程小结

Platform: Rockchip
OS: Android 6.0
Kernel: 3.10.92


AudioPolicyManager::checkAndSetVolume -> AudioPolicyManager.cpp
  AudioPolicyManager::computeVolume ->
    mEngine->volIndexToDb ->
      Engine::volIndexToDb -> frameworks/av/services/audiopolicy/enginedefault/Engine.cpp
        Gains::volIndexToDb -> Gains.cpp
  outputDesc->setVolume ->
    SwAudioOutputDescriptor::setVolume ->
      Volume::DbToAmpl

index -> db:
volIndexToDb()会将index转换成db.
float Gains::volIndexToDb(Volume::device_category deviceCategory,
                          const StreamDescriptor& streamDesc,
                          int indexInUi)
{
    //对应的是Gains::sVolumeProfiles列表,假设本例是改变music stream的音量,用的是speaker,
    //那么就是Gains::sSpeakerMediaVolumeCurve,后面会解释它的由来,见说明一
    //Gains::sSpeakerMediaVolumeCurve[Volume::VOLCNT] = {
    //{1, -56.0f}, {20, -34.0f}, {60, -11.0f}, {100, 0.0f}
    //};

    const VolumeCurvePoint *curve = streamDesc.getVolumeCurvePoint(deviceCategory);

    // the volume index in the UI is relative to the min and max volume indices for this stream type
    //nbssteps = 1 + 100 - 1 = 100
    int nbSteps = 1 + curve[Volume::VOLMAX].mIndex -
            curve[Volume::VOLMIN].mIndex;
    //假设AudioService设置的index是1
    //volIdx = (100 * (1 - 0)) / (15 - 0) = 6
    //getVolumeIndexMin()和getVolumeIndexMax()的初始化见后面说明二分析。
    //公式就是: volIdx = (20 / 3) * indexInUi
    //计算的物理意义表示目前index处于总index中的哪一点
    int volIdx = (nbSteps * (indexInUi - streamDesc.getVolumeIndexMin())) /
            (streamDesc.getVolumeIndexMax() - streamDesc.getVolumeIndexMin());

    // find what part of the curve this index volume belongs to, or if it's out of bounds
    int segment = 0;
    if (volIdx < curve[Volume::VOLMIN].mIndex) {         // out of bounds
        //如果算出来比设置的最小index还小,那么直接返回固定值。
        return VOLUME_MIN_DB;
    } else if (volIdx < curve[Volume::VOLKNEE1].mIndex) {
        //6 < 20, 会落入这个区间
        segment = 0;
    } else if (volIdx < curve[Volume::VOLKNEE2].mIndex) {
        segment = 1;
    } else if (volIdx <= curve[Volume::VOLMAX].mIndex) {
        segment = 2;
    } else {                                                               // out of bounds
        return 0.0f;
    }

    // linear interpolation in the attenuation table in dB
    //decibels = (-34.0f) + (6 - 1) * (((-34.0f) -(-56.0f)) / ((20 -1)))
    //其实这个公式就是计算segment到segment+1区间为一段,算出一个平均值,然后以
    //curve[segment].mDBAttenuation作为基值算出最终的db值
    float decibels = curve[segment].mDBAttenuation +
            ((float)(volIdx - curve[segment].mIndex)) *
                ( (curve[segment+1].mDBAttenuation -
                        curve[segment].mDBAttenuation) /
                    ((float)(curve[segment+1].mIndex -
                            curve[segment].mIndex)) );
......
    return decibels;
}

说明一

变量curve的由来:

const VolumeCurvePoint *getVolumeCurvePoint(Volume::device_category deviceCategory) const
{
return mVolumeCurve[deviceCategory];
}

initializeVolumeCurves ->
  streams.setVolumeCurvePoint ->  //保存sVolumeProfiles变量
    StreamDescriptorCollection::setVolumeCurvePoint ->
      StreamDescriptor::setVolumeCurvePoint ->
        mVolumeCurve[deviceCategory] = point

sVolumeProfiles:

const VolumeCurvePoint *Gains::sVolumeProfiles[AUDIO_STREAM_CNT]
                                                  [Volume::DEVICE_CATEGORY_CNT] = {
......
    { // AUDIO_STREAM_MUSIC
        Gains::sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_HEADSET
        Gains::sSpeakerMediaVolumeCurve, // DEVICE_CATEGORY_SPEAKER
        Gains::sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_EARPIECE
        Gains::sDefaultMediaVolumeCurve  // DEVICE_CATEGORY_EXT_MEDIA
    },
......
};
sSpeakerMediaVolumeCurve:
const VolumeCurvePoint Gains::sSpeakerMediaVolumeCurve[Volume::VOLCNT] = {
    {1, -56.0f}, {20, -34.0f}, {60, -11.0f}, {100, 0.0f}
};

说明二
streamDesc.getVolumeIndexMin()和streamDesc.getVolumeIndexMax():
其实就是上层设置的音量等级,即UI能看到的设置级数。在AudioService.java中:

/** Maximum volume index values for audio streams */
private static int[] MAX_STREAM_VOLUME = new int[] {
    //Kris, 20170105, Change from 5 to 15.
    15,  // STREAM_VOICE_CALL
    7,  // STREAM_SYSTEM
    7,  // STREAM_RING
    15, // STREAM_MUSIC
    //Kris, 20170105, Change from 5 to 15.
    15,  // STREAM_ALARM
    7,  // STREAM_NOTIFICATION
    15, // STREAM_BLUETOOTH_SCO
    7,  // STREAM_SYSTEM_ENFORCED
    15, // STREAM_DTMF
    15  // STREAM_TTS
};
/** Minimum volume index values for audio streams */
private static int[] MIN_STREAM_VOLUME = new int[] {
    1,  // STREAM_VOICE_CALL
    0,  // STREAM_SYSTEM
    0,  // STREAM_RING
    0,  // STREAM_MUSIC
    0,  // STREAM_ALARM
    0,  // STREAM_NOTIFICATION
    1,  // STREAM_BLUETOOTH_SCO
    0,  // STREAM_SYSTEM_ENFORCED
    0,  // STREAM_DTMF
    0   // STREAM_TTS
};

AudioService创建stream state时会设置下去

VolumeStreamState -> AudioService.java

  AudioSystem.initStreamVolume ->
    AudioSystem::initStreamVolume ->
      aps->initStreamVolume ->
        AudioPolicyService::initStreamVolume ->
          mAudioPolicyManager->initStreamVolume ->
            AudioPolicyManager::initStreamVolume ->
              mEngine->initStreamVolume ->
                Engine::initStreamVolume ->
                  mApmObserver->getStreamDescriptors().setVolumeIndexMin ->
                    StreamDescriptorCollection::setVolumeIndexMin
                  mApmObserver->getStreamDescriptors().setVolumeIndexMax ->
                    StreamDescriptorCollection::setVolumeIndexMax

                
db -> ampl:
static inline float DbToAmpl(float decibels)
{
if (decibels <= VOLUME_MIN_DB) {
return 0.0f;
}
//公式在注释里已经有了,转换成幅值
return exp(decibels * 0.115129f); // exp( dB * ln(10) / 20 )
}       

你可能感兴趣的:(子类__Audio)