summaryrefslogtreecommitdiffstats
path: root/media/libmedia/AudioTrack.cpp
diff options
context:
space:
mode:
authorAndy Hung <hunga@google.com>2015-04-15 21:56:53 -0700
committerAndy Hung <hunga@google.com>2015-04-16 09:58:43 -0700
commit26145643ce22d797b3b1675c82c47a2d8c79ecaa (patch)
tree746a243e80e1ac95086b825999822cbdf2302c1d /media/libmedia/AudioTrack.cpp
parentc44111b22c26236cb0b32d3fbd1cc9fad3fb28ff (diff)
downloadframeworks_av-26145643ce22d797b3b1675c82c47a2d8c79ecaa.zip
frameworks_av-26145643ce22d797b3b1675c82c47a2d8c79ecaa.tar.gz
frameworks_av-26145643ce22d797b3b1675c82c47a2d8c79ecaa.tar.bz2
Work around lack of pitch adjustment in Timestretcher
Change-Id: I3e057b97c250a826133248b6aa1ff9ed677d88df
Diffstat (limited to 'media/libmedia/AudioTrack.cpp')
-rw-r--r--media/libmedia/AudioTrack.cpp52
1 files changed, 40 insertions, 12 deletions
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index d32db7c..30d4355 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -56,6 +56,24 @@ static int64_t getNowUs()
return convertTimespecToUs(tv);
}
+// FIXME: we don't use the pitch setting in the time stretcher (not working);
+// instead we emulate it using our sample rate converter.
+static const bool kFixPitch = true; // enable pitch fix
+static inline uint32_t adjustSampleRate(uint32_t sampleRate, float pitch)
+{
+ return kFixPitch ? (sampleRate * pitch + 0.5) : sampleRate;
+}
+
+static inline float adjustSpeed(float speed, float pitch)
+{
+ return kFixPitch ? (speed / pitch) : speed;
+}
+
+static inline float adjustPitch(float pitch)
+{
+ return kFixPitch ? AUDIO_TIMESTRETCH_PITCH_NORMAL : pitch;
+}
+
// Must match similar computation in createTrack_l in Threads.cpp.
// TODO: Move to a common library
static size_t calculateMinFrameCount(
@@ -703,13 +721,15 @@ status_t AudioTrack::setSampleRate(uint32_t rate)
if (AudioSystem::getSamplingRate(mOutput, &afSamplingRate) != NO_ERROR) {
return NO_INIT;
}
- if (rate == 0 || rate > afSamplingRate * AUDIO_RESAMPLER_DOWN_RATIO_MAX) {
+ // pitch is emulated by adjusting speed and sampleRate
+ const uint32_t effectiveSampleRate = adjustSampleRate(rate, mPitch);
+ if (rate == 0 || effectiveSampleRate > afSamplingRate * AUDIO_RESAMPLER_DOWN_RATIO_MAX) {
return BAD_VALUE;
}
// TODO: Should we also check if the buffer size is compatible?
mSampleRate = rate;
- mProxy->setSampleRate(rate);
+ mProxy->setSampleRate(effectiveSampleRate);
return NO_ERROR;
}
@@ -739,12 +759,6 @@ uint32_t AudioTrack::getSampleRate() const
status_t AudioTrack::setPlaybackRate(float speed, float pitch)
{
- if (speed < AUDIO_TIMESTRETCH_SPEED_MIN
- || speed > AUDIO_TIMESTRETCH_SPEED_MAX
- || pitch < AUDIO_TIMESTRETCH_PITCH_MIN
- || pitch > AUDIO_TIMESTRETCH_PITCH_MAX) {
- return BAD_VALUE;
- }
AutoMutex lock(mLock);
if (speed == mSpeed && pitch == mPitch) {
return NO_ERROR;
@@ -755,14 +769,25 @@ status_t AudioTrack::setPlaybackRate(float speed, float pitch)
if (mFlags & AUDIO_OUTPUT_FLAG_FAST) {
return INVALID_OPERATION;
}
+ // pitch is emulated by adjusting speed and sampleRate
+ const uint32_t effectiveRate = adjustSampleRate(mSampleRate, pitch);
+ const float effectiveSpeed = adjustSpeed(speed, pitch);
+ const float effectivePitch = adjustPitch(pitch);
+ if (effectiveSpeed < AUDIO_TIMESTRETCH_SPEED_MIN
+ || effectiveSpeed > AUDIO_TIMESTRETCH_SPEED_MAX
+ || effectivePitch < AUDIO_TIMESTRETCH_PITCH_MIN
+ || effectivePitch > AUDIO_TIMESTRETCH_PITCH_MAX) {
+ return BAD_VALUE;
+ }
// Check if the buffer size is compatible.
- if (!isSampleRateSpeedAllowed_l(mSampleRate, speed)) {
+ if (!isSampleRateSpeedAllowed_l(effectiveRate, effectiveSpeed)) {
ALOGV("setPlaybackRate(%f, %f) failed", speed, pitch);
return BAD_VALUE;
}
mSpeed = speed;
mPitch = pitch;
- mProxy->setPlaybackRate(speed, pitch);
+ mProxy->setPlaybackRate(effectiveSpeed, effectivePitch);
+ mProxy->setSampleRate(effectiveRate); // FIXME: not quite "atomic" with setPlaybackRate
return NO_ERROR;
}
@@ -1317,8 +1342,11 @@ status_t AudioTrack::createTrack_l()
gain_from_float(mVolume[AUDIO_INTERLEAVE_RIGHT])));
mProxy->setSendLevel(mSendLevel);
- mProxy->setSampleRate(mSampleRate);
- mProxy->setPlaybackRate(mSpeed, mPitch);
+ const uint32_t effectiveSampleRate = adjustSampleRate(mSampleRate, mPitch);
+ const float effectiveSpeed = adjustSpeed(mSpeed, mPitch);
+ const float effectivePitch = adjustPitch(mPitch);
+ mProxy->setSampleRate(effectiveSampleRate);
+ mProxy->setPlaybackRate(effectiveSpeed, effectivePitch);
mProxy->setMinimum(mNotificationFramesAct);
mDeathNotifier = new DeathNotifier(this);