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_VOLUME
和MAX_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
};