diff options
author | Eric Laurent <elaurent@google.com> | 2011-02-28 16:52:51 -0800 |
---|---|---|
committer | Eric Laurent <elaurent@google.com> | 2011-02-28 16:52:51 -0800 |
commit | 4bb21c496b2c9427c18b8370dd631339e4e11094 (patch) | |
tree | db4452dbae5ed341dc85fcef513b2359c4a363d4 /services | |
parent | dd1ddc3b1626f8bc335b6e54a73e8dc18bc71bb5 (diff) | |
download | frameworks_base-4bb21c496b2c9427c18b8370dd631339e4e11094.zip frameworks_base-4bb21c496b2c9427c18b8370dd631339e4e11094.tar.gz frameworks_base-4bb21c496b2c9427c18b8370dd631339e4e11094.tar.bz2 |
Fix issue 3479042.
The problem is that when an AudioRecord using the resampler is restarted,
the resampler state is not reset (as there is no reset function in the resampler).
The consequence is that the first time the record thread loop runs, it calls the resampler
which consumes the remaining data in the input buffer and when this buffer is released
the input index is incremented over the limit.
The fix consists in implementing a reset function in the resampler.
A similar problem was also present for playback but unoticed because the track buffer is always
drained by the mixer when a track stops. The only problem for playback was that the initial
phase fraction was wrong when restarting a track after stop (it was correct after a pause).
Change-Id: Ifc2585d685f4402d29f4afc63f6efd1d69265de3
Diffstat (limited to 'services')
-rw-r--r-- | services/audioflinger/AudioFlinger.cpp | 6 | ||||
-rw-r--r-- | services/audioflinger/AudioMixer.cpp | 13 | ||||
-rw-r--r-- | services/audioflinger/AudioMixer.h | 2 | ||||
-rw-r--r-- | services/audioflinger/AudioResampler.cpp | 6 | ||||
-rw-r--r-- | services/audioflinger/AudioResampler.h | 2 |
5 files changed, 28 insertions, 1 deletions
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 704da72..a07ebfc 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -1629,6 +1629,7 @@ uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track track->mState = TrackBase::ACTIVE; param = AudioMixer::RAMP_VOLUME; } + mAudioMixer->setParameter(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 @@ -3855,9 +3856,12 @@ status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrac mActiveTrack.clear(); return status; } - mActiveTrack->mState = TrackBase::RESUMING; mRsmpInIndex = mFrameCount; mBytesRead = 0; + if (mResampler != NULL) { + mResampler->reset(); + } + mActiveTrack->mState = TrackBase::RESUMING; // signal thread to start LOGV("Signal record thread"); mWaitWorkCV.signal(); diff --git a/services/audioflinger/AudioMixer.cpp b/services/audioflinger/AudioMixer.cpp index 433f1f7..50dcda7 100644 --- a/services/audioflinger/AudioMixer.cpp +++ b/services/audioflinger/AudioMixer.cpp @@ -220,6 +220,12 @@ status_t AudioMixer::setParameter(int target, int name, void *value) return NO_ERROR; } } + if (name == RESET) { + track_t& track = mState.tracks[ mActiveTrack ]; + track.resetResampler(); + invalidateState(1<<mActiveTrack); + return NO_ERROR; + } break; case RAMP_VOLUME: case VOLUME: @@ -289,6 +295,13 @@ bool AudioMixer::track_t::doesResample() const return resampler != 0; } +void AudioMixer::track_t::resetResampler() +{ + if (resampler != 0) { + resampler->reset(); + } +} + inline void AudioMixer::track_t::adjustVolumeRamp(bool aux) { diff --git a/services/audioflinger/AudioMixer.h b/services/audioflinger/AudioMixer.h index aee3e17..88408a7 100644 --- a/services/audioflinger/AudioMixer.h +++ b/services/audioflinger/AudioMixer.h @@ -67,6 +67,7 @@ public: AUX_BUFFER = 0x4003, // for TARGET RESAMPLE SAMPLE_RATE = 0x4100, + RESET = 0x4101, // for TARGET VOLUME (8 channels max) VOLUME0 = 0x4200, VOLUME1 = 0x4201, @@ -163,6 +164,7 @@ private: bool setResampler(uint32_t sampleRate, uint32_t devSampleRate); bool doesResample() const; + void resetResampler(); void adjustVolumeRamp(bool aux); }; diff --git a/services/audioflinger/AudioResampler.cpp b/services/audioflinger/AudioResampler.cpp index 5dabacb..5c3b43fc 100644 --- a/services/audioflinger/AudioResampler.cpp +++ b/services/audioflinger/AudioResampler.cpp @@ -148,6 +148,12 @@ void AudioResampler::setVolume(int16_t left, int16_t right) { mVolume[1] = right; } +void AudioResampler::reset() { + mInputIndex = 0; + mPhaseFraction = 0; + mBuffer.frameCount = 0; +} + // ---------------------------------------------------------------------------- void AudioResamplerOrder1::resample(int32_t* out, size_t outFrameCount, diff --git a/services/audioflinger/AudioResampler.h b/services/audioflinger/AudioResampler.h index 2dfac76..9f06c1c 100644 --- a/services/audioflinger/AudioResampler.h +++ b/services/audioflinger/AudioResampler.h @@ -53,6 +53,8 @@ public: virtual void resample(int32_t* out, size_t outFrameCount, AudioBufferProvider* provider) = 0; + virtual void reset(); + protected: // number of bits for phase fraction - 30 bits allows nearly 2x downsampling static const int kNumPhaseBits = 30; |