Add PlaybackSettings for use with AudioTrack
Change-Id: Ie59686d46869558d489a7600170ddace00e548d5
This commit is contained in:
@@ -14987,6 +14987,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();
|
||||
@@ -15004,6 +15005,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);
|
||||
@@ -16367,6 +16369,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();
|
||||
|
||||
@@ -16199,6 +16199,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();
|
||||
@@ -16216,6 +16217,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);
|
||||
@@ -17582,6 +17584,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();
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
206
media/java/android/media/PlaybackSettings.java
Normal file
206
media/java/android/media/PlaybackSettings.java
Normal 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user