diff options
author | Andy Hung <hunga@google.com> | 2015-03-26 19:13:55 -0700 |
---|---|---|
committer | Andy Hung <hunga@google.com> | 2015-04-09 18:49:15 -0700 |
commit | 8edb8dc44b8a2f81bdb5db645b6b708548771a31 (patch) | |
tree | 663bda0f8a3d43894fa6d3d3f4283ed0df427f03 /include | |
parent | c5656cc900aeb4a705e27508dd82c70030a97709 (diff) | |
download | frameworks_av-8edb8dc44b8a2f81bdb5db645b6b708548771a31.zip frameworks_av-8edb8dc44b8a2f81bdb5db645b6b708548771a31.tar.gz frameworks_av-8edb8dc44b8a2f81bdb5db645b6b708548771a31.tar.bz2 |
Add playback rate to AudioTrack
Bug: 19196501
Change-Id: I6411e1d3ce652b711a71a6d9df020cb5f60d4714
Diffstat (limited to 'include')
-rw-r--r-- | include/media/AudioResamplerPublic.h | 11 | ||||
-rw-r--r-- | include/media/AudioTrack.h | 20 | ||||
-rw-r--r-- | include/private/media/AudioTrackShared.h | 36 |
3 files changed, 65 insertions, 2 deletions
diff --git a/include/media/AudioResamplerPublic.h b/include/media/AudioResamplerPublic.h index 3c30148..07d946d 100644 --- a/include/media/AudioResamplerPublic.h +++ b/include/media/AudioResamplerPublic.h @@ -42,6 +42,8 @@ #define AUDIO_TIMESTRETCH_PITCH_MAX 2.0f #define AUDIO_TIMESTRETCH_PITCH_NORMAL 1.0f +// TODO: Consider putting these inlines into a class scope + // Returns the source frames needed to resample to destination frames. This is not a precise // value and depends on the resampler (and possibly how it handles rounding internally). // Nevertheless, this should be an upper bound on the requirements of the resampler. @@ -66,4 +68,13 @@ static inline size_t destinationFramesPossible(size_t srcFrames, uint32_t srcSam return dstFrames > 2 ? dstFrames - 2 : 0; } +static inline size_t sourceFramesNeededWithTimestretch( + uint32_t srcSampleRate, size_t dstFramesRequired, uint32_t dstSampleRate, + float speed) { + // required is the number of input frames the resampler needs + size_t required = sourceFramesNeeded(srcSampleRate, dstFramesRequired, dstSampleRate); + // to deliver this, the time stretcher requires: + return required * (double)speed + 1 + 1; // accounting for rounding dependencies +} + #endif // ANDROID_AUDIO_RESAMPLER_PUBLIC_H diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h index e7e0703..a06197f 100644 --- a/include/media/AudioTrack.h +++ b/include/media/AudioTrack.h @@ -359,6 +359,21 @@ public: /* Return current source sample rate in Hz */ uint32_t getSampleRate() const; + /* Set source playback rate for timestretch + * 1.0 is normal speed: < 1.0 is slower, > 1.0 is faster + * 1.0 is normal pitch: < 1.0 is lower pitch, > 1.0 is higher pitch + * + * AUDIO_TIMESTRETCH_SPEED_MIN <= speed <= AUDIO_TIMESTRETCH_SPEED_MAX + * AUDIO_TIMESTRETCH_PITCH_MIN <= pitch <= AUDIO_TIMESTRETCH_PITCH_MAX + * + * 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); + + /* Return current playback rate */ + void getPlaybackRate(float *speed, float *pitch) const; + /* Enables looping and sets the start and end points of looping. * Only supported for static buffer mode. * @@ -719,6 +734,9 @@ protected: // increment mPosition by the delta of mServer, and return new value of mPosition uint32_t updateAndGetPosition_l(); + // check sample rate and speed is compatible with AudioTrack + bool isSampleRateSpeedAllowed_l(uint32_t sampleRate, float speed) const; + // Next 4 fields may be changed if IAudioTrack is re-created, but always != 0 sp<IAudioTrack> mAudioTrack; sp<IMemory> mCblkMemory; @@ -730,6 +748,8 @@ 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. 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 diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h index 5644428..6cc2e2b 100644 --- a/include/private/media/AudioTrackShared.h +++ b/include/private/media/AudioTrackShared.h @@ -25,6 +25,7 @@ #include <utils/Log.h> #include <utils/RefBase.h> #include <audio_utils/roundup.h> +#include <media/AudioResamplerPublic.h> #include <media/SingleStateQueue.h> namespace android { @@ -113,6 +114,14 @@ struct AudioTrackSharedStatic { mPosLoopQueue; }; + +struct AudioTrackPlaybackRate { + float mSpeed; + float mPitch; +}; + +typedef SingleStateQueue<AudioTrackPlaybackRate> AudioTrackPlaybackRateQueue; + // ---------------------------------------------------------------------------- // Important: do not add any virtual methods, including ~ @@ -159,6 +168,8 @@ 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; + // client write-only, server read-only uint16_t mSendLevel; // Fixed point U4.12 so 0x1000 means 1.0 @@ -313,7 +324,8 @@ public: AudioTrackClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize, bool clientInServer = false) : ClientProxy(cblk, buffers, frameCount, frameSize, true /*isOut*/, - clientInServer) { } + clientInServer), + mPlaybackRateMutator(&cblk->mPlaybackRateQueue) { } virtual ~AudioTrackClientProxy() { } // No barriers on the following operations, so the ordering of loads/stores @@ -333,6 +345,13 @@ public: mCblk->mSampleRate = sampleRate; } + void setPlaybackRate(float speed, float pitch) { + AudioTrackPlaybackRate playbackRate; + playbackRate.mSpeed = speed; + playbackRate.mPitch = pitch; + mPlaybackRateMutator.push(playbackRate); + } + virtual void flush(); virtual uint32_t getUnderrunFrames() const { @@ -344,6 +363,9 @@ public: bool getStreamEndDone() const; status_t waitStreamEndDone(const struct timespec *requested); + +private: + AudioTrackPlaybackRateQueue::Mutator mPlaybackRateMutator; }; class StaticAudioTrackClientProxy : public AudioTrackClientProxy { @@ -458,8 +480,11 @@ class AudioTrackServerProxy : public ServerProxy { public: AudioTrackServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize, bool clientInServer = false, uint32_t sampleRate = 0) - : ServerProxy(cblk, buffers, frameCount, frameSize, true /*isOut*/, clientInServer) { + : 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; } protected: virtual ~AudioTrackServerProxy() { } @@ -493,6 +518,13 @@ public: // Return the total number of frames that AudioFlinger has obtained and released 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); + +private: + AudioTrackPlaybackRate mPlaybackRate; // last observed playback rate + AudioTrackPlaybackRateQueue::Observer mPlaybackRateObserver; }; class StaticAudioTrackServerProxy : public AudioTrackServerProxy { |