您的位置:首页 > 移动开发 > Android开发

[RK3288][Android6.0] Audio中的混音过程小结

2017-06-14 10:55 429 查看
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);
......
}


参考:

http://www.cnblogs.com/TaigaCon/p/4827227.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: