diff options
author | Andy Hung <hunga@google.com> | 2014-08-07 11:04:34 -0700 |
---|---|---|
committer | Andy Hung <hunga@google.com> | 2014-08-11 10:17:18 -0700 |
commit | cd04484f4837b8ca0041d118286ab6a98e84fc75 (patch) | |
tree | 4b9e501bb71969c0ca5049201aeae42284ac9b80 | |
parent | 53a1e46e559b00653eadf6f4bb5572679b0ee734 (diff) | |
download | frameworks_av-cd04484f4837b8ca0041d118286ab6a98e84fc75.zip frameworks_av-cd04484f4837b8ca0041d118286ab6a98e84fc75.tar.gz frameworks_av-cd04484f4837b8ca0041d118286ab6a98e84fc75.tar.bz2 |
Extend downsampling ratios greater than 2:1
Also improve robustness to choice of sampling rate or buffer size
such that increasing either by 10x does not cause overflow.
Bug: 12979141
Bug: 15933066
Change-Id: If7989bd745d1bee3bdf811b8b7c978543ccafb65
-rw-r--r-- | include/media/AudioResamplerPublic.h | 29 | ||||
-rw-r--r-- | media/libmedia/AudioTrack.cpp | 8 | ||||
-rw-r--r-- | services/audioflinger/AudioResamplerDyn.cpp | 2 | ||||
-rw-r--r-- | services/audioflinger/Threads.cpp | 6 |
4 files changed, 37 insertions, 8 deletions
diff --git a/include/media/AudioResamplerPublic.h b/include/media/AudioResamplerPublic.h new file mode 100644 index 0000000..97847a0 --- /dev/null +++ b/include/media/AudioResamplerPublic.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_AUDIO_RESAMPLER_PUBLIC_H +#define ANDROID_AUDIO_RESAMPLER_PUBLIC_H + +// AUDIO_RESAMPLER_DOWN_RATIO_MAX is the maximum ratio between the original +// audio sample rate and the target rate when downsampling, +// as permitted in the audio framework, e.g. AudioTrack and AudioFlinger. +// In practice, it is not recommended to downsample more than 6:1 +// for best audio quality, even though the audio framework permits a larger +// downsampling ratio. +// TODO: replace with an API +#define AUDIO_RESAMPLER_DOWN_RATIO_MAX 256 + +#endif // ANDROID_AUDIO_RESAMPLER_PUBLIC_H diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index b5c9125..d87e6f5 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -28,6 +28,7 @@ #include <utils/Log.h> #include <private/media/AudioTrackShared.h> #include <media/IAudioFlinger.h> +#include <media/AudioResamplerPublic.h> #define WAIT_PERIOD_MS 10 #define WAIT_STREAM_END_TIMEOUT_SEC 120 @@ -82,7 +83,7 @@ status_t AudioTrack::getMinFrameCount( } *frameCount = (sampleRate == 0) ? afFrameCount * minBufCount : - afFrameCount * minBufCount * sampleRate / afSampleRate; + afFrameCount * minBufCount * uint64_t(sampleRate) / afSampleRate; // The formula above should always produce a non-zero value, but return an error // in the unlikely event that it does not, as that's part of the API contract. if (*frameCount == 0) { @@ -646,8 +647,7 @@ status_t AudioTrack::setSampleRate(uint32_t rate) if (AudioSystem::getOutputSamplingRateForAttr(&afSamplingRate, &mAttributes) != NO_ERROR) { return NO_INIT; } - // Resampler implementation limits input sampling rate to 2 x output sampling rate. - if (rate == 0 || rate > afSamplingRate*2 ) { + if (rate == 0 || rate > afSamplingRate * AUDIO_RESAMPLER_DOWN_RATIO_MAX) { return BAD_VALUE; } @@ -1002,7 +1002,7 @@ status_t AudioTrack::createTrack_l(size_t epoch) minBufCount = nBuffering; } - size_t minFrameCount = (afFrameCount*mSampleRate*minBufCount)/afSampleRate; + size_t minFrameCount = afFrameCount * minBufCount * uint64_t(mSampleRate) / afSampleRate; ALOGV("minFrameCount: %zu, afFrameCount=%zu, minBufCount=%d, sampleRate=%u, afSampleRate=%u" ", afLatency=%d", minFrameCount, afFrameCount, minBufCount, mSampleRate, afSampleRate, afLatency); diff --git a/services/audioflinger/AudioResamplerDyn.cpp b/services/audioflinger/AudioResamplerDyn.cpp index 159ab70..0eeb201 100644 --- a/services/audioflinger/AudioResamplerDyn.cpp +++ b/services/audioflinger/AudioResamplerDyn.cpp @@ -393,7 +393,7 @@ void AudioResamplerDyn<TC, TI, TO>::setSampleRate(int32_t inSampleRate) mPhaseFraction = static_cast<unsigned long long>(mPhaseFraction) * phaseWrapLimit / oldPhaseWrapLimit; mPhaseFraction %= phaseWrapLimit; // should not do anything, but just in case. - mPhaseIncrement = static_cast<uint32_t>(static_cast<double>(phaseWrapLimit) + mPhaseIncrement = static_cast<uint32_t>(static_cast<uint64_t>(phaseWrapLimit) * inSampleRate / mSampleRate); // determine which resampler to use diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index 7d583bb..30cebf4 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -26,6 +26,7 @@ #include <sys/stat.h> #include <cutils/properties.h> #include <media/AudioParameter.h> +#include <media/AudioResamplerPublic.h> #include <utils/Log.h> #include <utils/Trace.h> @@ -1479,8 +1480,7 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrac lStatus = BAD_VALUE; goto Exit; } - // Resampler implementation limits input sampling rate to 2 x output sampling rate. - if (sampleRate > mSampleRate*2) { + if (sampleRate > mSampleRate * AUDIO_RESAMPLER_DOWN_RATIO_MAX) { ALOGE("Sample rate out of range: %u mSampleRate %u", sampleRate, mSampleRate); lStatus = BAD_VALUE; goto Exit; @@ -3500,7 +3500,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac AudioMixer::TRACK, AudioMixer::MIXER_CHANNEL_MASK, (void *)(uintptr_t)mChannelMask); // limit track sample rate to 2 x output sample rate, which changes at re-configuration - uint32_t maxSampleRate = mSampleRate * 2; + uint32_t maxSampleRate = mSampleRate * AUDIO_RESAMPLER_DOWN_RATIO_MAX; uint32_t reqSampleRate = track->mAudioTrackServerProxy->getSampleRate(); if (reqSampleRate == 0) { reqSampleRate = mSampleRate; |