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