diff options
Diffstat (limited to 'services/audioflinger/AudioFlinger.cpp')
| -rw-r--r-- | services/audioflinger/AudioFlinger.cpp | 55 |
1 files changed, 42 insertions, 13 deletions
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 69560e5..780c0d2 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -2066,7 +2066,21 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track // The first time a track is added we wait // for all its buffers to be filled before processing it mAudioMixer->setActiveTrack(track->name()); - if (cblk->framesReady() && track->isReady() && + // 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 (track->mRetryCount >= kMaxTrackRetries) meaning the track was mixed + // during last round + uint32_t minFrames = 1; + if (!track->isStopped() && !track->isPausing() && + (track->mRetryCount >= kMaxTrackRetries)) { + if (t->sampleRate() == (int)mSampleRate) { + minFrames = mFrameCount; + } else { + minFrames = (mFrameCount * t->sampleRate()) / mSampleRate + 1; + } + } + if ((cblk->framesReady() >= minFrames) && track->isReady() && !track->isPaused() && !track->isTerminated()) { //LOGV("track %d u=%08x, s=%08x [OK] on thread %p", track->name(), cblk->user, cblk->server, this); @@ -7014,11 +7028,17 @@ void AudioFlinger::EffectHandle::dump(char* buffer, size_t size) AudioFlinger::EffectChain::EffectChain(const wp<ThreadBase>& wThread, int sessionId) - : mThread(wThread), mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), + : mThread(wThread), mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0), mOwnInBuffer(false), mVolumeCtrlIdx(-1), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX), mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX) { mStrategy = AudioSystem::getStrategyForStream(AUDIO_STREAM_MUSIC); + sp<ThreadBase> thread = mThread.promote(); + if (thread == 0) { + return; + } + mMaxTailBuffers = ((kProcessTailDurationMs * thread->sampleRate()) / 1000) / + thread->frameCount(); } AudioFlinger::EffectChain::~EffectChain() @@ -7086,22 +7106,31 @@ void AudioFlinger::EffectChain::process_l() } bool isGlobalSession = (mSessionId == AUDIO_SESSION_OUTPUT_MIX) || (mSessionId == AUDIO_SESSION_OUTPUT_STAGE); - bool tracksOnSession = false; + // always process effects unless no more tracks are on the session and the effect tail + // has been rendered + bool doProcess = true; if (!isGlobalSession) { - tracksOnSession = (trackCnt() != 0); - } + bool tracksOnSession = (trackCnt() != 0); + + if (!tracksOnSession && mTailBufferCount == 0) { + doProcess = false; + } - // if no track is active, input buffer must be cleared here as the mixer process - // will not do it - if (tracksOnSession && - activeTrackCnt() == 0) { - size_t numSamples = thread->frameCount() * thread->channelCount(); - memset(mInBuffer, 0, numSamples * sizeof(int16_t)); + if (activeTrackCnt() == 0) { + // if no track is active and the effect tail has not been rendered, + // the input buffer must be cleared here as the mixer process will not do it + if (tracksOnSession || mTailBufferCount > 0) { + size_t numSamples = thread->frameCount() * thread->channelCount(); + memset(mInBuffer, 0, numSamples * sizeof(int16_t)); + if (mTailBufferCount > 0) { + mTailBufferCount--; + } + } + } } size_t size = mEffects.size(); - // do not process effect if no track is present in same audio session - if (isGlobalSession || tracksOnSession) { + if (doProcess) { for (size_t i = 0; i < size; i++) { mEffects[i]->process(); } |
