Loading include/media/AudioResamplerPublic.h +74 −4 Original line number Diff line number Diff line Loading @@ -18,6 +18,9 @@ #define ANDROID_AUDIO_RESAMPLER_PUBLIC_H #include <stdint.h> #include <math.h> namespace android { // AUDIO_RESAMPLER_DOWN_RATIO_MAX is the maximum ratio between the original // audio sample rate and the target rate when downsampling, Loading @@ -34,13 +37,76 @@ // an int32_t of the phase increments, making the resulting sample rate inexact. #define AUDIO_RESAMPLER_UP_RATIO_MAX 65536 #define AUDIO_TIMESTRETCH_SPEED_MIN 0.5f #define AUDIO_TIMESTRETCH_SPEED_MAX 2.0f // AUDIO_TIMESTRETCH_SPEED_MIN and AUDIO_TIMESTRETCH_SPEED_MAX define the min and max time stretch // speeds supported by the system. These are enforced by the system and values outside this range // will result in a runtime error. // Depending on the AudioPlaybackRate::mStretchMode, the effective limits might be narrower than // the ones specified here // AUDIO_TIMESTRETCH_SPEED_MIN_DELTA is the minimum absolute speed difference that might trigger a // parameter update #define AUDIO_TIMESTRETCH_SPEED_MIN 0.01f #define AUDIO_TIMESTRETCH_SPEED_MAX 20.0f #define AUDIO_TIMESTRETCH_SPEED_NORMAL 1.0f #define AUDIO_TIMESTRETCH_SPEED_MIN_DELTA 0.0001f #define AUDIO_TIMESTRETCH_PITCH_MIN 0.5f #define AUDIO_TIMESTRETCH_PITCH_MAX 2.0f // AUDIO_TIMESTRETCH_PITCH_MIN and AUDIO_TIMESTRETCH_PITCH_MAX define the min and max time stretch // pitch shifting supported by the system. These are not enforced by the system and values // outside this range might result in a pitch different than the one requested. // Depending on the AudioPlaybackRate::mStretchMode, the effective limits might be narrower than // the ones specified here. // AUDIO_TIMESTRETCH_PITCH_MIN_DELTA is the minimum absolute pitch difference that might trigger a // parameter update #define AUDIO_TIMESTRETCH_PITCH_MIN 0.25f #define AUDIO_TIMESTRETCH_PITCH_MAX 4.0f #define AUDIO_TIMESTRETCH_PITCH_NORMAL 1.0f #define AUDIO_TIMESTRETCH_PITCH_MIN_DELTA 0.0001f //Determines the current algorithm used for stretching enum AudioTimestretchStretchMode : int32_t { AUDIO_TIMESTRETCH_STRETCH_DEFAULT = 0, AUDIO_TIMESTRETCH_STRETCH_SPEECH = 1, //TODO: add more stretch modes/algorithms }; //Limits for AUDIO_TIMESTRETCH_STRETCH_SPEECH mode #define TIMESTRETCH_SONIC_SPEED_MIN 0.1f #define TIMESTRETCH_SONIC_SPEED_MAX 6.0f //Determines behavior of Timestretch if current algorithm can't perform //with current parameters. // FALLBACK_CUT_REPEAT: (internal only) for speed <1.0 will truncate frames // for speed > 1.0 will repeat frames // FALLBACK_MUTE: will set all processed frames to zero // FALLBACK_FAIL: will stop program execution and log a fatal error enum AudioTimestretchFallbackMode : int32_t { AUDIO_TIMESTRETCH_FALLBACK_CUT_REPEAT = -1, AUDIO_TIMESTRETCH_FALLBACK_DEFAULT = 0, AUDIO_TIMESTRETCH_FALLBACK_MUTE = 1, AUDIO_TIMESTRETCH_FALLBACK_FAIL = 2, }; struct AudioPlaybackRate { float mSpeed; float mPitch; enum AudioTimestretchStretchMode mStretchMode; enum AudioTimestretchFallbackMode mFallbackMode; }; static const AudioPlaybackRate AUDIO_PLAYBACK_RATE_DEFAULT = { AUDIO_TIMESTRETCH_SPEED_NORMAL, AUDIO_TIMESTRETCH_PITCH_NORMAL, AUDIO_TIMESTRETCH_STRETCH_DEFAULT, AUDIO_TIMESTRETCH_FALLBACK_DEFAULT }; static inline bool isAudioPlaybackRateEqual(const AudioPlaybackRate &pr1, const AudioPlaybackRate &pr2) { return fabs(pr1.mSpeed - pr2.mSpeed) < AUDIO_TIMESTRETCH_SPEED_MIN_DELTA && fabs(pr1.mPitch - pr2.mPitch) < AUDIO_TIMESTRETCH_PITCH_MIN_DELTA && pr2.mStretchMode == pr2.mStretchMode && pr2.mFallbackMode == pr2.mFallbackMode; } // TODO: Consider putting these inlines into a class scope Loading Loading @@ -77,4 +143,8 @@ static inline size_t sourceFramesNeededWithTimestretch( return required * (double)speed + 1 + 1; // accounting for rounding dependencies } } // namespace android // --------------------------------------------------------------------------- #endif // ANDROID_AUDIO_RESAMPLER_PUBLIC_H include/media/AudioTrack.h +4 −4 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include <media/AudioSystem.h> #include <media/AudioTimestamp.h> #include <media/IAudioTrack.h> #include <media/AudioResamplerPublic.h> #include <utils/threads.h> namespace android { Loading Loading @@ -369,10 +370,10 @@ public: * Speed increases the playback rate of media, but does not alter pitch. * Pitch increases the "tonal frequency" of media, but does not affect the playback rate. */ status_t setPlaybackRate(float speed, float pitch); status_t setPlaybackRate(const AudioPlaybackRate &playbackRate); /* Return current playback rate */ void getPlaybackRate(float *speed, float *pitch) const; const AudioPlaybackRate& getPlaybackRate() const; /* Enables looping and sets the start and end points of looping. * Only supported for static buffer mode. Loading Loading @@ -748,8 +749,7 @@ protected: float mVolume[2]; float mSendLevel; mutable uint32_t mSampleRate; // mutable because getSampleRate() can update it float mSpeed; // timestretch: 1.0f for normal speed. float mPitch; // timestretch: 1.0f for normal pitch. AudioPlaybackRate mPlaybackRate; size_t mFrameCount; // corresponds to current IAudioTrack, value is // reported back by AudioFlinger to the client size_t mReqFrameCount; // frame count to request the first or next time Loading include/private/media/AudioTrackShared.h +8 −18 Original line number Diff line number Diff line Loading @@ -114,13 +114,7 @@ struct AudioTrackSharedStatic { mPosLoopQueue; }; struct AudioTrackPlaybackRate { float mSpeed; float mPitch; }; typedef SingleStateQueue<AudioTrackPlaybackRate> AudioTrackPlaybackRateQueue; typedef SingleStateQueue<AudioPlaybackRate> PlaybackRateQueue; // ---------------------------------------------------------------------------- Loading Loading @@ -168,7 +162,7 @@ private: uint32_t mSampleRate; // AudioTrack only: client's requested sample rate in Hz // or 0 == default. Write-only client, read-only server. AudioTrackPlaybackRateQueue::Shared mPlaybackRateQueue; PlaybackRateQueue::Shared mPlaybackRateQueue; // client write-only, server read-only uint16_t mSendLevel; // Fixed point U4.12 so 0x1000 means 1.0 Loading Loading @@ -345,10 +339,7 @@ public: mCblk->mSampleRate = sampleRate; } void setPlaybackRate(float speed, float pitch) { AudioTrackPlaybackRate playbackRate; playbackRate.mSpeed = speed; playbackRate.mPitch = pitch; void setPlaybackRate(const AudioPlaybackRate& playbackRate) { mPlaybackRateMutator.push(playbackRate); } Loading @@ -365,7 +356,7 @@ public: status_t waitStreamEndDone(const struct timespec *requested); private: AudioTrackPlaybackRateQueue::Mutator mPlaybackRateMutator; PlaybackRateQueue::Mutator mPlaybackRateMutator; }; class StaticAudioTrackClientProxy : public AudioTrackClientProxy { Loading Loading @@ -483,8 +474,7 @@ public: : ServerProxy(cblk, buffers, frameCount, frameSize, true /*isOut*/, clientInServer), mPlaybackRateObserver(&cblk->mPlaybackRateQueue) { mCblk->mSampleRate = sampleRate; mPlaybackRate.mSpeed = AUDIO_TIMESTRETCH_SPEED_NORMAL; mPlaybackRate.mPitch = AUDIO_TIMESTRETCH_PITCH_NORMAL; mPlaybackRate = AUDIO_PLAYBACK_RATE_DEFAULT; } protected: virtual ~AudioTrackServerProxy() { } Loading Loading @@ -520,11 +510,11 @@ public: virtual size_t framesReleased() const { return mCblk->mServer; } // Return the playback speed and pitch read atomically. Not multi-thread safe on server side. void getPlaybackRate(float *speed, float *pitch); AudioPlaybackRate getPlaybackRate(); private: AudioTrackPlaybackRate mPlaybackRate; // last observed playback rate AudioTrackPlaybackRateQueue::Observer mPlaybackRateObserver; AudioPlaybackRate mPlaybackRate; // last observed playback rate PlaybackRateQueue::Observer mPlaybackRateObserver; }; class StaticAudioTrackServerProxy : public AudioTrackServerProxy { Loading media/libmedia/AudioTrack.cpp +32 −23 Original line number Diff line number Diff line Loading @@ -393,8 +393,7 @@ status_t AudioTrack::set( return BAD_VALUE; } mSampleRate = sampleRate; mSpeed = AUDIO_TIMESTRETCH_SPEED_NORMAL; mPitch = AUDIO_TIMESTRETCH_PITCH_NORMAL; mPlaybackRate = AUDIO_PLAYBACK_RATE_DEFAULT; // Make copy of input parameter offloadInfo so that in the future: // (a) createTrack_l doesn't need it as an input parameter Loading Loading @@ -722,7 +721,7 @@ status_t AudioTrack::setSampleRate(uint32_t rate) return NO_INIT; } // pitch is emulated by adjusting speed and sampleRate const uint32_t effectiveSampleRate = adjustSampleRate(rate, mPitch); const uint32_t effectiveSampleRate = adjustSampleRate(rate, mPlaybackRate.mPitch); if (rate == 0 || effectiveSampleRate > afSamplingRate * AUDIO_RESAMPLER_DOWN_RATIO_MAX) { return BAD_VALUE; } Loading Loading @@ -757,10 +756,10 @@ uint32_t AudioTrack::getSampleRate() const return mSampleRate; } status_t AudioTrack::setPlaybackRate(float speed, float pitch) status_t AudioTrack::setPlaybackRate(const AudioPlaybackRate &playbackRate) { AutoMutex lock(mLock); if (speed == mSpeed && pitch == mPitch) { if (isAudioPlaybackRateEqual(playbackRate, mPlaybackRate)) { return NO_ERROR; } if (mIsTimed || isOffloadedOrDirect_l()) { Loading @@ -770,32 +769,37 @@ status_t AudioTrack::setPlaybackRate(float speed, float pitch) 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); const uint32_t effectiveRate = adjustSampleRate(mSampleRate, playbackRate.mPitch); const float effectiveSpeed = adjustSpeed(playbackRate.mSpeed, playbackRate.mPitch); const float effectivePitch = adjustPitch(playbackRate.mPitch); if (effectiveSpeed < AUDIO_TIMESTRETCH_SPEED_MIN || effectiveSpeed > AUDIO_TIMESTRETCH_SPEED_MAX || effectivePitch < AUDIO_TIMESTRETCH_PITCH_MIN || effectivePitch > AUDIO_TIMESTRETCH_PITCH_MAX) { return BAD_VALUE; //TODO: add function in AudioResamplerPublic.h to check for validity. } // Check if the buffer size is compatible. if (!isSampleRateSpeedAllowed_l(effectiveRate, effectiveSpeed)) { ALOGV("setPlaybackRate(%f, %f) failed", speed, pitch); ALOGV("setPlaybackRate(%f, %f) failed", playbackRate.mSpeed, playbackRate.mPitch); return BAD_VALUE; } mSpeed = speed; mPitch = pitch; mProxy->setPlaybackRate(effectiveSpeed, effectivePitch); mPlaybackRate = playbackRate; mProxy->setPlaybackRate(playbackRate); //modify this AudioPlaybackRate playbackRateTemp = playbackRate; playbackRateTemp.mSpeed = effectiveSpeed; playbackRateTemp.mPitch = effectivePitch; mProxy->setPlaybackRate(playbackRateTemp); mProxy->setSampleRate(effectiveRate); // FIXME: not quite "atomic" with setPlaybackRate return NO_ERROR; } void AudioTrack::getPlaybackRate(float *speed, float *pitch) const const AudioPlaybackRate& AudioTrack::getPlaybackRate() const { AutoMutex lock(mLock); *speed = mSpeed; *pitch = mPitch; return mPlaybackRate; } status_t AudioTrack::setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount) Loading Loading @@ -1169,7 +1173,8 @@ status_t AudioTrack::createTrack_l() if ((mFlags & AUDIO_OUTPUT_FLAG_FAST) == 0) { // for normal tracks precompute the frame count based on speed. const size_t minFrameCount = calculateMinFrameCount( afLatency, afFrameCount, afSampleRate, mSampleRate, mSpeed); afLatency, afFrameCount, afSampleRate, mSampleRate, mPlaybackRate.mSpeed); if (frameCount < minFrameCount) { frameCount = minFrameCount; } Loading Loading @@ -1341,11 +1346,15 @@ status_t AudioTrack::createTrack_l() gain_from_float(mVolume[AUDIO_INTERLEAVE_RIGHT]))); mProxy->setSendLevel(mSendLevel); const uint32_t effectiveSampleRate = adjustSampleRate(mSampleRate, mPitch); const float effectiveSpeed = adjustSpeed(mSpeed, mPitch); const float effectivePitch = adjustPitch(mPitch); const uint32_t effectiveSampleRate = adjustSampleRate(mSampleRate, mPlaybackRate.mPitch); const float effectiveSpeed = adjustSpeed(mPlaybackRate.mSpeed, mPlaybackRate.mPitch); const float effectivePitch = adjustPitch(mPlaybackRate.mPitch); mProxy->setSampleRate(effectiveSampleRate); mProxy->setPlaybackRate(effectiveSpeed, effectivePitch); AudioPlaybackRate playbackRateTemp = mPlaybackRate; playbackRateTemp.mSpeed = effectiveSpeed; playbackRateTemp.mPitch = effectivePitch; mProxy->setPlaybackRate(playbackRateTemp); mProxy->setMinimum(mNotificationFramesAct); mDeathNotifier = new DeathNotifier(this); Loading Loading @@ -1715,7 +1724,7 @@ nsecs_t AudioTrack::processAudioBuffer() // Cache other fields that will be needed soon uint32_t sampleRate = mSampleRate; float speed = mSpeed; float speed = mPlaybackRate.mSpeed; uint32_t notificationFrames = mNotificationFramesAct; if (mRefreshRemaining) { mRefreshRemaining = false; Loading Loading @@ -2137,7 +2146,7 @@ status_t AudioTrack::getTimestamp(AudioTimestamp& timestamp) } const int64_t deltaTimeUs = timestampTimeUs - mStartUs; const int64_t deltaPositionByUs = (double)timestamp.mPosition * 1000000 / ((double)mSampleRate * mSpeed); / ((double)mSampleRate * mPlaybackRate.mSpeed); if (deltaPositionByUs > deltaTimeUs + kTimeJitterUs) { // Verify that the counter can't count faster than the sample rate Loading Loading @@ -2225,7 +2234,7 @@ status_t AudioTrack::dump(int fd, const Vector<String16>& args __unused) const mChannelCount, mFrameCount); result.append(buffer); snprintf(buffer, 255, " sample rate(%u), speed(%f), status(%d)\n", mSampleRate, mSpeed, mStatus); mSampleRate, mPlaybackRate.mSpeed, mStatus); result.append(buffer); snprintf(buffer, 255, " state(%d), latency (%d)\n", mState, mLatency); result.append(buffer); Loading media/libmedia/AudioTrackShared.cpp +3 −7 Original line number Diff line number Diff line Loading @@ -794,14 +794,10 @@ void AudioTrackServerProxy::tallyUnderrunFrames(uint32_t frameCount) (void) android_atomic_or(CBLK_UNDERRUN, &cblk->mFlags); } void AudioTrackServerProxy::getPlaybackRate(float *speed, float *pitch) AudioPlaybackRate AudioTrackServerProxy::getPlaybackRate() { // do not call from multiple threads without holding lock AudioTrackPlaybackRate playbackRate; if (mPlaybackRateObserver.poll(playbackRate)) { mPlaybackRate = playbackRate; } *speed = mPlaybackRate.mSpeed; *pitch = mPlaybackRate.mPitch; mPlaybackRateObserver.poll(mPlaybackRate); return mPlaybackRate; } // --------------------------------------------------------------------------- Loading Loading
include/media/AudioResamplerPublic.h +74 −4 Original line number Diff line number Diff line Loading @@ -18,6 +18,9 @@ #define ANDROID_AUDIO_RESAMPLER_PUBLIC_H #include <stdint.h> #include <math.h> namespace android { // AUDIO_RESAMPLER_DOWN_RATIO_MAX is the maximum ratio between the original // audio sample rate and the target rate when downsampling, Loading @@ -34,13 +37,76 @@ // an int32_t of the phase increments, making the resulting sample rate inexact. #define AUDIO_RESAMPLER_UP_RATIO_MAX 65536 #define AUDIO_TIMESTRETCH_SPEED_MIN 0.5f #define AUDIO_TIMESTRETCH_SPEED_MAX 2.0f // AUDIO_TIMESTRETCH_SPEED_MIN and AUDIO_TIMESTRETCH_SPEED_MAX define the min and max time stretch // speeds supported by the system. These are enforced by the system and values outside this range // will result in a runtime error. // Depending on the AudioPlaybackRate::mStretchMode, the effective limits might be narrower than // the ones specified here // AUDIO_TIMESTRETCH_SPEED_MIN_DELTA is the minimum absolute speed difference that might trigger a // parameter update #define AUDIO_TIMESTRETCH_SPEED_MIN 0.01f #define AUDIO_TIMESTRETCH_SPEED_MAX 20.0f #define AUDIO_TIMESTRETCH_SPEED_NORMAL 1.0f #define AUDIO_TIMESTRETCH_SPEED_MIN_DELTA 0.0001f #define AUDIO_TIMESTRETCH_PITCH_MIN 0.5f #define AUDIO_TIMESTRETCH_PITCH_MAX 2.0f // AUDIO_TIMESTRETCH_PITCH_MIN and AUDIO_TIMESTRETCH_PITCH_MAX define the min and max time stretch // pitch shifting supported by the system. These are not enforced by the system and values // outside this range might result in a pitch different than the one requested. // Depending on the AudioPlaybackRate::mStretchMode, the effective limits might be narrower than // the ones specified here. // AUDIO_TIMESTRETCH_PITCH_MIN_DELTA is the minimum absolute pitch difference that might trigger a // parameter update #define AUDIO_TIMESTRETCH_PITCH_MIN 0.25f #define AUDIO_TIMESTRETCH_PITCH_MAX 4.0f #define AUDIO_TIMESTRETCH_PITCH_NORMAL 1.0f #define AUDIO_TIMESTRETCH_PITCH_MIN_DELTA 0.0001f //Determines the current algorithm used for stretching enum AudioTimestretchStretchMode : int32_t { AUDIO_TIMESTRETCH_STRETCH_DEFAULT = 0, AUDIO_TIMESTRETCH_STRETCH_SPEECH = 1, //TODO: add more stretch modes/algorithms }; //Limits for AUDIO_TIMESTRETCH_STRETCH_SPEECH mode #define TIMESTRETCH_SONIC_SPEED_MIN 0.1f #define TIMESTRETCH_SONIC_SPEED_MAX 6.0f //Determines behavior of Timestretch if current algorithm can't perform //with current parameters. // FALLBACK_CUT_REPEAT: (internal only) for speed <1.0 will truncate frames // for speed > 1.0 will repeat frames // FALLBACK_MUTE: will set all processed frames to zero // FALLBACK_FAIL: will stop program execution and log a fatal error enum AudioTimestretchFallbackMode : int32_t { AUDIO_TIMESTRETCH_FALLBACK_CUT_REPEAT = -1, AUDIO_TIMESTRETCH_FALLBACK_DEFAULT = 0, AUDIO_TIMESTRETCH_FALLBACK_MUTE = 1, AUDIO_TIMESTRETCH_FALLBACK_FAIL = 2, }; struct AudioPlaybackRate { float mSpeed; float mPitch; enum AudioTimestretchStretchMode mStretchMode; enum AudioTimestretchFallbackMode mFallbackMode; }; static const AudioPlaybackRate AUDIO_PLAYBACK_RATE_DEFAULT = { AUDIO_TIMESTRETCH_SPEED_NORMAL, AUDIO_TIMESTRETCH_PITCH_NORMAL, AUDIO_TIMESTRETCH_STRETCH_DEFAULT, AUDIO_TIMESTRETCH_FALLBACK_DEFAULT }; static inline bool isAudioPlaybackRateEqual(const AudioPlaybackRate &pr1, const AudioPlaybackRate &pr2) { return fabs(pr1.mSpeed - pr2.mSpeed) < AUDIO_TIMESTRETCH_SPEED_MIN_DELTA && fabs(pr1.mPitch - pr2.mPitch) < AUDIO_TIMESTRETCH_PITCH_MIN_DELTA && pr2.mStretchMode == pr2.mStretchMode && pr2.mFallbackMode == pr2.mFallbackMode; } // TODO: Consider putting these inlines into a class scope Loading Loading @@ -77,4 +143,8 @@ static inline size_t sourceFramesNeededWithTimestretch( return required * (double)speed + 1 + 1; // accounting for rounding dependencies } } // namespace android // --------------------------------------------------------------------------- #endif // ANDROID_AUDIO_RESAMPLER_PUBLIC_H
include/media/AudioTrack.h +4 −4 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include <media/AudioSystem.h> #include <media/AudioTimestamp.h> #include <media/IAudioTrack.h> #include <media/AudioResamplerPublic.h> #include <utils/threads.h> namespace android { Loading Loading @@ -369,10 +370,10 @@ public: * Speed increases the playback rate of media, but does not alter pitch. * Pitch increases the "tonal frequency" of media, but does not affect the playback rate. */ status_t setPlaybackRate(float speed, float pitch); status_t setPlaybackRate(const AudioPlaybackRate &playbackRate); /* Return current playback rate */ void getPlaybackRate(float *speed, float *pitch) const; const AudioPlaybackRate& getPlaybackRate() const; /* Enables looping and sets the start and end points of looping. * Only supported for static buffer mode. Loading Loading @@ -748,8 +749,7 @@ protected: float mVolume[2]; float mSendLevel; mutable uint32_t mSampleRate; // mutable because getSampleRate() can update it float mSpeed; // timestretch: 1.0f for normal speed. float mPitch; // timestretch: 1.0f for normal pitch. AudioPlaybackRate mPlaybackRate; size_t mFrameCount; // corresponds to current IAudioTrack, value is // reported back by AudioFlinger to the client size_t mReqFrameCount; // frame count to request the first or next time Loading
include/private/media/AudioTrackShared.h +8 −18 Original line number Diff line number Diff line Loading @@ -114,13 +114,7 @@ struct AudioTrackSharedStatic { mPosLoopQueue; }; struct AudioTrackPlaybackRate { float mSpeed; float mPitch; }; typedef SingleStateQueue<AudioTrackPlaybackRate> AudioTrackPlaybackRateQueue; typedef SingleStateQueue<AudioPlaybackRate> PlaybackRateQueue; // ---------------------------------------------------------------------------- Loading Loading @@ -168,7 +162,7 @@ private: uint32_t mSampleRate; // AudioTrack only: client's requested sample rate in Hz // or 0 == default. Write-only client, read-only server. AudioTrackPlaybackRateQueue::Shared mPlaybackRateQueue; PlaybackRateQueue::Shared mPlaybackRateQueue; // client write-only, server read-only uint16_t mSendLevel; // Fixed point U4.12 so 0x1000 means 1.0 Loading Loading @@ -345,10 +339,7 @@ public: mCblk->mSampleRate = sampleRate; } void setPlaybackRate(float speed, float pitch) { AudioTrackPlaybackRate playbackRate; playbackRate.mSpeed = speed; playbackRate.mPitch = pitch; void setPlaybackRate(const AudioPlaybackRate& playbackRate) { mPlaybackRateMutator.push(playbackRate); } Loading @@ -365,7 +356,7 @@ public: status_t waitStreamEndDone(const struct timespec *requested); private: AudioTrackPlaybackRateQueue::Mutator mPlaybackRateMutator; PlaybackRateQueue::Mutator mPlaybackRateMutator; }; class StaticAudioTrackClientProxy : public AudioTrackClientProxy { Loading Loading @@ -483,8 +474,7 @@ public: : ServerProxy(cblk, buffers, frameCount, frameSize, true /*isOut*/, clientInServer), mPlaybackRateObserver(&cblk->mPlaybackRateQueue) { mCblk->mSampleRate = sampleRate; mPlaybackRate.mSpeed = AUDIO_TIMESTRETCH_SPEED_NORMAL; mPlaybackRate.mPitch = AUDIO_TIMESTRETCH_PITCH_NORMAL; mPlaybackRate = AUDIO_PLAYBACK_RATE_DEFAULT; } protected: virtual ~AudioTrackServerProxy() { } Loading Loading @@ -520,11 +510,11 @@ public: virtual size_t framesReleased() const { return mCblk->mServer; } // Return the playback speed and pitch read atomically. Not multi-thread safe on server side. void getPlaybackRate(float *speed, float *pitch); AudioPlaybackRate getPlaybackRate(); private: AudioTrackPlaybackRate mPlaybackRate; // last observed playback rate AudioTrackPlaybackRateQueue::Observer mPlaybackRateObserver; AudioPlaybackRate mPlaybackRate; // last observed playback rate PlaybackRateQueue::Observer mPlaybackRateObserver; }; class StaticAudioTrackServerProxy : public AudioTrackServerProxy { Loading
media/libmedia/AudioTrack.cpp +32 −23 Original line number Diff line number Diff line Loading @@ -393,8 +393,7 @@ status_t AudioTrack::set( return BAD_VALUE; } mSampleRate = sampleRate; mSpeed = AUDIO_TIMESTRETCH_SPEED_NORMAL; mPitch = AUDIO_TIMESTRETCH_PITCH_NORMAL; mPlaybackRate = AUDIO_PLAYBACK_RATE_DEFAULT; // Make copy of input parameter offloadInfo so that in the future: // (a) createTrack_l doesn't need it as an input parameter Loading Loading @@ -722,7 +721,7 @@ status_t AudioTrack::setSampleRate(uint32_t rate) return NO_INIT; } // pitch is emulated by adjusting speed and sampleRate const uint32_t effectiveSampleRate = adjustSampleRate(rate, mPitch); const uint32_t effectiveSampleRate = adjustSampleRate(rate, mPlaybackRate.mPitch); if (rate == 0 || effectiveSampleRate > afSamplingRate * AUDIO_RESAMPLER_DOWN_RATIO_MAX) { return BAD_VALUE; } Loading Loading @@ -757,10 +756,10 @@ uint32_t AudioTrack::getSampleRate() const return mSampleRate; } status_t AudioTrack::setPlaybackRate(float speed, float pitch) status_t AudioTrack::setPlaybackRate(const AudioPlaybackRate &playbackRate) { AutoMutex lock(mLock); if (speed == mSpeed && pitch == mPitch) { if (isAudioPlaybackRateEqual(playbackRate, mPlaybackRate)) { return NO_ERROR; } if (mIsTimed || isOffloadedOrDirect_l()) { Loading @@ -770,32 +769,37 @@ status_t AudioTrack::setPlaybackRate(float speed, float pitch) 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); const uint32_t effectiveRate = adjustSampleRate(mSampleRate, playbackRate.mPitch); const float effectiveSpeed = adjustSpeed(playbackRate.mSpeed, playbackRate.mPitch); const float effectivePitch = adjustPitch(playbackRate.mPitch); if (effectiveSpeed < AUDIO_TIMESTRETCH_SPEED_MIN || effectiveSpeed > AUDIO_TIMESTRETCH_SPEED_MAX || effectivePitch < AUDIO_TIMESTRETCH_PITCH_MIN || effectivePitch > AUDIO_TIMESTRETCH_PITCH_MAX) { return BAD_VALUE; //TODO: add function in AudioResamplerPublic.h to check for validity. } // Check if the buffer size is compatible. if (!isSampleRateSpeedAllowed_l(effectiveRate, effectiveSpeed)) { ALOGV("setPlaybackRate(%f, %f) failed", speed, pitch); ALOGV("setPlaybackRate(%f, %f) failed", playbackRate.mSpeed, playbackRate.mPitch); return BAD_VALUE; } mSpeed = speed; mPitch = pitch; mProxy->setPlaybackRate(effectiveSpeed, effectivePitch); mPlaybackRate = playbackRate; mProxy->setPlaybackRate(playbackRate); //modify this AudioPlaybackRate playbackRateTemp = playbackRate; playbackRateTemp.mSpeed = effectiveSpeed; playbackRateTemp.mPitch = effectivePitch; mProxy->setPlaybackRate(playbackRateTemp); mProxy->setSampleRate(effectiveRate); // FIXME: not quite "atomic" with setPlaybackRate return NO_ERROR; } void AudioTrack::getPlaybackRate(float *speed, float *pitch) const const AudioPlaybackRate& AudioTrack::getPlaybackRate() const { AutoMutex lock(mLock); *speed = mSpeed; *pitch = mPitch; return mPlaybackRate; } status_t AudioTrack::setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount) Loading Loading @@ -1169,7 +1173,8 @@ status_t AudioTrack::createTrack_l() if ((mFlags & AUDIO_OUTPUT_FLAG_FAST) == 0) { // for normal tracks precompute the frame count based on speed. const size_t minFrameCount = calculateMinFrameCount( afLatency, afFrameCount, afSampleRate, mSampleRate, mSpeed); afLatency, afFrameCount, afSampleRate, mSampleRate, mPlaybackRate.mSpeed); if (frameCount < minFrameCount) { frameCount = minFrameCount; } Loading Loading @@ -1341,11 +1346,15 @@ status_t AudioTrack::createTrack_l() gain_from_float(mVolume[AUDIO_INTERLEAVE_RIGHT]))); mProxy->setSendLevel(mSendLevel); const uint32_t effectiveSampleRate = adjustSampleRate(mSampleRate, mPitch); const float effectiveSpeed = adjustSpeed(mSpeed, mPitch); const float effectivePitch = adjustPitch(mPitch); const uint32_t effectiveSampleRate = adjustSampleRate(mSampleRate, mPlaybackRate.mPitch); const float effectiveSpeed = adjustSpeed(mPlaybackRate.mSpeed, mPlaybackRate.mPitch); const float effectivePitch = adjustPitch(mPlaybackRate.mPitch); mProxy->setSampleRate(effectiveSampleRate); mProxy->setPlaybackRate(effectiveSpeed, effectivePitch); AudioPlaybackRate playbackRateTemp = mPlaybackRate; playbackRateTemp.mSpeed = effectiveSpeed; playbackRateTemp.mPitch = effectivePitch; mProxy->setPlaybackRate(playbackRateTemp); mProxy->setMinimum(mNotificationFramesAct); mDeathNotifier = new DeathNotifier(this); Loading Loading @@ -1715,7 +1724,7 @@ nsecs_t AudioTrack::processAudioBuffer() // Cache other fields that will be needed soon uint32_t sampleRate = mSampleRate; float speed = mSpeed; float speed = mPlaybackRate.mSpeed; uint32_t notificationFrames = mNotificationFramesAct; if (mRefreshRemaining) { mRefreshRemaining = false; Loading Loading @@ -2137,7 +2146,7 @@ status_t AudioTrack::getTimestamp(AudioTimestamp& timestamp) } const int64_t deltaTimeUs = timestampTimeUs - mStartUs; const int64_t deltaPositionByUs = (double)timestamp.mPosition * 1000000 / ((double)mSampleRate * mSpeed); / ((double)mSampleRate * mPlaybackRate.mSpeed); if (deltaPositionByUs > deltaTimeUs + kTimeJitterUs) { // Verify that the counter can't count faster than the sample rate Loading Loading @@ -2225,7 +2234,7 @@ status_t AudioTrack::dump(int fd, const Vector<String16>& args __unused) const mChannelCount, mFrameCount); result.append(buffer); snprintf(buffer, 255, " sample rate(%u), speed(%f), status(%d)\n", mSampleRate, mSpeed, mStatus); mSampleRate, mPlaybackRate.mSpeed, mStatus); result.append(buffer); snprintf(buffer, 255, " state(%d), latency (%d)\n", mState, mLatency); result.append(buffer); Loading
media/libmedia/AudioTrackShared.cpp +3 −7 Original line number Diff line number Diff line Loading @@ -794,14 +794,10 @@ void AudioTrackServerProxy::tallyUnderrunFrames(uint32_t frameCount) (void) android_atomic_or(CBLK_UNDERRUN, &cblk->mFlags); } void AudioTrackServerProxy::getPlaybackRate(float *speed, float *pitch) AudioPlaybackRate AudioTrackServerProxy::getPlaybackRate() { // do not call from multiple threads without holding lock AudioTrackPlaybackRate playbackRate; if (mPlaybackRateObserver.poll(playbackRate)) { mPlaybackRate = playbackRate; } *speed = mPlaybackRate.mSpeed; *pitch = mPlaybackRate.mPitch; mPlaybackRateObserver.poll(mPlaybackRate); return mPlaybackRate; } // --------------------------------------------------------------------------- Loading