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
91     private static final int SET_SPEED               = 1 << 0;
92     @UnsupportedAppUsage
93     private static final int SET_PITCH               = 1 << 1;
94     @UnsupportedAppUsage
95     private static final int SET_AUDIO_FALLBACK_MODE = 1 << 2;
96     @UnsupportedAppUsage
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
103     private int mAudioFallbackMode = AUDIO_FALLBACK_MODE_DEFAULT;
104     @UnsupportedAppUsage
105     private int mAudioStretchMode = AUDIO_STRETCH_MODE_DEFAULT;
106     @UnsupportedAppUsage
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