Android音量控制


背景

  • Platform: RK3399
  • OS: Android7.1.2
  • Kernel: v4.4.103

系统输出音量

总输出音量 = Android系统软件音量 * 音频Codec硬件音量**
**音频Codec硬件音量 = 音频Codec-DAC音量(数字音量) * 音频Codec-通道音量(AP模拟音量)

Android系统音量(数字音量) = stream Volume * master Volume * track Volume
注:
stream 音量: 系统控制音量等级,系统针对不同的stream type和不同输出device,有不同的音量level,韦伯定律(可展开,心理,情侣买礼物,金融等,)
Track volume: 通过AudioTrack.setVolume来设置,取值为0~1.0
master Volume: 音效

Android音量计算流程

注:这里所说的音量是上面所说的stream Volume流音量
整个流程即是数字音量增益调节的流程,纯数字实现,与底层音频codec无关.
整个流程大致分为以下2大步

AudioPolicyManager::checkAndSetVolume -> frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
  AudioPolicyManager::computeVolume ->
    mEngine->volIndexToDb ->
       Gains::volIndexToDb -> frameworks/av/services/audiopolicy/common/managerdefinitions/src/Gains.cpp
  outputDesc->setVolume ->
    SwAudioOutputDescriptor::setVolume -> frameworks/av/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
      Volume::DbToAmpl -> frameworks/av/services/audiopolicy/common/include/Volume.h

index -> db:

frameworks/av/services/audiopolicy/common/managerdefinitions/src/Gains.cpp
volIndexToDb():index转换成db,主要是依据音量曲线.
index为UI上设置的等级

float Gains::volIndexToDb(const VolumeCurvePoint *curve, int indexMin, int indexMax, int indexInUi)
{
    ///curve为对应流类型的音量曲线,见下面的说明1 
    ///indexMin,indexMax为UI音量等级的最小值和最大值,见下面的说明2

    // the volume index in the UI is relative to the min and max volume indices for this stream type
    int nbSteps = 1 + curve[Volume::VOLMAX].mIndex - curve[Volume::VOLMIN].mIndex;

    int volIdx = (nbSteps * (indexInUi - indexMin)) / (indexMax - indexMin);

    // 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
        return VOLUME_MIN_DB;
    } else if (volIdx < curve[Volume::VOLKNEE1].mIndex) {
        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
    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;
}

说明1:curve的由来
getVolumeCurvePoint()函数获得,即音量曲线

getVolumeCurvePoint()  frameworks/av/services/audiopolicy/common/managerdefinitions/src/StreamDescriptor.cpp
    -> mVolumeCurve 
        -> sVolumeProfiles
            ->sSpeakerMediaVolumeCurve //对应响应的流类型
            {1, -56.0f}, {20, -34.0f}, {60, -11.0f}, {100, 0.0f}

说明2:UI音量等级的最小值和最大值
streamDesc.getVolumeIndexMin()streamDesc.getVolumeIndexMax()获得.
而默认最小值和最大值由MIN_STREAM_VOLUMEMAX_STREAM_VOLUME确定,所在文件为(frameworks/base/services/core/java/com/android/server/audio/AudioService.java),所以修改这里的MAX_STREAM_VOLUME可以修改对应的音量等级
调整默认音量:
frameworks/base/media/java/android/media/AudioSystem.java -> DEFAULT_STREAM_VOLUME

db -> ampl:

DbToAmpl():db转换成振幅,转换公式为exp( dB * ln(10) / 20 ),即是韦伯定理的运用.

static inline float DbToAmpl(float decibels)
{
    if (decibels <= VOLUME_MIN_DB) {
        return 0.0f;
    }
    return exp( decibels * 0.115129f); // exp( dB * ln(10) / 20 )
}

扩展

音量统一:
frameworks/base/services/core/java/com/android/server/audio/AudioService.java
修改STREAM_VOLUME_ALIAS_DEFAULT数组改成跟STREAM_VOLUME_ALIAS_TELEVISION数组内容一样,所有音量条都属于music分组

private final int[] STREAM_VOLUME_ALIAS_DEFAULT = new int[] {
	AudioSystem.STREAM_MUSIC,       // STREAM_VOICE_CALL
	AudioSystem.STREAM_MUSIC,       // STREAM_SYSTEM
	AudioSystem.STREAM_MUSIC,       // STREAM_RING
	AudioSystem.STREAM_MUSIC,       // STREAM_MUSIC
	AudioSystem.STREAM_MUSIC,       // STREAM_ALARM
	AudioSystem.STREAM_MUSIC,       // STREAM_NOTIFICATION
	AudioSystem.STREAM_MUSIC,       // STREAM_BLUETOOTH_SCO
	AudioSystem.STREAM_MUSIC,       // STREAM_SYSTEM_ENFORCED
	AudioSystem.STREAM_MUSIC,       // STREAM_DTMF
	AudioSystem.STREAM_MUSIC        // STREAM_TTS
};

参考

  1. https://blog.csdn.net/kris_fei/article/details/72957142
  2. Audio的音量设置流程小结

文章作者: shell
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 shell !
评论
  目录