From 72dafb20e036b8844775e3456e5d06a8a8a2cd50 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Thu, 22 Dec 2011 16:08:41 -0800 Subject: [PATCH] audioflinger: fix clicks on 48kHz audio. The calculation done in prepareTracks_l() for the minimum amount off frames needed to mix one output buffer had 2 issues: - the additional sample needed for interpolation was not included - the fact that the resampler does not acknowledge the frames consumed immediately after each mixing round but only once all frames requested have been used was not taken into account. Thus the number of frames available in track buffer could be considered sufficient although it was not and the resampler would abort producing a short silence perceived as a click. Issue 5727099. Change-Id: I7419847a7474c7d9f9170bedd0a636132262142c --- services/audioflinger/AudioFlinger.cpp | 10 +++++++++- services/audioflinger/AudioMixer.cpp | 17 +++++++++++++++++ services/audioflinger/AudioMixer.h | 3 +++ services/audioflinger/AudioResampler.h | 1 + 4 files changed, 30 insertions(+), 1 deletion(-) diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index e9ac3f93e8a06..060a6322029f0 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -2111,7 +2111,15 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wpsampleRate() == (int)mSampleRate) { minFrames = mFrameCount; } else { - minFrames = (mFrameCount * t->sampleRate()) / mSampleRate + 1; + // +1 for rounding and +1 for additional sample needed for interpolation + minFrames = (mFrameCount * t->sampleRate()) / mSampleRate + 1 + 1; + // add frames already consumed but not yet released by the resampler + // because cblk->framesReady() will include these frames + minFrames += 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... + LOG_ASSERT(minFrames <= cblk->frameCount); } } if ((cblk->framesReady() >= minFrames) && track->isReady() && diff --git a/services/audioflinger/AudioMixer.cpp b/services/audioflinger/AudioMixer.cpp index 6e9319d816995..1200f75f13d83 100644 --- a/services/audioflinger/AudioMixer.cpp +++ b/services/audioflinger/AudioMixer.cpp @@ -331,6 +331,23 @@ void AudioMixer::track_t::adjustVolumeRamp(bool aux) } } +size_t AudioMixer::track_t::getUnreleasedFrames() +{ + if (resampler != NULL) { + return resampler->getUnreleasedFrames(); + } + return 0; +} + +size_t AudioMixer::getUnreleasedFrames(int name) +{ + name -= TRACK0; + if (uint32_t(name) < MAX_NUM_TRACKS) { + track_t& track(mState.tracks[name]); + return track.getUnreleasedFrames(); + } + return 0; +} status_t AudioMixer::setBufferProvider(AudioBufferProvider* buffer) { diff --git a/services/audioflinger/AudioMixer.h b/services/audioflinger/AudioMixer.h index 75c91700e3525..0137185d936fa 100644 --- a/services/audioflinger/AudioMixer.h +++ b/services/audioflinger/AudioMixer.h @@ -91,6 +91,8 @@ public: static void ditherAndClamp(int32_t* out, int32_t const *sums, size_t c); + size_t getUnreleasedFrames(int name); + private: enum { @@ -167,6 +169,7 @@ private: bool doesResample() const; void resetResampler(); void adjustVolumeRamp(bool aux); + size_t getUnreleasedFrames(); }; // pad to 32-bytes to fill cache line diff --git a/services/audioflinger/AudioResampler.h b/services/audioflinger/AudioResampler.h index 9f06c1cf1d2f3..ffa690afd0ad7 100644 --- a/services/audioflinger/AudioResampler.h +++ b/services/audioflinger/AudioResampler.h @@ -54,6 +54,7 @@ public: AudioBufferProvider* provider) = 0; virtual void reset(); + virtual size_t getUnreleasedFrames() { return mInputIndex; } protected: // number of bits for phase fraction - 30 bits allows nearly 2x downsampling