1. 音量级数定义
在AudioService.java中定义了最大音量MAX_STREAM_VOLUME,手机的设置property可以覆盖它。
2. 音量初始化
initStreamVolume传入AudioPolicyManagerBase里的StreamDescriptor mStreams[AudioSystem::NUM_STREAM_TYPES];
3. 设置主音量
主音量怎么起作用?
最终音量=主音量*流音量
4. 设置流音量
setStreamVolumeIndex函数,在AudioPolicy中,通过volIndexToAmpl把Index整数转为float型的振幅比,也就是“振幅/参考振幅”。
具体做法是:通过输入的index查表找到对应的声压值db,然后通过下面的公式算出amplifier,这个值就是振幅比。
函数volIndexToAmpl中有一行代码
float amplification = exp( decibels * 0.115129f);
就是这个公式。
通过这个值乘以音源的振幅,就得到了调节后的音量。这也是数字增益调节的原理。
拿到这个值后,存入AudioFlinger的全局变量mStreamTypes,即:mStreamTypes[stream].volume =value。
在Thread试图播放声音时,在prepareTracks_l中是这么做的(AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTracks_l(
Vector< sp<Track> > *tracksToRemove)):
// compute volume for this track
uint32_t vl, vr; // in U8.24 integer format
float vlf, vrf, vaf; // in [0.0, 1.0] float format
if (track->isPausing() || mStreamTypes[track->streamType()].mute) {
vl = vr = 0;
vlf = vrf = vaf = 0.;
if (track->isPausing()) {
track->setPaused();
}
} else {
// read original volumes with volume control
float typeVolume = mStreamTypes[track->streamType()].volume;
float v = masterVolume * typeVolume;
AudioTrackServerProxy *proxy = track->mAudioTrackServerProxy;
gain_minifloat_packed_t vlr = proxy->getVolumeLR();
vlf = float_from_gain(gain_minifloat_unpack_left(vlr));
vrf = float_from_gain(gain_minifloat_unpack_right(vlr));
// track volumes come from shared memory, so can't be trusted and must be clamped
if (vlf > GAIN_FLOAT_UNITY) {
ALOGV("Track left volume out of range: %.3g", vlf);
vlf = GAIN_FLOAT_UNITY;
}
if (vrf > GAIN_FLOAT_UNITY) {
ALOGV("Track right volume out of range: %.3g", vrf);
vrf = GAIN_FLOAT_UNITY;
}
// now apply the master volume and stream type volume
vlf *= v;
vrf *= v;
// assuming master volume and stream type volume each go up to 1.0,
// then derive vl and vr as U8.24 versions for the effect chain
const float scaleto8_24 = MAX_GAIN_INT * MAX_GAIN_INT;
vl = (uint32_t) (scaleto8_24 * vlf);
vr = (uint32_t) (scaleto8_24 * vrf);
// vl and vr are now in U8.24 format
uint16_t sendLevel = proxy->getSendLevel_U4_12();
// send level comes from shared memory and so may be corrupt
if (sendLevel > MAX_GAIN_INT) {
ALOGV("Track send level out of range: %04X", sendLevel);
sendLevel = MAX_GAIN_INT;
}
// vaf is represented as [0.0, 1.0] float by rescaling sendLevel
vaf = v * sendLevel * (1. / MAX_GAIN_INT);
}
// Delegate volume control to effect in track effect chain if needed
if (chain != 0 && chain->setVolume_l(&vl, &vr)) {
// Do not ramp volume if volume is controlled by effect
param = AudioMixer::VOLUME;
// Update remaining floating point volume levels
vlf = (float)vl / (1 << 24);
vrf = (float)vr / (1 << 24);
track->mHasVolumeController = true;
} else {
// force no volume ramp when volume controller was just disabled or removed
// from effect chain to avoid volume spike
if (track->mHasVolumeController) {
param = AudioMixer::VOLUME;
}
track->mHasVolumeController = false;
}
// XXX: these things DON'T need to be done each time
mAudioMixer->setBufferProvider(name, track);
mAudioMixer->enable(name);
mAudioMixer->setParameter(name, param, AudioMixer::VOLUME0, &vlf);
mAudioMixer->setParameter(name, param, AudioMixer::VOLUME1, &vrf);
mAudioMixer->setParameter(name, param, AudioMixer::AUXLEVEL, &vaf);
mAudioMixer->setParameter(
name,
AudioMixer::TRACK,
AudioMixer::FORMAT, (void *)track->format());
mAudioMixer->setParameter(
name,
AudioMixer::TRACK,
AudioMixer::CHANNEL_MASK, (void *)(uintptr_t)track->channelMask());
mAudioMixer->setParameter(
name,
AudioMixer::TRACK,
AudioMixer::MIXER_CHANNEL_MASK, (void *)(uintptr_t)mChannelMask
在系统静音时,只是很简单的设置下列参数为0:
vl = vr = 0;vlf = vrf = vaf = 0.
设置AudioMixer的参数
mAudioMixer->setParameter(name, param,AudioMixer::VOLUME0, &vlf);
mAudioMixer->setParameter(name, param,AudioMixer::VOLUME1, &vrf);
所以最后还是通过AudioMixer真正去乘以VOLUME0和VOLUME1来设置音量。
如track__16BitsStereo中
int32_t vl = t->prevVolume[0];
int32_t vr = t->prevVolume[1];
const int32_t vlInc =t->volumeInc[0];
const int32_t vrInc =t->volumeInc[1];
do {
*out++ += (vl >> 16) *(int32_t) *in++;
*out++ += (vr >> 16) *(int32_t) *in++;
vl += vlInc;
vr += vrInc;
} while (--frameCount);