Fix issue 1743700: AudioTrack: setPlaybackRate can not set the playback rate to twice of the ouputSR
Store sample rate on 32 bits instead of 16 bits in audio_track_cblk_t.
Removed sampleRate() methods from AudioTrack and AudioRecord: replaced by getSampleRate().
AudioTrack::setSampleRate() no returns a status.
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index 42ada54..e7d4694 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -539,16 +539,17 @@
// ----------------------------------------------------------------------------
-static void android_media_AudioTrack_set_playback_rate(JNIEnv *env, jobject thiz,
+static jint android_media_AudioTrack_set_playback_rate(JNIEnv *env, jobject thiz,
jint sampleRateInHz) {
AudioTrack *lpTrack = (AudioTrack *)env->GetIntField(
thiz, javaAudioTrackFields.nativeTrackInJavaObj);
if (lpTrack) {
- lpTrack->setSampleRate(sampleRateInHz);
+ return android_media_translateErrorCode(lpTrack->setSampleRate(sampleRateInHz));
} else {
jniThrowException(env, "java/lang/IllegalStateException",
"Unable to retrieve AudioTrack pointer for setSampleRate()");
+ return AUDIOTRACK_ERROR;
}
}
@@ -788,7 +789,7 @@
{"native_get_native_frame_count",
"()I", (void *)android_media_AudioTrack_get_native_frame_count},
{"native_set_playback_rate",
- "(I)V", (void *)android_media_AudioTrack_set_playback_rate},
+ "(I)I", (void *)android_media_AudioTrack_set_playback_rate},
{"native_get_playback_rate",
"()I", (void *)android_media_AudioTrack_get_playback_rate},
{"native_set_marker_pos","(I)I", (void *)android_media_AudioTrack_set_marker_pos},
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
index 3694803..13e51ee 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -197,7 +197,6 @@
/* getters, see constructor */
- uint32_t sampleRate() const;
int format() const;
int channelCount() const;
uint32_t frameCount() const;
@@ -217,7 +216,7 @@
status_t stop();
bool stopped() const;
- /* get sample rate for this track
+ /* get sample rate for this record track
*/
uint32_t getSampleRate();
@@ -323,7 +322,6 @@
sp<ClientRecordThread> mClientRecordThread;
Mutex mRecordThreadLock;
- uint32_t mSampleRate;
uint32_t mFrameCount;
audio_track_cblk_t* mCblk;
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index ba0467c..7c86a65 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -201,7 +201,6 @@
/* getters, see constructor */
int streamType() const;
- uint32_t sampleRate() const;
int format() const;
int channelCount() const;
uint32_t frameCount() const;
@@ -246,7 +245,7 @@
/* set sample rate for this track, mostly used for games' sound effects
*/
- void setSampleRate(int sampleRate);
+ status_t setSampleRate(int sampleRate);
uint32_t getSampleRate();
/* Enables looping and sets the start and end points of looping.
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index bda969c..496a739 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -26,7 +26,6 @@
// ----------------------------------------------------------------------------
-#define MAX_SAMPLE_RATE 65535
#define THREAD_PRIORITY_AUDIO_CLIENT (ANDROID_PRIORITY_AUDIO)
// Maximum cumulated timeout milliseconds before restarting audioflinger thread
#define MAX_STARTUP_TIMEOUT_MS 3000 // Longer timeout period at startup to cope with A2DP init time
@@ -55,9 +54,9 @@
uint16_t volume[2];
uint32_t volumeLR;
};
- uint16_t sampleRate;
- uint16_t channels;
- int16_t flowControlFlag; // underrun (out) or overrrun (in) indication
+ uint32_t sampleRate;
+ uint8_t channels;
+ uint8_t flowControlFlag; // underrun (out) or overrrun (in) indication
uint8_t out; // out equals 1 for AudioTrack and 0 for AudioRecord
uint8_t forceReady;
uint16_t bufferTimeoutMs; // Maximum cumulated timeout before restarting audioflinger
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index 75ca22c..8a19fbd 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -1281,7 +1281,7 @@
status_t lStatus;
// Resampler implementation limits input sampling rate to 2 x output sampling rate.
- if (sampleRate > MAX_SAMPLE_RATE || sampleRate > mSampleRate*2) {
+ if (sampleRate > mSampleRate*2) {
LOGE("Sample rate out of range: %d mSampleRate %d", sampleRate, mSampleRate);
lStatus = BAD_VALUE;
goto Exit;
@@ -1596,8 +1596,8 @@
new(mCblk) audio_track_cblk_t();
// clear all buffers
mCblk->frameCount = frameCount;
- mCblk->sampleRate = (uint16_t)sampleRate;
- mCblk->channels = (uint16_t)channelCount;
+ mCblk->sampleRate = sampleRate;
+ mCblk->channels = (uint8_t)channelCount;
if (sharedBuffer == 0) {
mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
@@ -1620,8 +1620,8 @@
new(mCblk) audio_track_cblk_t();
// clear all buffers
mCblk->frameCount = frameCount;
- mCblk->sampleRate = (uint16_t)sampleRate;
- mCblk->channels = (uint16_t)channelCount;
+ mCblk->sampleRate = sampleRate;
+ mCblk->channels = (uint8_t)channelCount;
mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
// Force underrun condition to avoid false underrun callback until first data is
@@ -1682,7 +1682,7 @@
}
int AudioFlinger::MixerThread::TrackBase::channelCount() const {
- return mCblk->channels;
+ return (int)mCblk->channels;
}
void* AudioFlinger::MixerThread::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
@@ -2267,12 +2267,6 @@
goto Exit;
}
- if (sampleRate > MAX_SAMPLE_RATE) {
- LOGE("Sample rate out of range");
- lStatus = BAD_VALUE;
- goto Exit;
- }
-
if (mAudioRecordThread == 0) {
LOGE("Audio record thread not started");
lStatus = NO_INIT;
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 3cd841d..5f1be9d 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -425,8 +425,7 @@
}
/**
- * Returns the current playback rate in Hz. Note that this rate may differ from the one set
- * with {@link #setPlaybackRate(int)} as the value effectively used is implementation-dependent.
+ * Returns the current playback rate in Hz.
*/
public int getPlaybackRate() {
return native_get_playback_rate();
@@ -651,18 +650,13 @@
* Sets the playback sample rate for this track. This sets the sampling rate at which
* the audio data will be consumed and played back, not the original sampling rate of the
* content. Setting it to half the sample rate of the content will cause the playback to
- * last twice as long, but will also result result in a negative pitch shift.
- * The current implementation supports a maximum sample rate of 64kHz.
- * Use {@link #getSampleRate()} to check the rate actually used in hardware after
- * potential clamping.
+ * last twice as long, but will also result in a negative pitch shift.
+ * The valid sample rate range if from 1Hz to twice the value returned by
+ * {@link #getNativeOutputSampleRate(int)}.
* @param sampleRateInHz the sample rate expressed in Hz
* @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE},
* {@link #ERROR_INVALID_OPERATION}
*/
- // FIXME: the implementation should support twice the hardware output sample rate
- // (see {@link #getNativeOutputSampleRate(int)}), but currently
- // due to the representation of the sample rate in the native layer, the sample rate
- // is limited to 65535Hz
public int setPlaybackRate(int sampleRateInHz) {
if (mState != STATE_INITIALIZED) {
return ERROR_INVALID_OPERATION;
@@ -670,8 +664,7 @@
if (sampleRateInHz <= 0) {
return ERROR_BAD_VALUE;
}
- native_set_playback_rate(sampleRateInHz);
- return SUCCESS;
+ return native_set_playback_rate(sampleRateInHz);
}
@@ -1031,8 +1024,8 @@
private native final void native_setVolume(float leftVolume, float rightVolume);
- private native final void native_set_playback_rate(int sampleRateInHz);
- private native final int native_get_playback_rate();
+ private native final int native_set_playback_rate(int sampleRateInHz);
+ private native final int native_get_playback_rate();
private native final int native_set_marker_pos(int marker);
private native final int native_get_marker_pos();
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 4c8b02a..e56efbb 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -185,7 +185,6 @@
mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
mCblk->out = 0;
- mSampleRate = sampleRate;
mFormat = format;
// Update buffer size in case it has been limited by AudioFlinger during track creation
mFrameCount = mCblk->frameCount;
@@ -196,7 +195,7 @@
mRemainingFrames = notificationFrames;
mUserData = user;
// TODO: add audio hardware input latency here
- mLatency = (1000*mFrameCount) / mSampleRate;
+ mLatency = (1000*mFrameCount) / sampleRate;
mMarkerPosition = 0;
mMarkerReached = false;
mNewPosition = 0;
@@ -218,11 +217,6 @@
return mLatency;
}
-uint32_t AudioRecord::sampleRate() const
-{
- return mSampleRate;
-}
-
int AudioRecord::format() const
{
return mFormat;
@@ -321,6 +315,11 @@
return !mActive;
}
+uint32_t AudioRecord::getSampleRate()
+{
+ return mCblk->sampleRate;
+}
+
status_t AudioRecord::setMarkerPosition(uint32_t marker)
{
if (mCbf == 0) return INVALID_OPERATION;
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 289bd75..b2c067b 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -243,7 +243,6 @@
mCblk->volume[0] = mCblk->volume[1] = 0x1000;
mVolume[LEFT] = 1.0f;
mVolume[RIGHT] = 1.0f;
- mSampleRate = sampleRate;
mStreamType = streamType;
mFormat = format;
mChannelCount = channelCount;
@@ -254,7 +253,7 @@
mNotificationFrames = notificationFrames;
mRemainingFrames = notificationFrames;
mUserData = user;
- mLatency = afLatency + (1000*mFrameCount) / mSampleRate;
+ mLatency = afLatency + (1000*mFrameCount) / sampleRate;
mLoopCount = 0;
mMarkerPosition = 0;
mMarkerReached = false;
@@ -281,11 +280,6 @@
return mStreamType;
}
-uint32_t AudioTrack::sampleRate() const
-{
- return mSampleRate;
-}
-
int AudioTrack::format() const
{
return mFormat;
@@ -438,24 +432,23 @@
*right = mVolume[RIGHT];
}
-void AudioTrack::setSampleRate(int rate)
+status_t AudioTrack::setSampleRate(int rate)
{
int afSamplingRate;
if (AudioSystem::getOutputSamplingRate(&afSamplingRate, mStreamType) != NO_ERROR) {
- return;
+ return NO_INIT;
}
// Resampler implementation limits input sampling rate to 2 x output sampling rate.
- if (rate <= 0) rate = 1;
- if (rate > afSamplingRate*2) rate = afSamplingRate*2;
- if (rate > MAX_SAMPLE_RATE) rate = MAX_SAMPLE_RATE;
+ if (rate <= 0 || rate > afSamplingRate*2 ) return BAD_VALUE;
- mCblk->sampleRate = (uint16_t)rate;
+ mCblk->sampleRate = rate;
+ return NO_ERROR;
}
uint32_t AudioTrack::getSampleRate()
{
- return uint32_t(mCblk->sampleRate);
+ return mCblk->sampleRate;
}
status_t AudioTrack::setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount)
@@ -866,7 +859,7 @@
result.append(buffer);
snprintf(buffer, 255, " format(%d), channel count(%d), frame count(%d)\n", mFormat, mChannelCount, mFrameCount);
result.append(buffer);
- snprintf(buffer, 255, " sample rate(%d), status(%d), muted(%d)\n", mSampleRate, mStatus, mMuted);
+ snprintf(buffer, 255, " sample rate(%d), status(%d), muted(%d)\n", (mCblk == 0) ? 0 : mCblk->sampleRate, mStatus, mMuted);
result.append(buffer);
snprintf(buffer, 255, " active(%d), latency (%d)\n", mActive, mLatency);
result.append(buffer);