Android音量设置流程干货版
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);