1. 程式人生 > >[RK3288][Android6.0] Audio中的混音過程小結

[RK3288][Android6.0] Audio中的混音過程小結

Platform: Rockchip
OS: Android 6.0
Kernel: 3.10.92

bool AudioFlinger::PlaybackThread::threadLoop()
{
......
    while (!exitPending())
    {
......
        //如果目前沒有音訊需要處理,那麼進入睡眠。
        if ((!mActiveTracks.size() && systemTime() > mStandbyTimeNs) ||
                               isSuspended()) {
// put audio hardware into standby after short delay if (shouldStandby_l()) { //進入睡眠待機 threadLoop_standby(); mStandby = true; } if (!mActiveTracks.size() && mConfigEvents.isEmpty()) { ..... //等待被喚醒 mWaitWorkCV.wait(mLock); ......
} } // mMixerStatusIgnoringFastTracks is also updated internally //喚醒後說明有active的trace,混音前做準備工作 mMixerStatus = prepareTracks_l(&tracksToRemove); ...... if (mBytesRemaining == 0) { //開始混音 threadLoop_mix(); ...... } if (!waitingAsyncCallback()) {
...... if (mBytesRemaining) { //混音後就可以寫資料到底層了 ret = threadLoop_write(); //處理underrun的情況 if ((now - lastWarning) > kWarningThrottleNs) { ATRACE_NAME("underrun"); ...... } ...... }

所以核心流程就是:
1. 睡眠, threadLoop_standby()
2. 混音前做準備工作, prepareTracks_l()
3. 混音, threadLoop_mix()
4. 音訊輸出, threadLoop_write()

prepareTracks_l():

AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTracks_l(
        Vector< sp<Track> > *tracksToRemove)
{
......
    //當前active的track做配置。
    size_t count = mActiveTracks.size();
    for (size_t i=0 ; i<count ; i++) {
......
            // XXX: these things DON'T need to be done each time
            //設定資料buffer,這個buffer可能會因為format,channel不一樣以及effect功能而被重新輸出到另一個buffer。
            //可以參考reconfigureBufferProviders()
            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);
            //設定format
            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);
......
            //設定取樣率,如果取樣率不一致,那麼要做重取樣的初始化工作。
            mAudioMixer->setParameter(
                name,
                AudioMixer::RESAMPLE,
                AudioMixer::SAMPLE_RATE,
                (void *)(uintptr_t)reqSampleRate);
        ......
    }
......
}

threadLoop_mix():

void AudioFlinger::MixerThread::threadLoop_mix()
{
......
    // mix buffers...
    mAudioMixer->process(pts);
......
}
void AudioMixer::process(int64_t pts)
{
    mState.hook(&mState, pts);
}

hook在之前會根據取樣率來選擇不同的處理函式,假如不需要resample,那麼呼叫process__genericNoResampling()

void AudioMixer::process__genericNoResampling(state_t* state, int64_t pts)
{
......
    while (e0) {
        const int i = 31 - __builtin_clz(e0);
        e0 &= ~(1<<i);
        track_t& t = state->tracks[i];
        t.buffer.frameCount = state->frameCount;
        //獲取可用buffer
        t.bufferProvider->getNextBuffer(&t.buffer, pts);
        t.frameCount = t.buffer.frameCount;
        t.in = t.buffer.raw;
    }
    while (e0) {
        track_t& t = state->tracks[i];
        //函式的賦值也是在process__validate()中,選擇哪個處理函式可參考getTrackHook()
        t.hook()
        .....
    }
......
}

threadLoop_write():

ssize_t AudioFlinger::MixerThread::threadLoop_write()
{
......
    return PlaybackThread::threadLoop_write();
}
ssize_t AudioFlinger::PlaybackThread::threadLoop_write()
{
......
mOutput->write((char *)mSinkBuffer + offset, mBytesRemaining);
......
}