1 /* 2 * Copyright 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.media; 18 19 import android.annotation.IntDef; 20 import android.annotation.TestApi; 21 import android.compat.annotation.UnsupportedAppUsage; 22 import android.os.Build; 23 import android.os.Parcel; 24 import android.os.Parcelable; 25 26 import java.lang.annotation.Retention; 27 import java.lang.annotation.RetentionPolicy; 28 29 /** 30 * Structure for common playback params. 31 * 32 * Used by {@link AudioTrack} {@link AudioTrack#getPlaybackParams()} and 33 * {@link AudioTrack#setPlaybackParams(PlaybackParams)} 34 * to control playback behavior. 35 * <p> <strong>audio fallback mode:</strong> 36 * select out-of-range parameter handling. 37 * <ul> 38 * <li> {@link PlaybackParams#AUDIO_FALLBACK_MODE_DEFAULT}: 39 * System will determine best handling. </li> 40 * <li> {@link PlaybackParams#AUDIO_FALLBACK_MODE_MUTE}: 41 * Play silence for params normally out of range.</li> 42 * <li> {@link PlaybackParams#AUDIO_FALLBACK_MODE_FAIL}: 43 * Return {@link java.lang.IllegalArgumentException} from 44 * <code>AudioTrack.setPlaybackParams(PlaybackParams)</code>.</li> 45 * </ul> 46 * <p> <strong>pitch:</strong> increases or decreases the tonal frequency of the audio content. 47 * It is expressed as a multiplicative factor, where normal pitch is 1.0f. 48 * <p> <strong>speed:</strong> increases or decreases the time to 49 * play back a set of audio or video frames. 50 * It is expressed as a multiplicative factor, where normal speed is 1.0f. 51 * <p> Different combinations of speed and pitch may be used for audio playback; 52 * some common ones: 53 * <ul> 54 * <li> <em>Pitch equals 1.0f.</em> Speed change will be done with pitch preserved, 55 * often called <em>timestretching</em>.</li> 56 * <li> <em>Pitch equals speed.</em> Speed change will be done by <em>resampling</em>, 57 * similar to {@link AudioTrack#setPlaybackRate(int)}.</li> 58 * </ul> 59 */ 60 public final class PlaybackParams implements Parcelable { 61 /** @hide */ 62 @IntDef( 63 value = { 64 AUDIO_FALLBACK_MODE_DEFAULT, 65 AUDIO_FALLBACK_MODE_MUTE, 66 AUDIO_FALLBACK_MODE_FAIL, 67 } 68 ) 69 @Retention(RetentionPolicy.SOURCE) 70 public @interface AudioFallbackMode {} 71 public static final int AUDIO_FALLBACK_MODE_DEFAULT = 0; 72 public static final int AUDIO_FALLBACK_MODE_MUTE = 1; 73 public static final int AUDIO_FALLBACK_MODE_FAIL = 2; 74 75 /** @hide */ 76 @IntDef( 77 value = { 78 AUDIO_STRETCH_MODE_DEFAULT, 79 AUDIO_STRETCH_MODE_VOICE, 80 } 81 ) 82 @Retention(RetentionPolicy.SOURCE) 83 public @interface AudioStretchMode {} 84 /** @hide */ 85 public static final int AUDIO_STRETCH_MODE_DEFAULT = 0; 86 /** @hide */ 87 public static final int AUDIO_STRETCH_MODE_VOICE = 1; 88 89 // flags to indicate which params are actually set 90 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 91 private static final int SET_SPEED = 1 << 0; 92 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 93 private static final int SET_PITCH = 1 << 1; 94 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 95 private static final int SET_AUDIO_FALLBACK_MODE = 1 << 2; 96 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 97 private static final int SET_AUDIO_STRETCH_MODE = 1 << 3; 98 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 99 private int mSet = 0; 100 101 // params 102 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 103 private int mAudioFallbackMode = AUDIO_FALLBACK_MODE_DEFAULT; 104 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 105 private int mAudioStretchMode = AUDIO_STRETCH_MODE_DEFAULT; 106 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 107 private float mPitch = 1.0f; 108 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 109 private float mSpeed = 1.0f; 110 PlaybackParams()111 public PlaybackParams() { 112 } 113 PlaybackParams(Parcel in)114 private PlaybackParams(Parcel in) { 115 mSet = in.readInt(); 116 mAudioFallbackMode = in.readInt(); 117 mAudioStretchMode = in.readInt(); 118 mPitch = in.readFloat(); 119 if (mPitch < 0.f) { 120 mPitch = 0.f; 121 } 122 mSpeed = in.readFloat(); 123 } 124 125 /** 126 * Allows defaults to be returned for properties not set. 127 * Otherwise a {@link java.lang.IllegalArgumentException} exception 128 * is raised when getting those properties 129 * which have defaults but have never been set. 130 * @return this <code>PlaybackParams</code> instance. 131 */ allowDefaults()132 public PlaybackParams allowDefaults() { 133 mSet |= SET_AUDIO_FALLBACK_MODE | SET_AUDIO_STRETCH_MODE | SET_PITCH | SET_SPEED; 134 return this; 135 } 136 137 /** 138 * Sets the audio fallback mode. 139 * @param audioFallbackMode 140 * @return this <code>PlaybackParams</code> instance. 141 */ setAudioFallbackMode(@udioFallbackMode int audioFallbackMode)142 public PlaybackParams setAudioFallbackMode(@AudioFallbackMode int audioFallbackMode) { 143 mAudioFallbackMode = audioFallbackMode; 144 mSet |= SET_AUDIO_FALLBACK_MODE; 145 return this; 146 } 147 148 /** 149 * Retrieves the audio fallback mode. 150 * @return audio fallback mode 151 * @throws IllegalStateException if the audio fallback mode is not set. 152 */ getAudioFallbackMode()153 public @AudioFallbackMode int getAudioFallbackMode() { 154 if ((mSet & SET_AUDIO_FALLBACK_MODE) == 0) { 155 throw new IllegalStateException("audio fallback mode not set"); 156 } 157 return mAudioFallbackMode; 158 } 159 160 /** 161 * @hide 162 * Sets the audio stretch mode. 163 * @param audioStretchMode 164 * @return this <code>PlaybackParams</code> instance. 165 */ 166 @TestApi setAudioStretchMode(@udioStretchMode int audioStretchMode)167 public PlaybackParams setAudioStretchMode(@AudioStretchMode int audioStretchMode) { 168 mAudioStretchMode = audioStretchMode; 169 mSet |= SET_AUDIO_STRETCH_MODE; 170 return this; 171 } 172 173 /** 174 * @hide 175 * Retrieves the audio stretch mode. 176 * @return audio stretch mode 177 * @throws IllegalStateException if the audio stretch mode is not set. 178 */ 179 @TestApi getAudioStretchMode()180 public @AudioStretchMode int getAudioStretchMode() { 181 if ((mSet & SET_AUDIO_STRETCH_MODE) == 0) { 182 throw new IllegalStateException("audio stretch mode not set"); 183 } 184 return mAudioStretchMode; 185 } 186 187 /** 188 * Sets the pitch factor. 189 * @param pitch 190 * @return this <code>PlaybackParams</code> instance. 191 * @throws IllegalArgumentException if the pitch is negative. 192 */ setPitch(float pitch)193 public PlaybackParams setPitch(float pitch) { 194 if (pitch < 0.f) { 195 throw new IllegalArgumentException("pitch must not be negative"); 196 } 197 mPitch = pitch; 198 mSet |= SET_PITCH; 199 return this; 200 } 201 202 /** 203 * Retrieves the pitch factor. 204 * @return pitch 205 * @throws IllegalStateException if pitch is not set. 206 */ getPitch()207 public float getPitch() { 208 if ((mSet & SET_PITCH) == 0) { 209 throw new IllegalStateException("pitch not set"); 210 } 211 return mPitch; 212 } 213 214 /** 215 * Sets the speed factor. 216 * @param speed 217 * @return this <code>PlaybackParams</code> instance. 218 */ setSpeed(float speed)219 public PlaybackParams setSpeed(float speed) { 220 mSpeed = speed; 221 mSet |= SET_SPEED; 222 return this; 223 } 224 225 /** 226 * Retrieves the speed factor. 227 * @return speed 228 * @throws IllegalStateException if speed is not set. 229 */ getSpeed()230 public float getSpeed() { 231 if ((mSet & SET_SPEED) == 0) { 232 throw new IllegalStateException("speed not set"); 233 } 234 return mSpeed; 235 } 236 237 public static final @android.annotation.NonNull Parcelable.Creator<PlaybackParams> CREATOR = 238 new Parcelable.Creator<PlaybackParams>() { 239 @Override 240 public PlaybackParams createFromParcel(Parcel in) { 241 return new PlaybackParams(in); 242 } 243 244 @Override 245 public PlaybackParams[] newArray(int size) { 246 return new PlaybackParams[size]; 247 } 248 }; 249 250 251 @Override describeContents()252 public int describeContents() { 253 return 0; 254 } 255 256 @Override writeToParcel(Parcel dest, int flags)257 public void writeToParcel(Parcel dest, int flags) { 258 dest.writeInt(mSet); 259 dest.writeInt(mAudioFallbackMode); 260 dest.writeInt(mAudioStretchMode); 261 dest.writeFloat(mPitch); 262 dest.writeFloat(mSpeed); 263 } 264 } 265