// prepareTracks_l() must be called with ThreadBase::mLock held AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTracks_l( Vector< sp<Track> > *tracksToRemove) { mixer_state mixerStatus = MIXER_IDLE; // find out which tracks need to be processed // 激活的track数量,待mix的track,关联effect的track size_t count = mActiveTracks.size(); size_t mixedTracks = 0; size_t tracksWithEffect = 0; // counts only _active_ fast tracks // fast track计数和重置标志位 size_t fastTracks = 0; uint32_t resetMask = 0; // bit mask of fast tracks that need to be reset float masterVolume = mMasterVolume; bool masterMute = mMasterMute; if (masterMute) { masterVolume = 0; } // Delegate master volume control to effect in output mix effect chain if needed // 将主音量设置到MixEffectChain中 sp<EffectChain> chain = getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX); if (chain != 0) { uint32_t v = (uint32_t)(masterVolume * (1 << 24)); chain->setVolume_l(&v, &v); masterVolume = (float)((v + (1 << 23)) >> 24); chain.clear(); } // prepare a new state to push FastMixerStateQueue *sq = NULL; FastMixerState *state = NULL; bool didModify = false; FastMixerStateQueue::block_t block = FastMixerStateQueue::BLOCK_UNTIL_PUSHED; if (mFastMixer != NULL) { sq = mFastMixer->sq(); state = sq->begin(); } //循环处理active类型的track,核心代码 for (size_t i=0 ; i<count ; i++) { sp<Track> t = mActiveTracks[i].promote(); if (t == 0) { continue; } // this const just means the local variable doesn't change Track* const track = t.get(); //---------------------------------------------------------------- // process fast tracks // 如果该track在AudioMix端有对应的fast track if (track->isFastTrack()) { // It's theoretically possible (though unlikely) for a fast track to be created // and then removed within the same normal mix cycle. This is not a problem, as // the track never becomes active so it's fast mixer slot is never touched. // The converse, of removing an (active) track and then creating a new track // at the identical fast mixer slot within the same normal mix cycle, // is impossible because the slot isn't marked available until the end of each cycle. int j = track->mFastIndex; ALOG_ASSERT(0 < j && j < (int)FastMixerState::kMaxFastTracks); ALOG_ASSERT(!(mFastTrackAvailMask & (1 << j))); FastTrack *fastTrack = &state->mFastTracks[j]; // Determine whether the track is currently in underrun condition, // and whether it had a recent underrun. FastTrackDump *ftDump = &mFastMixerDumpState.mTracks[j]; FastTrackUnderruns underruns = ftDump->mUnderruns; uint32_t recentFull = (underruns.mBitFields.mFull - track->mObservedUnderruns.mBitFields.mFull) & UNDERRUN_MASK; uint32_t recentPartial = (underruns.mBitFields.mPartial - track->mObservedUnderruns.mBitFields.mPartial) & UNDERRUN_MASK; uint32_t recentEmpty = (underruns.mBitFields.mEmpty - track->mObservedUnderruns.mBitFields.mEmpty) & UNDERRUN_MASK; uint32_t recentUnderruns = recentPartial + recentEmpty; track->mObservedUnderruns = underruns; // don't count underruns that occur while stopping or pausing // or stopped which can occur when flush() is called while active if (!(track->isStopping() || track->isPausing() || track->isStopped()) && recentUnderruns > 0) { // FIXME fast mixer will pull & mix partial buffers, but we count as a full underrun track->mAudioTrackServerProxy->tallyUnderrunFrames(recentUnderruns * mFrameCount); } // This is similar to the state machine for normal tracks, // with a few modifications for fast tracks. bool isActive = true; switch (track->mState) { case TrackBase::STOPPING_1: // track stays active in STOPPING_1 state until first underrun if (recentUnderruns > 0 || track->isTerminated()) { track->mState = TrackBase::STOPPING_2; } break; case TrackBase::PAUSING: // ramp down is not yet implemented track->setPaused(); break; case TrackBase::RESUMING: // ramp up is not yet implemented track->mState = TrackBase::ACTIVE; break; case TrackBase::ACTIVE: if (recentFull > 0 || recentPartial > 0) { // track has provided at least some frames recently: reset retry count track->mRetryCount = kMaxTrackRetries; } if (recentUnderruns == 0) { // no recent underruns: stay active break; } // there has recently been an underrun of some kind if (track->sharedBuffer() == 0) { // were any of the recent underruns "empty" (no frames available)? if (recentEmpty == 0) { // no, then ignore the partial underruns as they are allowed indefinitely break; } // there has recently been an "empty" underrun: decrement the retry counter if (--(track->mRetryCount) > 0) { break; } // indicate to client process that the track was disabled because of underrun; // it will then automatically call start() when data is available android_atomic_or(CBLK_DISABLED, &track->mCblk->mFlags); // remove from active list, but state remains ACTIVE [confusing but true] isActive = false; break; } // fall through case TrackBase::STOPPING_2: case TrackBase::PAUSED: case TrackBase::STOPPED: case TrackBase::FLUSHED: // flush() while active // Check for presentation complete if track is inactive // We have consumed all the buffers of this track. // This would be incomplete if we auto-paused on underrun { size_t audioHALFrames = (mOutput->stream->get_latency(mOutput->stream)*mSampleRate) / 1000; size_t framesWritten = mBytesWritten / mFrameSize; if (!(mStandby || track->presentationComplete(framesWritten, audioHALFrames))) { // track stays in active list until presentation is complete break; } } if (track->isStopping_2()) { track->mState = TrackBase::STOPPED; } if (track->isStopped()) { // Can't reset directly, as fast mixer is still polling this track // track->reset(); // So instead mark this track as needing to be reset after push with ack resetMask |= 1 << i; } isActive = false; break; case TrackBase::IDLE: default: LOG_FATAL("unexpected track state %d", track->mState); } if (isActive) { // was it previously inactive? if (!(state->mTrackMask & (1 << j))) { ExtendedAudioBufferProvider *eabp = track; VolumeProvider *vp = track; fastTrack->mBufferProvider = eabp; fastTrack->mVolumeProvider = vp; fastTrack->mChannelMask = track->mChannelMask; fastTrack->mGeneration++; state->mTrackMask |= 1 << j; didModify = true; // no acknowledgement required for newly active tracks } // cache the combined master volume and stream type volume for fast mixer; this // lacks any synchronization or barrier so VolumeProvider may read a stale value track->mCachedVolume = masterVolume * mStreamTypes[track->streamType()].volume; ++fastTracks; } else { // was it previously active? if (state->mTrackMask & (1 << j)) { fastTrack->mBufferProvider = NULL; fastTrack->mGeneration++; state->mTrackMask &= ~(1 << j); didModify = true; // If any fast tracks were removed, we must wait for acknowledgement // because we're about to decrement the last sp<> on those tracks. block = FastMixerStateQueue::BLOCK_UNTIL_ACKED; } else { LOG_FATAL("fast track %d should have been active", j); } tracksToRemove->add(track); // Avoids a misleading display in dumpsys track->mObservedUnderruns.mBitFields.mMostRecent = UNDERRUN_FULL; } //对fastTrack和normTrack进行不同处理 continue; } //开始处理normTrack //++++++++++++++++++++++++++++++++++++++++++++++++++++++++ { // local variable scope to avoid goto warning audio_track_cblk_t* cblk = track->cblk(); // The first time a track is added we wait // for all its buffers to be filled before processing it int name = track->name(); // make sure that we have enough frames to mix one full buffer. // enforce this condition only once to enable draining the buffer in case the client // app does not call stop() and relies on underrun to stop: // hence the test on (mMixerStatus == MIXER_TRACKS_READY) meaning the track was mixed // during last round // 计算最少需要多少数据帧,防止出现underrun的情况,即读取数据的速度比写入数据的速度快 // 1、如果track的采样率和Hal输出端的采样率相同,则按照输出端大小提供数据帧 // 2、否则需要按照track和Hal输出端的采样率换算最小数据帧,包含未释放帧数 // track的采样率越大,则需要的数据帧越多,相当于进行了压缩 // 3、最少帧数必须小于cblk控制的数据块总数frameCount_,通常情况下 // 其数目是mNormalFrameCount的两倍 size_t desiredFrames; uint32_t sr = track->sampleRate(); if (sr == mSampleRate) { desiredFrames = mNormalFrameCount; } else { // +1 for rounding and +1 for additional sample needed for interpolation desiredFrames = (mNormalFrameCount * sr) / mSampleRate + 1 + 1; // add frames already consumed but not yet released by the resampler // because cblk->framesReady() will include these frames desiredFrames += mAudioMixer->getUnreleasedFrames(track->name()); // the minimum track buffer size is normally twice the number of frames necessary // to fill one buffer and the resampler should not leave more than one buffer worth // of unreleased frames after each pass, but just in case... ALOG_ASSERT(desiredFrames <= cblk->frameCount_); } //如果是STREAM模式,则需要采用以上计算的最小帧数 //因为STATIC模式是一次性行为,不需要计算最小帧数 uint32_t minFrames = 1; if ((track->sharedBuffer() == 0) && !track->isStopped() && !track->isPausing() && (mMixerStatusIgnoringFastTracks == MIXER_TRACKS_READY)) { minFrames = desiredFrames; } // 当track准备的帧数大于需要写入的最少帧,则增加mixedTrack计数,进行Mix if ((track->framesReady() >= minFrames) && track->isReady() && !track->isPaused() && !track->isTerminated()) { ALOGVV("track %d u=%08x, s=%08x [OK] on thread %p", name, cblk->user, cblk->server, this); mixedTracks++; // track->mainBuffer() != mMixBuffer means there is an effect chain // connected to the track // 如果track已经已关联effectChain,增加trackwitheffect计数,其数据流: // track->mainBuff->effectChain->mMixBuff chain.clear(); if (track->mainBuffer() != mMixBuffer) { chain = getEffectChain_l(track->sessionId()); // Delegate volume control to effect in track effect chain if needed if (chain != 0) { tracksWithEffect++; } else { ALOGW("prepareTracks_l(): track %d attached to effect but no chain found on " "session %d", name, track->sessionId()); } } //调整音量 int param = AudioMixer::VOLUME; if (track->mFillingUpStatus == Track::FS_FILLED) { // no ramp for the first volume setting track->mFillingUpStatus = Track::FS_ACTIVE; if (track->mState == TrackBase::RESUMING) { track->mState = TrackBase::ACTIVE; param = AudioMixer::RAMP_VOLUME; } mAudioMixer->setParameter(name, AudioMixer::RESAMPLE, AudioMixer::RESET, NULL); } else if (cblk->server != 0) { // If the track is stopped before the first frame was mixed, // do not apply ramp param = AudioMixer::RAMP_VOLUME; } // compute volume for this track // 分别表示左声道、右声道、Aux音量 // 1、静音状态时,直接将音量置为0 uint32_t vl, vr, va; if (track->isPausing() || mStreamTypes[track->streamType()].mute) { vl = vr = va = 0; if (track->isPausing()) { track->setPaused(); } } else { // read original volumes with volume control // 获得每种stream类型设置的音量 float typeVolume = mStreamTypes[track->streamType()].volume; // 主音量和类型音量的乘积 float v = masterVolume * typeVolume; AudioTrackServerProxy *proxy = track->mAudioTrackServerProxy; // 读取cblk中的左右音量,32到17位为左音量,16到1为右音量 // 验证左右音量的合法性 uint32_t vlr = proxy->getVolumeLR(); vl = vlr & 0xFFFF; vr = vlr >> 16; // track volumes come from shared memory, so can't be trusted and must be clamped if (vl > MAX_GAIN_INT) { ALOGV("Track left volume out of range: %04X", vl); vl = MAX_GAIN_INT; } if (vr > MAX_GAIN_INT) { ALOGV("Track right volume out of range: %04X", vr); vr = MAX_GAIN_INT; } // now apply the master volume and stream type volume vl = (uint32_t)(v * vl) << 12; vr = (uint32_t)(v * vr) << 12; // assuming master volume and stream type volume each go up to 1.0, // vl and vr are now in 8.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; } va = (uint32_t)(v * sendLevel); } // Delegate volume control to effect in track effect chain if needed // 向effectChain中设置音量,如果失败则表示volume Controller移除了 if (chain != 0 && chain->setVolume_l(&vl, &vr)) { // Do not ramp volume if volume is controlled by effect param = AudioMixer::VOLUME; 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; } // Convert volumes from 8.24 to 4.12 format // This additional clamping is needed in case chain->setVolume_l() overshot vl = (vl + (1 << 11)) >> 12; if (vl > MAX_GAIN_INT) { vl = MAX_GAIN_INT; } vr = (vr + (1 << 11)) >> 12; if (vr > MAX_GAIN_INT) { vr = MAX_GAIN_INT; } if (va > MAX_GAIN_INT) { va = MAX_GAIN_INT; // va is uint32_t, so no need to check for - } // XXX: these things DON'T need to be done each time // 设置Mix的输入,将track设置为AudioMix中track的数据提供者 // 后续AudioMixer会从track申请的cblk中获取数据 // 根据name使能AudioMix中track mAudioMixer->setBufferProvider(name, track); mAudioMixer->enable(name); // 设置左右声道和Aux声道 mAudioMixer->setParameter(name, param, AudioMixer::VOLUME0, (void *)(uintptr_t)vl); mAudioMixer->setParameter(name, param, AudioMixer::VOLUME1, (void *)(uintptr_t)vr); mAudioMixer->setParameter(name, param, AudioMixer::AUXLEVEL, (void *)(uintptr_t)va); mAudioMixer->setParameter( name, AudioMixer::TRACK, AudioMixer::FORMAT, (void *)track->format()); mAudioMixer->setParameter( name, AudioMixer::TRACK, AudioMixer::CHANNEL_MASK, (void *)(uintptr_t)track->channelMask()); // limit track sample rate to 2 x output sample rate, which changes at re-configuration // 读取cblk中的采样率,取值不能大于Hal层采样率的两倍 uint32_t maxSampleRate = mSampleRate * 2; uint32_t reqSampleRate = track->mAudioTrackServerProxy->getSampleRate(); if (reqSampleRate == 0) { reqSampleRate = mSampleRate; } else if (reqSampleRate > maxSampleRate) { reqSampleRate = maxSampleRate; } mAudioMixer->setParameter( name, AudioMixer::RESAMPLE, AudioMixer::SAMPLE_RATE, (void *)(uintptr_t)reqSampleRate); //设置Mix的输出,包括mainBuff和auxBuff //其中mainBuff关联 mAudioMixer->setParameter( name, AudioMixer::TRACK, AudioMixer::MAIN_BUFFER, (void *)track->mainBuffer()); mAudioMixer->setParameter( name, AudioMixer::TRACK, AudioMixer::AUX_BUFFER, (void *)track->auxBuffer()); // reset retry count track->mRetryCount = kMaxTrackRetries; // If one track is ready, set the mixer ready if: // - the mixer was not ready during previous round OR // - no other track is not ready //需要满足以下任意条件才能设置mix的状态为ready //1、之前的调用结果不是ready //2、其它track都满足ready的条件,即只要有一个track // 不满足ready的条件,则Mix都不能设置为ready if (mMixerStatusIgnoringFastTracks != MIXER_TRACKS_READY || mixerStatus != MIXER_TRACKS_ENABLED) { mixerStatus = MIXER_TRACKS_READY; } } else { if (framesReady < desiredFrames && !track->isStopped() && !track->isPaused()) { track->mAudioTrackServerProxy->tallyUnderrunFrames(desiredFrames); } // clear effect chain input buffer if an active track underruns to avoid sending // previous audio buffer again to effects // 清空track关联effect的buff,防止underruns的情况 // 即避免废弃的数据影响effect的下一次输出 chain = getEffectChain_l(track->sessionId()); if (chain != 0) { chain->clearInputBuffer(); } //以下情况时表明已经完成track指向cblk中数据的读取, //可以将该track放入移除列队,等待移除 ALOGVV("track %d s=%08x [NOT READY] on thread %p", name, cblk->mServer, this); if ((track->sharedBuffer() != 0) || track->isTerminated() || track->isStopped() || track->isPaused()) { // We have consumed all the buffers of this track. // Remove it from the list of active tracks. // TODO: use actual buffer filling status instead of latency when available from // audio HAL size_t audioHALFrames = (latency_l() * mSampleRate) / 1000; size_t framesWritten = mBytesWritten / mFrameSize; if (mStandby || track->presentationComplete(framesWritten, audioHALFrames)) { if (track->isStopped()) { track->reset(); } tracksToRemove->add(track); } } else { // No buffers for this track. Give it a few chances to // fill a buffer, then remove it from active list. // 如果重试计数小于0,将该track放入移除队列, // 否则将Mix状态设置为enable if (--(track->mRetryCount) <= 0) { ALOGI("BUFFER TIMEOUT: remove(%d) from active list on thread %p", name, this); tracksToRemove->add(track); // indicate to client process that the track was disabled because of underrun; // it will then automatically call start() when data is available android_atomic_or(CBLK_DISABLED, &cblk->mFlags); // If one track is not ready, mark the mixer also not ready if: // - the mixer was ready during previous round OR // - no other track is ready } else if (mMixerStatusIgnoringFastTracks == MIXER_TRACKS_READY || mixerStatus != MIXER_TRACKS_READY) { mixerStatus = MIXER_TRACKS_ENABLED; } } //关闭AudioMix中的track mAudioMixer->disable(name); } } // local variable scope to avoid goto warning track_is_ready: ; } //----------------------------------------------------------------- // Push the new FastMixer state if necessary bool pauseAudioWatchdog = false; if (didModify) { state->mFastTracksGen++; // if the fast mixer was active, but now there are no fast tracks, then put it in cold idle if (kUseFastMixer == FastMixer_Dynamic && state->mCommand == FastMixerState::MIX_WRITE && state->mTrackMask <= 1) { state->mCommand = FastMixerState::COLD_IDLE; state->mColdFutexAddr = &mFastMixerFutex; state->mColdGen++; mFastMixerFutex = 0; if (kUseFastMixer == FastMixer_Dynamic) { mNormalSink = mOutputSink; } // If we go into cold idle, need to wait for acknowledgement // so that fast mixer stops doing I/O. block = FastMixerStateQueue::BLOCK_UNTIL_ACKED; pauseAudioWatchdog = true; } } if (sq != NULL) { sq->end(didModify); sq->push(block); } #ifdef AUDIO_WATCHDOG if (pauseAudioWatchdog && mAudioWatchdog != 0) { mAudioWatchdog->pause(); } #endif // Now perform the deferred reset on fast tracks that have stopped while (resetMask != 0) { size_t i = __builtin_ctz(resetMask); ALOG_ASSERT(i < count); resetMask &= ~(1 << i); sp<Track> t = mActiveTracks[i].promote(); if (t == 0) { continue; } Track* track = t.get(); ALOG_ASSERT(track->isFastTrack() && track->isStopped()); track->reset(); } //++++++++++++++++++++++++++++++++++++++++++++++++++++++ // remove all the tracks that need to be... removeTracks_l(*tracksToRemove); // mix buffer must be cleared if all tracks are connected to an // effect chain as in this case the mixer will not write to // mix buffer and track effects will accumulate into it // 以下两种情况需要清空MixBuff // 1、如果所有的track都与effect相关联,其数据流向为: // track->mainBuff(InBuff)->Chain, // 否则其数据流为:track->mainBuff(MixBuff)->AudioMix // 2、没有可供mix的track,但是有fastTrack需要处理, // 其数据流为:track->mainBuff(MixBuff)->pipSink->FastMix if ((mBytesRemaining == 0) && ((mixedTracks != 0 && mixedTracks == tracksWithEffect) || (mixedTracks == 0 && fastTracks > 0))) { // FIXME as a performance optimization, should remember previous zero status memset(mMixBuffer, 0, mNormalFrameCount * mChannelCount * sizeof(int16_t)); } // if any fast tracks, then status is ready mMixerStatusIgnoringFastTracks = mixerStatus; if (fastTracks > 0) { mixerStatus = MIXER_TRACKS_READY; } return mixerStatus; } //enabled的注释貌似不对,实际上,当上次mix状态为ready时,本次只要有一个track为enabled状态 //则mix的状态就为enabled enum mixer_state { MIXER_IDLE, // no active tracks MIXER_TRACKS_ENABLED, // at least one active track, but no track has any data ready MIXER_TRACKS_READY, // at least one active track, and at least one track has data MIXER_DRAIN_TRACK, // drain currently playing track MIXER_DRAIN_ALL, // fully drain the hardware // standby mode does not have an enum value // suspend by audio policy manager is orthogonal to mixer state }; //计算当前track中可供处理的数据帧 size_t AudioTrackServerProxy::framesReady() { LOG_ALWAYS_FATAL_IF(!mIsOut); if (mIsShutdown) { return 0; } audio_track_cblk_t* cblk = mCblk; //如果有flush动作,则直接返回缓冲区的大小 int32_t flush = cblk->u.mStreaming.mFlush; if (flush != mFlush) { return mFrameCount; } // the acquire might not be necessary since not doing a subsequent read // 根据写和读的位置计算当前缓冲区可读数据字节数 int32_t rear = android_atomic_acquire_load(&cblk->u.mStreaming.mRear); ssize_t filled = rear - cblk->u.mStreaming.mFront; // pipe should not already be overfull // 校验缓冲区是否溢出 if (!(0 <= filled && (size_t) filled <= mFrameCount)) { ALOGE("Shared memory control block is corrupt (filled=%d); shutting down", filled); mIsShutdown = true; return 0; } // cache this value for later use by obtainBuffer(), with added barrier // and racy if called by normal mixer thread // ignores flush(), so framesReady() may report a larger mFrameCount than obtainBuffer() return filled; } void AudioMixer::setBufferProvider(int name, AudioBufferProvider* bufferProvider) { name -= TRACK0; ALOG_ASSERT(uint32_t(name) < MAX_NUM_TRACKS, "bad track name %d", name); if (mState.tracks[name].downmixerBufferProvider != NULL) { // update required? if (mState.tracks[name].downmixerBufferProvider->mTrackBufferProvider != bufferProvider) { ALOGV("AudioMixer::setBufferProvider(%p) for downmix", bufferProvider); // setting the buffer provider for a track that gets downmixed consists in: // 1/ setting the buffer provider to the "downmix / buffer provider" wrapper // so it's the one that gets called when the buffer provider is needed, mState.tracks[name].bufferProvider = mState.tracks[name].downmixerBufferProvider; // 2/ saving the buffer provider for the track so the wrapper can use it // when it downmixes. mState.tracks[name].downmixerBufferProvider->mTrackBufferProvider = bufferProvider; } } else { mState.tracks[name].bufferProvider = bufferProvider; } } void AudioMixer::enable(int name) { name -= TRACK0; ALOG_ASSERT(uint32_t(name) < MAX_NUM_TRACKS, "bad track name %d", name); track_t& track = mState.tracks[name]; if (!track.enabled) { track.enabled = true; ALOGV("enable(%d)", name); invalidateState(1 << name); } } void AudioMixer::disable(int name) { name -= TRACK0; ALOG_ASSERT(uint32_t(name) < MAX_NUM_TRACKS, "bad track name %d", name); track_t& track = mState.tracks[name]; if (track.enabled) { track.enabled = false; ALOGV("disable(%d)", name); invalidateState(1 << name); } } //设置AudioMix端指定track的参数,包括通道数、输出buff、Aux buff、精度、音量、 //重采样等,同时记录tracck的index,调用process__validate,进行处理函数的调整 void AudioMixer::setParameter(int name, int target, int param, void *value) { name -= TRACK0; ALOG_ASSERT(uint32_t(name) < MAX_NUM_TRACKS, "bad track name %d", name); track_t& track = mState.tracks[name]; int valueInt = static_cast<int>(reinterpret_cast<uintptr_t>(value)); int32_t *valueBuf = reinterpret_cast<int32_t*>(value); switch (target) { case TRACK: switch (param) { case CHANNEL_MASK: { audio_channel_mask_t mask = static_cast<audio_channel_mask_t>(reinterpret_cast<uintptr_t>(value)); if (track.channelMask != mask) { uint32_t channelCount = popcount(mask); ALOG_ASSERT((channelCount <= MAX_NUM_CHANNELS_TO_DOWNMIX) && channelCount); track.channelMask = mask; track.channelCount = channelCount; // the mask has changed, does this track need a downmixer? initTrackDownmix(&mState.tracks[name], name, mask); ALOGV("setParameter(TRACK, CHANNEL_MASK, %x)", mask); invalidateState(1 << name); } } break; case MAIN_BUFFER: if (track.mainBuffer != valueBuf) { track.mainBuffer = valueBuf; ALOGV("setParameter(TRACK, MAIN_BUFFER, %p)", valueBuf); invalidateState(1 << name); } break; case AUX_BUFFER: if (track.auxBuffer != valueBuf) { track.auxBuffer = valueBuf; ALOGV("setParameter(TRACK, AUX_BUFFER, %p)", valueBuf); invalidateState(1 << name); } break; case FORMAT: ALOG_ASSERT(valueInt == AUDIO_FORMAT_PCM_16_BIT); break; // FIXME do we want to support setting the downmix type from AudioFlinger? // for a specific track? or per mixer? /* case DOWNMIX_TYPE: break */ default: LOG_FATAL("bad param"); } break; case RESAMPLE: switch (param) { case SAMPLE_RATE: ALOG_ASSERT(valueInt > 0, "bad sample rate %d", valueInt); if (track.setResampler(uint32_t(valueInt), mSampleRate)) { ALOGV("setParameter(RESAMPLE, SAMPLE_RATE, %u)", uint32_t(valueInt)); invalidateState(1 << name); } break; case RESET: track.resetResampler(); invalidateState(1 << name); break; case REMOVE: delete track.resampler; track.resampler = NULL; track.sampleRate = mSampleRate; invalidateState(1 << name); break; default: LOG_FATAL("bad param"); } break; case RAMP_VOLUME: case VOLUME: switch (param) { case VOLUME0: case VOLUME1: if (track.volume[param-VOLUME0] != valueInt) { ALOGV("setParameter(VOLUME, VOLUME0/1: %04x)", valueInt); track.prevVolume[param-VOLUME0] = track.volume[param-VOLUME0] << 16; track.volume[param-VOLUME0] = valueInt; if (target == VOLUME) { track.prevVolume[param-VOLUME0] = valueInt << 16; track.volumeInc[param-VOLUME0] = 0; } else { int32_t d = (valueInt<<16) - track.prevVolume[param-VOLUME0]; int32_t volInc = d / int32_t(mState.frameCount); track.volumeInc[param-VOLUME0] = volInc; if (volInc == 0) { track.prevVolume[param-VOLUME0] = valueInt << 16; } } invalidateState(1 << name); } break; case AUXLEVEL: //ALOG_ASSERT(0 <= valueInt && valueInt <= MAX_GAIN_INT, "bad aux level %d", valueInt); if (track.auxLevel != valueInt) { ALOGV("setParameter(VOLUME, AUXLEVEL: %04x)", valueInt); track.prevAuxLevel = track.auxLevel << 16; track.auxLevel = valueInt; if (target == VOLUME) { track.prevAuxLevel = valueInt << 16; track.auxInc = 0; } else { int32_t d = (valueInt<<16) - track.prevAuxLevel; int32_t volInc = d / int32_t(mState.frameCount); track.auxInc = volInc; if (volInc == 0) { track.prevAuxLevel = valueInt << 16; } } invalidateState(1 << name); } break; default: LOG_FATAL("bad param"); } break; default: LOG_FATAL("bad target"); } } void AudioMixer::invalidateState(uint32_t mask) { if (mask) { mState.needsChanged |= mask; mState.hook = process__validate; } } //根据prepare设置的参数来进行处理函数的调整 void AudioMixer::process__validate(state_t* state, int64_t pts) { ALOGW_IF(!state->needsChanged, "in process__validate() but nothing's invalid"); uint32_t changed = state->needsChanged; state->needsChanged = 0; // clear the validation flag // recompute which tracks are enabled / disabled // 检查需要改变的track是否已经使能 uint32_t enabled = 0; uint32_t disabled = 0; while (changed) { const int i = 31 - __builtin_clz(changed); const uint32_t mask = 1<<i; changed &= ~mask; track_t& t = state->tracks[i]; (t.enabled ? enabled : disabled) |= mask; } state->enabledTracks &= ~disabled; state->enabledTracks |= enabled; // compute everything we need... // 选择处理函数之前的参数计算 int countActiveTracks = 0; bool all16BitsStereoNoResample = true; bool resampling = false; bool volumeRamp = false; uint32_t en = state->enabledTracks; while (en) { const int i = 31 - __builtin_clz(en); en &= ~(1<<i); countActiveTracks++; track_t& t = state->tracks[i]; uint32_t n = 0; n |= NEEDS_CHANNEL_1 + t.channelCount - 1; n |= NEEDS_FORMAT_16; n |= t.doesResample() ? NEEDS_RESAMPLE_ENABLED : NEEDS_RESAMPLE_DISABLED; if (t.auxLevel != 0 && t.auxBuffer != NULL) { n |= NEEDS_AUX_ENABLED; } if (t.volumeInc[0]|t.volumeInc[1]) { volumeRamp = true; } else if (!t.doesResample() && t.volumeRL == 0) { n |= NEEDS_MUTE_ENABLED; } t.needs = n; if ((n & NEEDS_MUTE__MASK) == NEEDS_MUTE_ENABLED) { t.hook = track__nop; } else { if ((n & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED) { all16BitsStereoNoResample = false; } if ((n & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) { all16BitsStereoNoResample = false; resampling = true; t.hook = track__genericResample; ALOGV_IF((n & NEEDS_CHANNEL_COUNT__MASK) > NEEDS_CHANNEL_2, "Track %d needs downmix + resample", i); } else { if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1){ t.hook = track__16BitsMono; all16BitsStereoNoResample = false; } if ((n & NEEDS_CHANNEL_COUNT__MASK) >= NEEDS_CHANNEL_2){ t.hook = track__16BitsStereo; ALOGV_IF((n & NEEDS_CHANNEL_COUNT__MASK) > NEEDS_CHANNEL_2, "Track %d needs downmix", i); } } } } // select the processing hooks state->hook = process__nop; if (countActiveTracks) { if (resampling) { if (!state->outputTemp) { state->outputTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount]; } if (!state->resampleTemp) { state->resampleTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount]; } state->hook = process__genericResampling; } else { if (state->outputTemp) { delete [] state->outputTemp; state->outputTemp = NULL; } if (state->resampleTemp) { delete [] state->resampleTemp; state->resampleTemp = NULL; } state->hook = process__genericNoResampling; if (all16BitsStereoNoResample && !volumeRamp) { if (countActiveTracks == 1) { state->hook = process__OneTrack16BitsStereoNoResampling; } } } } ALOGV("mixer configuration change: %d activeTracks (%08x) " "all16BitsStereoNoResample=%d, resampling=%d, volumeRamp=%d", countActiveTracks, state->enabledTracks, all16BitsStereoNoResample, resampling, volumeRamp); state->hook(state, pts); // Now that the volume ramp has been done, set optimal state and // track hooks for subsequent mixer process if (countActiveTracks) { bool allMuted = true; uint32_t en = state->enabledTracks; while (en) { const int i = 31 - __builtin_clz(en); en &= ~(1<<i); track_t& t = state->tracks[i]; if (!t.doesResample() && t.volumeRL == 0) { t.needs |= NEEDS_MUTE_ENABLED; t.hook = track__nop; } else { allMuted = false; } } if (allMuted) { state->hook = process__nop; } else if (all16BitsStereoNoResample) { if (countActiveTracks == 1) { state->hook = process__OneTrack16BitsStereoNoResampling; } } } }