1. 程式人生 > >Android音量設定流程乾貨版

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);