Merge "Add PlaybackSettings for use with AudioTrack"

This commit is contained in:
Andy Hung
2015-04-22 22:36:12 +00:00
committed by Android (Google) Code Review
5 changed files with 371 additions and 1 deletions

View File

@@ -14995,6 +14995,7 @@ package android.media {
method public int getPlayState();
method public int getPlaybackHeadPosition();
method public int getPlaybackRate();
method public android.media.PlaybackSettings getPlaybackSettings();
method public int getPositionNotificationPeriod();
method public android.media.AudioDeviceInfo getPreferredOutputDevice();
method public int getSampleRate();
@@ -15012,6 +15013,7 @@ package android.media {
method public void setPlaybackPositionUpdateListener(android.media.AudioTrack.OnPlaybackPositionUpdateListener);
method public void setPlaybackPositionUpdateListener(android.media.AudioTrack.OnPlaybackPositionUpdateListener, android.os.Handler);
method public int setPlaybackRate(int);
method public void setPlaybackSettings(android.media.PlaybackSettings);
method public int setPositionNotificationPeriod(int);
method public boolean setPreferredOutputDevice(android.media.AudioDeviceInfo);
method protected deprecated void setState(int);
@@ -16375,6 +16377,24 @@ package android.media {
method public abstract void onAudioDeviceConnection();
}
public final class PlaybackSettings {
ctor public PlaybackSettings();
method public android.media.PlaybackSettings allowDefaults();
method public int getAudioFallbackMode();
method public int getAudioStretchMode();
method public float getPitch();
method public float getSpeed();
method public android.media.PlaybackSettings setAudioFallbackMode(int);
method public android.media.PlaybackSettings setAudioStretchMode(int);
method public android.media.PlaybackSettings setPitch(float);
method public android.media.PlaybackSettings setSpeed(float);
field public static final int AUDIO_FALLBACK_MODE_DEFAULT = 0; // 0x0
field public static final int AUDIO_FALLBACK_MODE_FAIL = 2; // 0x2
field public static final int AUDIO_FALLBACK_MODE_MUTE = 1; // 0x1
field public static final int AUDIO_STRETCH_MODE_DEFAULT = 0; // 0x0
field public static final int AUDIO_STRETCH_MODE_VOICE = 1; // 0x1
}
public final class Rating implements android.os.Parcelable {
method public int describeContents();
method public float getPercentRating();

View File

@@ -16207,6 +16207,7 @@ package android.media {
method public int getPlayState();
method public int getPlaybackHeadPosition();
method public int getPlaybackRate();
method public android.media.PlaybackSettings getPlaybackSettings();
method public int getPositionNotificationPeriod();
method public android.media.AudioDeviceInfo getPreferredOutputDevice();
method public int getSampleRate();
@@ -16224,6 +16225,7 @@ package android.media {
method public void setPlaybackPositionUpdateListener(android.media.AudioTrack.OnPlaybackPositionUpdateListener);
method public void setPlaybackPositionUpdateListener(android.media.AudioTrack.OnPlaybackPositionUpdateListener, android.os.Handler);
method public int setPlaybackRate(int);
method public void setPlaybackSettings(android.media.PlaybackSettings);
method public int setPositionNotificationPeriod(int);
method public boolean setPreferredOutputDevice(android.media.AudioDeviceInfo);
method protected deprecated void setState(int);
@@ -17590,6 +17592,24 @@ package android.media {
method public abstract void onAudioDeviceConnection();
}
public final class PlaybackSettings {
ctor public PlaybackSettings();
method public android.media.PlaybackSettings allowDefaults();
method public int getAudioFallbackMode();
method public int getAudioStretchMode();
method public float getPitch();
method public float getSpeed();
method public android.media.PlaybackSettings setAudioFallbackMode(int);
method public android.media.PlaybackSettings setAudioStretchMode(int);
method public android.media.PlaybackSettings setPitch(float);
method public android.media.PlaybackSettings setSpeed(float);
field public static final int AUDIO_FALLBACK_MODE_DEFAULT = 0; // 0x0
field public static final int AUDIO_FALLBACK_MODE_FAIL = 2; // 0x2
field public static final int AUDIO_FALLBACK_MODE_MUTE = 1; // 0x1
field public static final int AUDIO_STRETCH_MODE_DEFAULT = 0; // 0x0
field public static final int AUDIO_STRETCH_MODE_VOICE = 1; // 0x1
}
public final class Rating implements android.os.Parcelable {
method public int describeContents();
method public float getPercentRating();

View File

@@ -676,6 +676,63 @@ static jint android_media_AudioTrack_get_playback_rate(JNIEnv *env, jobject thi
}
// ----------------------------------------------------------------------------
static void android_media_AudioTrack_set_playback_settings(JNIEnv *env, jobject thiz,
jfloatArray floatArray, jintArray intArray) {
sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
if (lpTrack == NULL) {
jniThrowException(env, "java/lang/IllegalStateException",
"AudioTrack not initialized");
return;
}
// NOTE: Get<Primitive>ArrayRegion throws ArrayIndexOutOfBoundsException if not valid.
// TODO: consider the actual occupancy.
float farray[2];
int iarray[2];
if ((env->GetFloatArrayRegion(floatArray, 0, 2, farray), env->ExceptionCheck()) == JNI_FALSE
&&
(env->GetIntArrayRegion(intArray, 0, 2, iarray), env->ExceptionCheck()) == JNI_FALSE) {
// arrays retrieved OK
AudioPlaybackRate playbackRate;
playbackRate.mSpeed = farray[0];
playbackRate.mPitch = farray[1];
playbackRate.mFallbackMode = (AudioTimestretchFallbackMode)iarray[0];
playbackRate.mStretchMode = (AudioTimestretchStretchMode)iarray[1];
if (lpTrack->setPlaybackRate(playbackRate) != OK) {
jniThrowException(env, "java/lang/IllegalArgumentException",
"arguments out of range");
}
}
}
// ----------------------------------------------------------------------------
static void android_media_AudioTrack_get_playback_settings(JNIEnv *env, jobject thiz,
jfloatArray floatArray, jintArray intArray) {
sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
if (lpTrack == NULL) {
jniThrowException(env, "java/lang/IllegalStateException",
"AudioTrack not initialized");
return;
}
AudioPlaybackRate playbackRate = lpTrack->getPlaybackRate();
float farray[2] = {
playbackRate.mSpeed,
playbackRate.mPitch,
};
int iarray[2] = {
playbackRate.mFallbackMode,
playbackRate.mStretchMode,
};
// NOTE: Set<Primitive>ArrayRegion throws ArrayIndexOutOfBoundsException if not valid.
env->SetFloatArrayRegion(floatArray, 0, 2, farray);
env->SetIntArrayRegion(intArray, 0, 2, iarray);
}
// ----------------------------------------------------------------------------
static jint android_media_AudioTrack_set_marker_pos(JNIEnv *env, jobject thiz,
jint markerPos) {
@@ -942,6 +999,10 @@ static JNINativeMethod gMethods[] = {
"(I)I", (void *)android_media_AudioTrack_set_playback_rate},
{"native_get_playback_rate",
"()I", (void *)android_media_AudioTrack_get_playback_rate},
{"native_set_playback_settings",
"([F[I)V", (void *)android_media_AudioTrack_set_playback_settings},
{"native_get_playback_settings",
"([F[I)V", (void *)android_media_AudioTrack_get_playback_settings},
{"native_set_marker_pos","(I)I", (void *)android_media_AudioTrack_set_marker_pos},
{"native_get_marker_pos","()I", (void *)android_media_AudioTrack_get_marker_pos},
{"native_set_pos_update_period",

View File

@@ -946,12 +946,29 @@ public class AudioTrack
}
/**
* Returns the current playback rate in Hz.
* Returns the current playback sample rate rate in Hz.
*/
public int getPlaybackRate() {
return native_get_playback_rate();
}
/**
* Returns the current playback settings.
* See {@link #setPlaybackSettings(PlaybackSettings)} to set playback settings
* @return current {@link PlaybackSettings}.
* @throws IllegalStateException if track is not initialized.
*/
public @NonNull PlaybackSettings getPlaybackSettings() {
float[] floatArray = new float[2];
int[] intArray = new int[2];
native_get_playback_settings(floatArray, intArray);
return new PlaybackSettings()
.setSpeed(floatArray[0])
.setPitch(floatArray[1])
.setAudioFallbackMode(intArray[0])
.setAudioStretchMode(intArray[1]);
}
/**
* Returns the configured audio data format. See {@link AudioFormat#ENCODING_PCM_16BIT}
* and {@link AudioFormat#ENCODING_PCM_8BIT}.
@@ -1307,6 +1324,7 @@ public class AudioTrack
* playback to last twice as long, but will also result in a pitch shift down by one octave.
* The valid sample rate range is from 1 Hz to twice the value returned by
* {@link #getNativeOutputSampleRate(int)}.
* Use {@link #setPlaybackSettings(PlaybackSettings)} for speed control.
* @param sampleRateInHz the sample rate expressed in Hz
* @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE},
* {@link #ERROR_INVALID_OPERATION}
@@ -1322,6 +1340,42 @@ public class AudioTrack
}
/**
* Sets the playback settings.
* This method returns failure if it cannot apply the playback settings.
* One possible cause is that the parameters for speed or pitch are out of range.
* Another possible cause is that the <code>AudioTrack</code> is streaming
* (see {@link #MODE_STREAM}) and the
* buffer size is too small. For speeds greater than 1.0f, the <code>AudioTrack</code> buffer
* on configuration must be larger than the speed multiplied by the minimum size
* {@link #getMinBufferSize(int, int, int)}) to allow proper playback.
* @param settings see {@link PlaybackSettings}. In particular,
* speed, pitch, and audio mode should be set.
* @throws IllegalArgumentException if the settings are invalid or not accepted.
* @throws IllegalStateException if track is not initialized.
*/
public void setPlaybackSettings(@NonNull PlaybackSettings settings) {
if (settings == null) {
throw new IllegalArgumentException("settings is null");
}
float[] floatArray;
int[] intArray;
try {
floatArray = new float[] {
settings.getSpeed(),
settings.getPitch(),
};
intArray = new int[] {
settings.getAudioFallbackMode(),
settings.getAudioStretchMode(),
};
} catch (IllegalStateException e) {
throw new IllegalArgumentException(e);
}
native_set_playback_settings(floatArray, intArray);
}
/**
* Sets the position of the notification marker. At most one marker can be active.
* @param markerInFrames marker position in wrapping frame units similar to
@@ -2207,6 +2261,15 @@ public class AudioTrack
private native final int native_set_playback_rate(int sampleRateInHz);
private native final int native_get_playback_rate();
// floatArray must be a non-null array of length >= 2
// [0] is speed
// [1] is pitch
// intArray must be a non-null array of length >= 2
// [0] is audio fallback mode
// [1] is audio stretch mode
private native final void native_set_playback_settings(float[] floatArray, int[] intArray);
private native final void native_get_playback_settings(float[] floatArray, int[] intArray);
private native final int native_set_marker_pos(int marker);
private native final int native_get_marker_pos();

View File

@@ -0,0 +1,206 @@
/*
* Copyright 2015 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.
*/
package android.media;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import android.annotation.IntDef;
/**
* Structure for common playback settings.
*
* Used by {@link AudioTrack} {@link AudioTrack#getPlaybackSettings()} and
* {@link AudioTrack#setPlaybackSettings(PlaybackSettings)}
* to control playback behavior.
* <p> <strong>audio fallback mode:</strong>
* select out-of-range parameter handling.
* <ul>
* <li> {@link PlaybackSettings#AUDIO_FALLBACK_MODE_DEFAULT}:
* System will determine best handling. </li>
* <li> {@link PlaybackSettings#AUDIO_FALLBACK_MODE_MUTE}:
* Play silence for settings normally out of range.</li>
* <li> {@link PlaybackSettings#AUDIO_FALLBACK_MODE_FAIL}:
* Return {@link java.lang.IllegalArgumentException} from
* <code>AudioTrack.setPlaybackSettings(PlaybackSettings)</code>.</li>
* </ul>
* <p> <strong>audio stretch mode:</strong> select
* timestretch handling.
* <ul>
* <li> {@link PlaybackSettings#AUDIO_STRETCH_MODE_DEFAULT}:
* System will determine best selection. </li>
* <li> {@link PlaybackSettings#AUDIO_STRETCH_MODE_VOICE}:
* Content is primarily voice.</li>
* </ul>
* <p> <strong>pitch:</strong> increases or decreases the tonal frequency of the audio content.
* It is expressed as a multiplicative factor, where normal pitch is 1.0f.
* <p> <strong>speed:</strong> increases or decreases the time to
* play back a set of audio or video frames.
* It is expressed as a multiplicative factor, where normal speed is 1.0f.
* <p> Different combinations of speed and pitch may be used for audio playback;
* some common ones:
* <ul>
* <li> <em>Pitch equals 1.0f.</em> Speed change will be done with pitch preserved,
* often called <em>timestretching</em>.</li>
* <li> <em>Pitch equals speed.</em> Speed change will be done by <em>resampling</em>,
* similar to {@link AudioTrack#setPlaybackRate(int)}.</li>
* </ul>
*/
public final class PlaybackSettings {
/** @hide */
@IntDef(
value = {
AUDIO_FALLBACK_MODE_DEFAULT,
AUDIO_FALLBACK_MODE_MUTE,
AUDIO_FALLBACK_MODE_FAIL,
}
)
@Retention(RetentionPolicy.SOURCE)
public @interface AudioFallbackMode {}
public static final int AUDIO_FALLBACK_MODE_DEFAULT = 0;
public static final int AUDIO_FALLBACK_MODE_MUTE = 1;
public static final int AUDIO_FALLBACK_MODE_FAIL = 2;
/** @hide */
@IntDef(
value = {
AUDIO_STRETCH_MODE_DEFAULT,
AUDIO_STRETCH_MODE_VOICE,
}
)
@Retention(RetentionPolicy.SOURCE)
public @interface AudioStretchMode {}
public static final int AUDIO_STRETCH_MODE_DEFAULT = 0;
public static final int AUDIO_STRETCH_MODE_VOICE = 1;
// flags to indicate which settings are actually set
private static final int SET_SPEED = 1 << 0;
private static final int SET_PITCH = 1 << 1;
private static final int SET_AUDIO_FALLBACK_MODE = 1 << 2;
private static final int SET_AUDIO_STRETCH_MODE = 1 << 3;
private int mSet = 0;
// settings
private int mAudioFallbackMode = AUDIO_FALLBACK_MODE_DEFAULT;
private int mAudioStretchMode = AUDIO_STRETCH_MODE_DEFAULT;
private float mPitch = 1.0f;
private float mSpeed = 1.0f;
/**
* Allows defaults to be returned for properties not set.
* Otherwise a {@link java.lang.IllegalArgumentException} exception
* is raised when getting those properties
* which have defaults but have never been set.
* @return this <code>PlaybackSettings</code> instance.
*/
public PlaybackSettings allowDefaults() {
mSet |= SET_AUDIO_FALLBACK_MODE | SET_AUDIO_STRETCH_MODE | SET_PITCH | SET_SPEED;
return this;
}
/**
* Sets the audio fallback mode.
* @param audioFallbackMode
* @return this <code>PlaybackSettings</code> instance.
*/
public PlaybackSettings setAudioFallbackMode(@AudioFallbackMode int audioFallbackMode) {
mAudioFallbackMode = audioFallbackMode;
mSet |= SET_AUDIO_FALLBACK_MODE;
return this;
}
/**
* Retrieves the audio fallback mode.
* @return audio fallback mode
* @throws IllegalStateException if the audio fallback mode is not set.
*/
public @AudioFallbackMode int getAudioFallbackMode() {
if ((mSet & SET_AUDIO_FALLBACK_MODE) == 0) {
throw new IllegalStateException("audio fallback mode not set");
}
return mAudioFallbackMode;
}
/**
* Sets the audio stretch mode.
* @param audioStretchMode
* @return this <code>PlaybackSettings</code> instance.
*/
public PlaybackSettings setAudioStretchMode(@AudioStretchMode int audioStretchMode) {
mAudioStretchMode = audioStretchMode;
mSet |= SET_AUDIO_STRETCH_MODE;
return this;
}
/**
* Retrieves the audio stretch mode.
* @return audio stretch mode
* @throws IllegalStateException if the audio stretch mode is not set.
*/
public @AudioStretchMode int getAudioStretchMode() {
if ((mSet & SET_AUDIO_STRETCH_MODE) == 0) {
throw new IllegalStateException("audio stretch mode not set");
}
return mAudioStretchMode;
}
/**
* Sets the pitch factor.
* @param pitch
* @return this <code>PlaybackSettings</code> instance.
*/
public PlaybackSettings setPitch(float pitch) {
mPitch = pitch;
mSet |= SET_PITCH;
return this;
}
/**
* Retrieves the pitch factor.
* @return pitch
* @throws IllegalStateException if pitch is not set.
*/
public float getPitch() {
if ((mSet & SET_PITCH) == 0) {
throw new IllegalStateException("pitch not set");
}
return mPitch;
}
/**
* Sets the speed factor.
* @param speed
* @return this <code>PlaybackSettings</code> instance.
*/
public PlaybackSettings setSpeed(float speed) {
mSpeed = speed;
mSet |= SET_SPEED;
return this;
}
/**
* Retrieves the speed factor.
* @return speed
* @throws IllegalStateException if speed is not set.
*/
public float getSpeed() {
if ((mSet & SET_SPEED) == 0) {
throw new IllegalStateException("speed not set");
}
return mSpeed;
}
}