AudioTrack.java revision 3b3ed7af3b4837440af62e7af4fe5e0e2df17559
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.media;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
197ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Triviimport java.lang.annotation.Retention;
207ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Triviimport java.lang.annotation.RetentionPolicy;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.ref.WeakReference;
22cfe964a09ca05778e5dd84f2fd24119b89401696Rachadimport java.lang.Math;
237ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Triviimport java.nio.ByteBuffer;
24cfe964a09ca05778e5dd84f2fd24119b89401696Rachadimport java.nio.ByteOrder;
257ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Triviimport java.nio.NioUtils;
26d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLeanimport java.util.Collection;
2735ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi
287ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Triviimport android.annotation.IntDef;
2935ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Triviimport android.annotation.NonNull;
309025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hungimport android.annotation.Nullable;
311af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlockimport android.app.ActivityThread;
321af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlockimport android.content.Context;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
341af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlockimport android.os.IBinder;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Looper;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message;
371af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlockimport android.os.Process;
381af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlockimport android.os.RemoteException;
391af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlockimport android.os.ServiceManager;
40d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLeanimport android.util.ArrayMap;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
43ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkeyimport com.android.internal.annotations.GuardedBy;
441af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The AudioTrack class manages and plays a single audio resource for Java applications.
47e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * It allows streaming of PCM audio buffers to the audio sink for playback. This is
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * achieved by "pushing" the data to the AudioTrack object using one of the
497d60bcd2d950e3571c00ce9f1c492c6bd58334c9Glenn Kasten *  {@link #write(byte[], int, int)}, {@link #write(short[], int, int)},
507d60bcd2d950e3571c00ce9f1c492c6bd58334c9Glenn Kasten *  and {@link #write(float[], int, int, int)} methods.
5188bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath *
52ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi * <p>An AudioTrack instance can operate under two modes: static or streaming.<br>
53ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi * In Streaming mode, the application writes a continuous stream of data to the AudioTrack, using
5488bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath * one of the {@code write()} methods. These are blocking and return when the data has been
5588bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath * transferred from the Java layer to the native layer and queued for playback. The streaming
5688bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath * mode is most useful when playing blocks of audio data that for instance are:
5788bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath *
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul>
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   <li>too big to fit in memory because of the duration of the sound to play,</li>
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   <li>too big to fit in memory because of the characteristics of the audio data
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         (high sampling rate, bits per sample ...)</li>
62ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi *   <li>received or generated while previously queued audio is playing.</li>
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </ul>
6488bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath *
655c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten * The static mode should be chosen when dealing with short sounds that fit in memory and
6688bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath * that need to be played with the smallest latency possible. The static mode will
6788bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath * therefore be preferred for UI and game sounds that are played often, and with the
6888bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath * smallest overhead possible.
6988bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath *
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Upon creation, an AudioTrack object initializes its associated audio buffer.
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The size of this buffer, specified during the construction, determines how long an AudioTrack
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * can play before running out of data.<br>
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * For an AudioTrack using the static mode, this size is the maximum size of the sound that can
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be played from it.<br>
75e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * For the streaming mode, data will be written to the audio sink in chunks of
765c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten * sizes less than or equal to the total buffer size.
7755a3218f242a611afb3569d88970c0c5dbf8ce54Glenn Kasten *
7855a3218f242a611afb3569d88970c0c5dbf8ce54Glenn Kasten * AudioTrack is not final and thus permits subclasses, but such use is not recommended.
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
803c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivipublic class AudioTrack extends PlayerBase
813c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi                        implements AudioRouting
82fef734cec10420c4a008bb41c184c143333d7570Andy Hung                                 , VolumeAutomation
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //---------------------------------------------------------
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Constants
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //--------------------
8778cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten    /** Minimum value for a linear gain or auxiliary effect level.
8878cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     *  This value must be exactly equal to 0.0f; do not change it.
8978cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     */
9078cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten    private static final float GAIN_MIN = 0.0f;
9178cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten    /** Maximum value for a linear gain or auxiliary effect level.
9278cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     *  This value must be greater than or equal to 1.0f.
9378cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     */
9478cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten    private static final float GAIN_MAX = 1.0f;
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
96bd2c3d65d6b62b5a359268246e7ebe96904bd851Glenn Kasten    /** Maximum value for AudioTrack channel count
97bd2c3d65d6b62b5a359268246e7ebe96904bd851Glenn Kasten     * @hide public for MediaCode only, do not un-hide or change to a numeric literal
98bd2c3d65d6b62b5a359268246e7ebe96904bd851Glenn Kasten     */
9925d3c7c49bafb22723138bfab2e315d2d0a926fbGlenn Kasten    public static final int CHANNEL_COUNT_MAX = native_get_FCC_8();
100ad720aeea741d9058a7b4d326c9ab1b3ebcd7c62Andy Hung
101ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi    /** indicates AudioTrack state is stopped */
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int PLAYSTATE_STOPPED = 1;  // matches SL_PLAYSTATE_STOPPED
103ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi    /** indicates AudioTrack state is paused */
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int PLAYSTATE_PAUSED  = 2;  // matches SL_PLAYSTATE_PAUSED
105ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi    /** indicates AudioTrack state is playing */
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int PLAYSTATE_PLAYING = 3;  // matches SL_PLAYSTATE_PLAYING
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1085c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten    // keep these values in sync with android_media_AudioTrack.cpp
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Creation mode where audio data is transferred from Java to the native layer
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * only once before the audio starts playing.
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int MODE_STATIC = 0;
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Creation mode where audio data is streamed from Java to the native layer
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * as the audio is playing.
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int MODE_STREAM = 1;
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12035ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi    /** @hide */
12135ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi    @IntDef({
12235ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi        MODE_STATIC,
12335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi        MODE_STREAM
12435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi    })
12535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi    @Retention(RetentionPolicy.SOURCE)
12635ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi    public @interface TransferMode {}
12735ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
129ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * State of an AudioTrack that was not successfully initialized upon creation.
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int STATE_UNINITIALIZED = 0;
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * State of an AudioTrack that is ready to be used.
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int STATE_INITIALIZED   = 1;
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * State of a successfully initialized AudioTrack that uses static data,
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * but that hasn't received that data yet.
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int STATE_NO_STATIC_DATA = 2;
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Denotes a successful operation.
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
145bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent    public  static final int SUCCESS                               = AudioSystem.SUCCESS;
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Denotes a generic operation failure.
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
149bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent    public  static final int ERROR                                 = AudioSystem.ERROR;
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Denotes a failure due to the use of an invalid value.
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
153bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent    public  static final int ERROR_BAD_VALUE                       = AudioSystem.BAD_VALUE;
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Denotes a failure due to the improper use of a method.
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
157bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent    public  static final int ERROR_INVALID_OPERATION               = AudioSystem.INVALID_OPERATION;
1584e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent    /**
1594e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent     * An error code indicating that the object reporting it is no longer valid and needs to
1604e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent     * be recreated.
1614e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent     */
1624e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent    public  static final int ERROR_DEAD_OBJECT                     = AudioSystem.DEAD_OBJECT;
1634e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent    /**
1644e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent     * {@link #getTimestampWithStatus(AudioTimestamp)} is called in STOPPED or FLUSHED state,
1654e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent     * or immediately after start/ACTIVE.
1664e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent     * @hide
1674e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent     */
1684e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent    public  static final int ERROR_WOULD_BLOCK                     = AudioSystem.WOULD_BLOCK;
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
170bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent    // Error codes:
171bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent    // to keep in sync with frameworks/base/core/jni/android_media_AudioTrack.cpp
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int ERROR_NATIVESETUP_AUDIOSYSTEM         = -16;
173a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent    private static final int ERROR_NATIVESETUP_INVALIDCHANNELMASK  = -17;
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int ERROR_NATIVESETUP_INVALIDFORMAT       = -18;
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int ERROR_NATIVESETUP_INVALIDSTREAMTYPE   = -19;
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int ERROR_NATIVESETUP_NATIVEINITFAILED    = -20;
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Events:
179e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten    // to keep in sync with frameworks/av/include/media/AudioTrack.h
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
181ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * Event id denotes when playback head has reached a previously set marker.
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int NATIVE_EVENT_MARKER  = 3;
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
185ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * Event id denotes when previously set update period has elapsed during playback.
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int NATIVE_EVENT_NEW_POS = 4;
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1891f61d01508651b4475397414e1fe06af1ab8fadaGlenn Kasten    private final static String TAG = "android.media.AudioTrack";
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1927ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi    /** @hide */
1937ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi    @IntDef({
1947ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi        WRITE_BLOCKING,
1957ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi        WRITE_NON_BLOCKING
1967ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi    })
1977ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi    @Retention(RetentionPolicy.SOURCE)
1987ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi    public @interface WriteMode {}
1997ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi
2007ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi    /**
2017ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi     * The write mode indicating the write operation will block until all data has been written,
202659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * to be used as the actual value of the writeMode parameter in
203659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * {@link #write(byte[], int, int, int)}, {@link #write(short[], int, int, int)},
204659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * {@link #write(float[], int, int, int)}, {@link #write(ByteBuffer, int, int)}, and
205659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * {@link #write(ByteBuffer, int, int, long)}.
2067ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi     */
2077ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi    public final static int WRITE_BLOCKING = 0;
208659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten
2097ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi    /**
2107ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi     * The write mode indicating the write operation will return immediately after
211659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * queuing as much audio data for playback as possible without blocking,
212659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * to be used as the actual value of the writeMode parameter in
213659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * {@link #write(ByteBuffer, int, int)}, {@link #write(short[], int, int, int)},
214659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * {@link #write(float[], int, int, int)}, {@link #write(ByteBuffer, int, int)}, and
215659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * {@link #write(ByteBuffer, int, int, long)}.
2167ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi     */
2177ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi    public final static int WRITE_NON_BLOCKING = 1;
2187ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi
219ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung    /** @hide */
220ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung    @IntDef({
221ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung        PERFORMANCE_MODE_NONE,
222ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung        PERFORMANCE_MODE_LOW_LATENCY,
223ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung        PERFORMANCE_MODE_POWER_SAVING
224ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung    })
225ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung    @Retention(RetentionPolicy.SOURCE)
226ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung    public @interface PerformanceMode {}
227ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung
228ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung    /**
229ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * Default performance mode for an {@link AudioTrack}.
230ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     */
231ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung    public static final int PERFORMANCE_MODE_NONE = 0;
232ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung
233ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung    /**
234ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * Low latency performance mode for an {@link AudioTrack}.
235ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * If the device supports it, this mode
236ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * enables a lower latency path through to the audio output sink.
237ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * Effects may no longer work with such an {@code AudioTrack} and
238ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * the sample rate must match that of the output sink.
239ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * <p>
240ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * Applications should be aware that low latency requires careful
241ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * buffer management, with smaller chunks of audio data written by each
242ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * {@code write()} call.
243ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * <p>
244ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * If this flag is used without specifying a {@code bufferSizeInBytes} then the
245ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * {@code AudioTrack}'s actual buffer size may be too small.
246ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * It is recommended that a fairly
247ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * large buffer should be specified when the {@code AudioTrack} is created.
248ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * Then the actual size can be reduced by calling
249ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * {@link #setBufferSizeInFrames(int)}. The buffer size can be optimized
250ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * by lowering it after each {@code write()} call until the audio glitches,
251ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * which is detected by calling
252ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * {@link #getUnderrunCount()}. Then the buffer size can be increased
253ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * until there are no glitches.
254ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * This tuning step should be done while playing silence.
255ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * This technique provides a compromise between latency and glitch rate.
256ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     */
257ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung    public static final int PERFORMANCE_MODE_LOW_LATENCY = 1;
258ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung
259ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung    /**
260ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * Power saving performance mode for an {@link AudioTrack}.
261ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * If the device supports it, this
262ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * mode will enable a lower power path to the audio output sink.
263ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * In addition, this lower power path typically will have
264ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * deeper internal buffers and better underrun resistance,
265ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * with a tradeoff of higher latency.
266ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * <p>
267ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * In this mode, applications should attempt to use a larger buffer size
268ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * and deliver larger chunks of audio data per {@code write()} call.
269ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * Use {@link #getBufferSizeInFrames()} to determine
270ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * the actual buffer size of the {@code AudioTrack} as it may have increased
271ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * to accommodate a deeper buffer.
272ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     */
273ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung    public static final int PERFORMANCE_MODE_POWER_SAVING = 2;
274ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung
275ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung    // keep in sync with system/media/audio/include/system/audio-base.h
276ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung    private static final int AUDIO_OUTPUT_FLAG_FAST = 0x4;
277ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung    private static final int AUDIO_OUTPUT_FLAG_DEEP_BUFFER = 0x8;
278ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //--------------------------------------------------------------------------
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Member variables
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //--------------------
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
283ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * Indicates the state of the AudioTrack instance.
284340a6d09bdba7d4d99cef52a83a90fb96842c58aGlenn Kasten     * One of STATE_UNINITIALIZED, STATE_INITIALIZED, or STATE_NO_STATIC_DATA.
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mState = STATE_UNINITIALIZED;
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
288ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * Indicates the play state of the AudioTrack instance.
289340a6d09bdba7d4d99cef52a83a90fb96842c58aGlenn Kasten     * One of PLAYSTATE_STOPPED, PLAYSTATE_PAUSED, or PLAYSTATE_PLAYING.
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mPlayState = PLAYSTATE_STOPPED;
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
293340a6d09bdba7d4d99cef52a83a90fb96842c58aGlenn Kasten     * Lock to ensure mPlayState updates reflect the actual state of the object.
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Object mPlayStateLock = new Object();
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2971d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     * Sizes of the audio buffer.
2984bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung     * These values are set during construction and can be stale.
2991d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     * To obtain the current audio buffer frame count use {@link #getBufferSizeInFrames()}.
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mNativeBufferSizeInBytes = 0;
302e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten    private int mNativeBufferSizeInFrames = 0;
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
30486fad47e68e344b19fabeab1156c5e6742d8dfadGlenn Kasten     * Handler for events coming from the native code.
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
306d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean    private NativePositionEventHandlerDelegate mEventHandlerDelegate;
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
308ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * Looper associated with the thread that creates the AudioTrack instance.
309105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     */
310b09707a041957f055cee3d290c85763cfef8d986Glenn Kasten    private final Looper mInitializationLooper;
311105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    /**
3128d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten     * The audio data source sampling rate in Hz.
3131cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten     * Never {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED}.
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
315340a6d09bdba7d4d99cef52a83a90fb96842c58aGlenn Kasten    private int mSampleRate; // initialized by all constructors via audioParamCheck()
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
317340a6d09bdba7d4d99cef52a83a90fb96842c58aGlenn Kasten     * The number of audio output channels (1 is mono, 2 is stereo, etc.).
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mChannelCount = 1;
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
321a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung     * The audio channel mask used for calling native AudioTrack
3223026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent     */
3239ea5e5564812bb88e62d0c4fae8f1d40d8a6e7e0Glenn Kasten    private int mChannelMask = AudioFormat.CHANNEL_OUT_MONO;
3243026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent
3253026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent    /**
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The type of the audio stream to play. See
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   {@link AudioManager#STREAM_VOICE_CALL}, {@link AudioManager#STREAM_SYSTEM},
3285c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten     *   {@link AudioManager#STREAM_RING}, {@link AudioManager#STREAM_MUSIC},
329b282e08ab641d4fc74d0324b7a0ce30926638dd5Glenn Kasten     *   {@link AudioManager#STREAM_ALARM}, {@link AudioManager#STREAM_NOTIFICATION}, and
330b282e08ab641d4fc74d0324b7a0ce30926638dd5Glenn Kasten     *   {@link AudioManager#STREAM_DTMF}.
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mStreamType = AudioManager.STREAM_MUSIC;
333a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
335340a6d09bdba7d4d99cef52a83a90fb96842c58aGlenn Kasten     * The way audio is consumed by the audio sink, one of MODE_STATIC or MODE_STREAM.
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mDataLoadMode = MODE_STREAM;
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
339a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung     * The current channel position mask, as specified on AudioTrack creation.
340a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung     * Can be set simultaneously with channel index mask {@link #mChannelIndexMask}.
341a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung     * May be set to {@link AudioFormat#CHANNEL_INVALID} if a channel index mask is specified.
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
343a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent    private int mChannelConfiguration = AudioFormat.CHANNEL_OUT_MONO;
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
345340a6d09bdba7d4d99cef52a83a90fb96842c58aGlenn Kasten     * The channel index mask if specified, otherwise 0.
346a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung     */
347a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung    private int mChannelIndexMask = 0;
348a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung    /**
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The encoding of the audio samples.
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see AudioFormat#ENCODING_PCM_8BIT
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see AudioFormat#ENCODING_PCM_16BIT
3527d60bcd2d950e3571c00ce9f1c492c6bd58334c9Glenn Kasten     * @see AudioFormat#ENCODING_PCM_FLOAT
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
354340a6d09bdba7d4d99cef52a83a90fb96842c58aGlenn Kasten    private int mAudioFormat;   // initialized by all constructors via audioParamCheck()
355619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent    /**
356619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     * Audio session ID
357619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     */
35833b840444f5a481dd31e129079d3c0cf3acdf80eGlenn Kasten    private int mSessionId = AudioManager.AUDIO_SESSION_ID_GENERATE;
3591af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock    /**
360cfe964a09ca05778e5dd84f2fd24119b89401696Rachad     * HW_AV_SYNC track AV Sync Header
361cfe964a09ca05778e5dd84f2fd24119b89401696Rachad     */
362cfe964a09ca05778e5dd84f2fd24119b89401696Rachad    private ByteBuffer mAvSyncHeader = null;
363cfe964a09ca05778e5dd84f2fd24119b89401696Rachad    /**
364cfe964a09ca05778e5dd84f2fd24119b89401696Rachad     * HW_AV_SYNC track audio data bytes remaining to write after current AV sync header
365cfe964a09ca05778e5dd84f2fd24119b89401696Rachad     */
366cfe964a09ca05778e5dd84f2fd24119b89401696Rachad    private int mAvSyncBytesRemaining = 0;
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //--------------------------------
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Used exclusively by native code
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //--------------------
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
372ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean     * @hide
373ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * Accessed by native methods: provides access to C++ AudioTrack object.
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @SuppressWarnings("unused")
376ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean    protected long mNativeTrackInJavaObj;
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Accessed by native methods: provides access to the JNI data (i.e. resources used by
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the native AudioTrack object, but not stored in it).
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @SuppressWarnings("unused")
382075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    private long mJniData;
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //--------------------------------------------------------------------------
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Constructor, Finalize
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //--------------------
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Class constructor.
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param streamType the type of the audio stream. See
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   {@link AudioManager#STREAM_VOICE_CALL}, {@link AudioManager#STREAM_SYSTEM},
3925c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten     *   {@link AudioManager#STREAM_RING}, {@link AudioManager#STREAM_MUSIC},
3935c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten     *   {@link AudioManager#STREAM_ALARM}, and {@link AudioManager#STREAM_NOTIFICATION}.
3948d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten     * @param sampleRateInHz the initial source sample rate expressed in Hz.
3951cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten     *   {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED} means to use a route-dependent value
3961cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten     *   which is usually the sample rate of the sink.
3971cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten     *   {@link #getSampleRate()} can be used to retrieve the actual sample rate chosen.
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param channelConfig describes the configuration of the audio channels.
399a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent     *   See {@link AudioFormat#CHANNEL_OUT_MONO} and
400a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent     *   {@link AudioFormat#CHANNEL_OUT_STEREO}
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param audioFormat the format in which the audio data is represented.
4027d60bcd2d950e3571c00ce9f1c492c6bd58334c9Glenn Kasten     *   See {@link AudioFormat#ENCODING_PCM_16BIT},
4037d60bcd2d950e3571c00ce9f1c492c6bd58334c9Glenn Kasten     *   {@link AudioFormat#ENCODING_PCM_8BIT},
4047d60bcd2d950e3571c00ce9f1c492c6bd58334c9Glenn Kasten     *   and {@link AudioFormat#ENCODING_PCM_FLOAT}.
405e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * @param bufferSizeInBytes the total size (in bytes) of the internal buffer where audio data is
4061d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   read from for playback. This should be a nonzero multiple of the frame size in bytes.
4074bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung     *   <p> If the track's creation mode is {@link #MODE_STATIC},
408e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     *   this is the maximum length sample, or audio clip, that can be played by this instance.
4094bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung     *   <p> If the track's creation mode is {@link #MODE_STREAM},
4104bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung     *   this should be the desired buffer size
4114bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung     *   for the <code>AudioTrack</code> to satisfy the application's
4121d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   latency requirements.
4134bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung     *   If <code>bufferSizeInBytes</code> is less than the
4141d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   minimum buffer size for the output sink, it is increased to the minimum
4154bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung     *   buffer size.
416e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung     *   The method {@link #getBufferSizeInFrames()} returns the
4171d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   actual size in frames of the buffer created, which
4181d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   determines the minimum frequency to write
4194bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung     *   to the streaming <code>AudioTrack</code> to avoid underrun.
4201d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   See {@link #getMinBufferSize(int, int, int)} to determine the estimated minimum buffer size
4211d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   for an AudioTrack instance in streaming mode.
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param mode streaming or static buffer. See {@link #MODE_STATIC} and {@link #MODE_STREAM}
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws java.lang.IllegalArgumentException
4242f7511fd065aa121287da3d4b5b8bea3e528b0bcJean-Michel Trivi     * @deprecated use {@link Builder} or
4252f7511fd065aa121287da3d4b5b8bea3e528b0bcJean-Michel Trivi     *   {@link #AudioTrack(AudioAttributes, AudioFormat, int, int, int)} to specify the
4262f7511fd065aa121287da3d4b5b8bea3e528b0bcJean-Michel Trivi     *   {@link AudioAttributes} instead of the stream type which is only for volume control.
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat,
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int bufferSizeInBytes, int mode)
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    throws IllegalArgumentException {
431619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent        this(streamType, sampleRateInHz, channelConfig, audioFormat,
43233b840444f5a481dd31e129079d3c0cf3acdf80eGlenn Kasten                bufferSizeInBytes, mode, AudioManager.AUDIO_SESSION_ID_GENERATE);
433619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent    }
434619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent
435619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent    /**
436619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     * Class constructor with audio session. Use this constructor when the AudioTrack must be
437619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     * attached to a particular audio session. The primary use of the audio session ID is to
438619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     * associate audio effects to a particular instance of AudioTrack: if an audio session ID
439619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     * is provided when creating an AudioEffect, this effect will be applied only to audio tracks
440619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     * and media players in the same session and not to the output mix.
441619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     * When an AudioTrack is created without specifying a session, it will create its own session
4428d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten     * which can be retrieved by calling the {@link #getAudioSessionId()} method.
4435c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten     * If a non-zero session ID is provided, this AudioTrack will share effects attached to this
4445c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten     * session
4455c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten     * with all other media players or audio tracks in the same session, otherwise a new session
4465c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten     * will be created for this track if none is supplied.
447619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     * @param streamType the type of the audio stream. See
448619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     *   {@link AudioManager#STREAM_VOICE_CALL}, {@link AudioManager#STREAM_SYSTEM},
4495c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten     *   {@link AudioManager#STREAM_RING}, {@link AudioManager#STREAM_MUSIC},
4505c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten     *   {@link AudioManager#STREAM_ALARM}, and {@link AudioManager#STREAM_NOTIFICATION}.
4518d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten     * @param sampleRateInHz the initial source sample rate expressed in Hz.
4521cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten     *   {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED} means to use a route-dependent value
4531cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten     *   which is usually the sample rate of the sink.
454619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     * @param channelConfig describes the configuration of the audio channels.
455619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     *   See {@link AudioFormat#CHANNEL_OUT_MONO} and
456619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     *   {@link AudioFormat#CHANNEL_OUT_STEREO}
457619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     * @param audioFormat the format in which the audio data is represented.
458619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     *   See {@link AudioFormat#ENCODING_PCM_16BIT} and
4597d60bcd2d950e3571c00ce9f1c492c6bd58334c9Glenn Kasten     *   {@link AudioFormat#ENCODING_PCM_8BIT},
4607d60bcd2d950e3571c00ce9f1c492c6bd58334c9Glenn Kasten     *   and {@link AudioFormat#ENCODING_PCM_FLOAT}.
4611d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     * @param bufferSizeInBytes the total size (in bytes) of the internal buffer where audio data is
4621d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   read from for playback. This should be a nonzero multiple of the frame size in bytes.
4631d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   <p> If the track's creation mode is {@link #MODE_STATIC},
4641d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   this is the maximum length sample, or audio clip, that can be played by this instance.
4651d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   <p> If the track's creation mode is {@link #MODE_STREAM},
4661d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   this should be the desired buffer size
4671d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   for the <code>AudioTrack</code> to satisfy the application's
4681d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   latency requirements.
4691d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   If <code>bufferSizeInBytes</code> is less than the
4701d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   minimum buffer size for the output sink, it is increased to the minimum
4711d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   buffer size.
4721d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   The method {@link #getBufferSizeInFrames()} returns the
4731d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   actual size in frames of the buffer created, which
4741d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   determines the minimum frequency to write
4751d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   to the streaming <code>AudioTrack</code> to avoid underrun.
4761d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   You can write data into this buffer in smaller chunks than this size.
4771d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   See {@link #getMinBufferSize(int, int, int)} to determine the estimated minimum buffer size
4781d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   for an AudioTrack instance in streaming mode.
479619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     * @param mode streaming or static buffer. See {@link #MODE_STATIC} and {@link #MODE_STREAM}
480619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     * @param sessionId Id of audio session the AudioTrack must be attached to
481619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     * @throws java.lang.IllegalArgumentException
4822f7511fd065aa121287da3d4b5b8bea3e528b0bcJean-Michel Trivi     * @deprecated use {@link Builder} or
4832f7511fd065aa121287da3d4b5b8bea3e528b0bcJean-Michel Trivi     *   {@link #AudioTrack(AudioAttributes, AudioFormat, int, int, int)} to specify the
4842f7511fd065aa121287da3d4b5b8bea3e528b0bcJean-Michel Trivi     *   {@link AudioAttributes} instead of the stream type which is only for volume control.
485619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     */
486619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent    public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat,
487619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent            int bufferSizeInBytes, int mode, int sessionId)
488619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent    throws IllegalArgumentException {
489a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten        // mState already == STATE_UNINITIALIZED
490a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi        this((new AudioAttributes.Builder())
491a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                    .setLegacyStreamType(streamType)
492a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                    .build(),
493a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                (new AudioFormat.Builder())
494a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                    .setChannelMask(channelConfig)
495a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                    .setEncoding(audioFormat)
496a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                    .setSampleRate(sampleRateInHz)
497a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                    .build(),
498a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                bufferSizeInBytes,
499a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                mode, sessionId);
5002f7511fd065aa121287da3d4b5b8bea3e528b0bcJean-Michel Trivi        deprecateStreamTypeForPlayback(streamType, "AudioTrack", "AudioTrack()");
501a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi    }
502a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi
503a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi    /**
5047f6ee760b0aee76bdb9fe61ac7ed1465c0da3489Jean-Michel Trivi     * Class constructor with {@link AudioAttributes} and {@link AudioFormat}.
5057f6ee760b0aee76bdb9fe61ac7ed1465c0da3489Jean-Michel Trivi     * @param attributes a non-null {@link AudioAttributes} instance.
5067f6ee760b0aee76bdb9fe61ac7ed1465c0da3489Jean-Michel Trivi     * @param format a non-null {@link AudioFormat} instance describing the format of the data
5077f6ee760b0aee76bdb9fe61ac7ed1465c0da3489Jean-Michel Trivi     *     that will be played through this AudioTrack. See {@link AudioFormat.Builder} for
5087f6ee760b0aee76bdb9fe61ac7ed1465c0da3489Jean-Michel Trivi     *     configuring the audio format parameters such as encoding, channel mask and sample rate.
5091d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     * @param bufferSizeInBytes the total size (in bytes) of the internal buffer where audio data is
5101d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   read from for playback. This should be a nonzero multiple of the frame size in bytes.
5111d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   <p> If the track's creation mode is {@link #MODE_STATIC},
5121d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   this is the maximum length sample, or audio clip, that can be played by this instance.
5131d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   <p> If the track's creation mode is {@link #MODE_STREAM},
5141d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   this should be the desired buffer size
5151d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   for the <code>AudioTrack</code> to satisfy the application's
5161d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   latency requirements.
5171d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   If <code>bufferSizeInBytes</code> is less than the
5181d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   minimum buffer size for the output sink, it is increased to the minimum
5191d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   buffer size.
5201d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   The method {@link #getBufferSizeInFrames()} returns the
5211d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   actual size in frames of the buffer created, which
5221d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   determines the minimum frequency to write
5231d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   to the streaming <code>AudioTrack</code> to avoid underrun.
5241d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   See {@link #getMinBufferSize(int, int, int)} to determine the estimated minimum buffer size
5251d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *   for an AudioTrack instance in streaming mode.
5267f6ee760b0aee76bdb9fe61ac7ed1465c0da3489Jean-Michel Trivi     * @param mode streaming or static buffer. See {@link #MODE_STATIC} and {@link #MODE_STREAM}.
527289cc8e887f786f557faab226a1e01abb9a632a6Jean-Michel Trivi     * @param sessionId ID of audio session the AudioTrack must be attached to, or
528289cc8e887f786f557faab226a1e01abb9a632a6Jean-Michel Trivi     *   {@link AudioManager#AUDIO_SESSION_ID_GENERATE} if the session isn't known at construction
529289cc8e887f786f557faab226a1e01abb9a632a6Jean-Michel Trivi     *   time. See also {@link AudioManager#generateAudioSessionId()} to obtain a session ID before
530289cc8e887f786f557faab226a1e01abb9a632a6Jean-Michel Trivi     *   construction.
5317f6ee760b0aee76bdb9fe61ac7ed1465c0da3489Jean-Michel Trivi     * @throws IllegalArgumentException
532a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi     */
533a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi    public AudioTrack(AudioAttributes attributes, AudioFormat format, int bufferSizeInBytes,
534a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi            int mode, int sessionId)
535a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi                    throws IllegalArgumentException {
536292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi        super(attributes, AudioPlaybackConfiguration.PLAYER_TYPE_JAM_AUDIOTRACK);
537a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi        // mState already == STATE_UNINITIALIZED
5385c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten
5397f6ee760b0aee76bdb9fe61ac7ed1465c0da3489Jean-Michel Trivi        if (format == null) {
5407f6ee760b0aee76bdb9fe61ac7ed1465c0da3489Jean-Michel Trivi            throw new IllegalArgumentException("Illegal null AudioFormat");
5417f6ee760b0aee76bdb9fe61ac7ed1465c0da3489Jean-Michel Trivi        }
5427f6ee760b0aee76bdb9fe61ac7ed1465c0da3489Jean-Michel Trivi
5439025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung        // Check if we should enable deep buffer mode
5449025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung        if (shouldEnablePowerSaving(mAttributes, format, bufferSizeInBytes, mode)) {
5459025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung            mAttributes = new AudioAttributes.Builder(mAttributes)
5469025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung                .replaceFlags((mAttributes.getAllFlags()
5479025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung                        | AudioAttributes.FLAG_DEEP_BUFFER)
5489025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung                        & ~AudioAttributes.FLAG_LOW_LATENCY)
5499025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung                .build();
5509025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung        }
5519025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung
5525c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten        // remember which looper is associated with the AudioTrack instantiation
553b09707a041957f055cee3d290c85763cfef8d986Glenn Kasten        Looper looper;
554b09707a041957f055cee3d290c85763cfef8d986Glenn Kasten        if ((looper = Looper.myLooper()) == null) {
555b09707a041957f055cee3d290c85763cfef8d986Glenn Kasten            looper = Looper.getMainLooper();
556105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5581cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten        int rate = format.getSampleRate();
5591cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten        if (rate == AudioFormat.SAMPLE_RATE_UNSPECIFIED) {
5601cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten            rate = 0;
561a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi        }
5621cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten
563a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung        int channelIndexMask = 0;
564a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung        if ((format.getPropertySetMask()
565a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung                & AudioFormat.AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_INDEX_MASK) != 0) {
566a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung            channelIndexMask = format.getChannelIndexMask();
567a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung        }
568a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung        int channelMask = 0;
569a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung        if ((format.getPropertySetMask()
570a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung                & AudioFormat.AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_MASK) != 0) {
571a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi            channelMask = format.getChannelMask();
572a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung        } else if (channelIndexMask == 0) { // if no masks at all, use stereo
573a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung            channelMask = AudioFormat.CHANNEL_OUT_FRONT_LEFT
574a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung                    | AudioFormat.CHANNEL_OUT_FRONT_RIGHT;
575a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi        }
576a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi        int encoding = AudioFormat.ENCODING_DEFAULT;
577a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi        if ((format.getPropertySetMask() & AudioFormat.AUDIO_FORMAT_HAS_PROPERTY_ENCODING) != 0) {
578a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi            encoding = format.getEncoding();
579a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi        }
580a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung        audioParamCheck(rate, channelMask, channelIndexMask, encoding, mode);
581a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi        mStreamType = AudioSystem.STREAM_DEFAULT;
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        audioBuffSizeCheck(bufferSizeInBytes);
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
585a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi        mInitializationLooper = looper;
586a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi
587619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent        if (sessionId < 0) {
588f4e58051e22ad4e21c7cd436c37cc5665c194d1cGlenn Kasten            throw new IllegalArgumentException("Invalid audio session ID: "+sessionId);
589619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent        }
590619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent
5911cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten        int[] sampleRate = new int[] {mSampleRate};
592619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent        int[] session = new int[1];
593619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent        session[0] = sessionId;
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // native initialization
595a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi        int initResult = native_setup(new WeakReference<AudioTrack>(this), mAttributes,
5961cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten                sampleRate, mChannelMask, mChannelIndexMask, mAudioFormat,
5979b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean                mNativeBufferSizeInBytes, mDataLoadMode, session, 0 /*nativeTrackInJavaObj*/);
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (initResult != SUCCESS) {
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            loge("Error code "+initResult+" when initializing AudioTrack.");
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return; // with mState == STATE_UNINITIALIZED
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6031cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten        mSampleRate = sampleRate[0];
604619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent        mSessionId = session[0];
605619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDataLoadMode == MODE_STATIC) {
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mState = STATE_NO_STATIC_DATA;
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mState = STATE_INITIALIZED;
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6119dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi
6129dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi        baseRegisterPlayer();
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
61535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi    /**
616ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean     * A constructor which explicitly connects a Native (C++) AudioTrack. For use by
617ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean     * the AudioTrackRoutingProxy subclass.
618ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean     * @param nativeTrackInJavaObj a C/C++ pointer to a native AudioTrack
619ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean     * (associated with an OpenSL ES player).
62014b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean     * IMPORTANT: For "N", this method is ONLY called to setup a Java routing proxy,
62114b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean     * i.e. IAndroidConfiguration::AcquireJavaProxy(). If we call with a 0 in nativeTrackInJavaObj
62214b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean     * it means that the OpenSL player interface hasn't been realized, so there is no native
62314b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean     * Audiotrack to connect to. In this case wait to call deferred_connect() until the
62414b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean     * OpenSLES interface is realized.
625ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean     */
626ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean    /*package*/ AudioTrack(long nativeTrackInJavaObj) {
627292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi        super(new AudioAttributes.Builder().build(),
628292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi                AudioPlaybackConfiguration.PLAYER_TYPE_JAM_AUDIOTRACK);
629ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean        // "final"s
63014b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean        mNativeTrackInJavaObj = 0;
63114b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean        mJniData = 0;
632ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean
633ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean        // remember which looper is associated with the AudioTrack instantiation
634ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean        Looper looper;
635ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean        if ((looper = Looper.myLooper()) == null) {
636ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean            looper = Looper.getMainLooper();
637ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean        }
638ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean        mInitializationLooper = looper;
639ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean
640ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean        // other initialization...
64114b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean        if (nativeTrackInJavaObj != 0) {
6429dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi            baseRegisterPlayer();
64314b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean            deferred_connect(nativeTrackInJavaObj);
64414b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean        } else {
64514b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean            mState = STATE_UNINITIALIZED;
6469b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean        }
64714b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean    }
6489b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean
64914b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean    /**
65014b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean     * @hide
65114b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean     */
65214b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean    /* package */ void deferred_connect(long nativeTrackInJavaObj) {
65314b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean        if (mState != STATE_INITIALIZED) {
65414b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean            // Note that for this native_setup, we are providing an already created/initialized
65514b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean            // *Native* AudioTrack, so the attributes parameters to native_setup() are ignored.
65614b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean            int[] session = { 0 };
65714b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean            int[] rates = { 0 };
65814b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean            int initResult = native_setup(new WeakReference<AudioTrack>(this),
65914b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean                    null /*mAttributes - NA*/,
66014b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean                    rates /*sampleRate - NA*/,
66114b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean                    0 /*mChannelMask - NA*/,
66214b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean                    0 /*mChannelIndexMask - NA*/,
66314b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean                    0 /*mAudioFormat - NA*/,
66414b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean                    0 /*mNativeBufferSizeInBytes - NA*/,
66514b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean                    0 /*mDataLoadMode - NA*/,
66614b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean                    session,
66714b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean                    nativeTrackInJavaObj);
66814b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean            if (initResult != SUCCESS) {
66914b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean                loge("Error code "+initResult+" when initializing AudioTrack.");
67014b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean                return; // with mState == STATE_UNINITIALIZED
67114b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean            }
67214b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean
67314b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean            mSessionId = session[0];
674ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean
67514b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean            mState = STATE_INITIALIZED;
67614b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean        }
677ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean    }
678ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean
679ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean    /**
68035ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi     * Builder class for {@link AudioTrack} objects.
68135ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi     * Use this class to configure and create an <code>AudioTrack</code> instance. By setting audio
68235ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi     * attributes and audio format parameters, you indicate which of those vary from the default
68335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi     * behavior on the device.
68435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi     * <p> Here is an example where <code>Builder</code> is used to specify all {@link AudioFormat}
68535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi     * parameters, to be used by a new <code>AudioTrack</code> instance:
68635ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi     *
68735ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi     * <pre class="prettyprint">
68835ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi     * AudioTrack player = new AudioTrack.Builder()
68935ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi     *         .setAudioAttributes(new AudioAttributes.Builder()
69035ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi     *                  .setUsage(AudioAttributes.USAGE_ALARM)
691e27a75173f0eb43c1a5d52f35f543d50a859e144Jean-Michel Trivi     *                  .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
69235ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi     *                  .build())
69335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi     *         .setAudioFormat(new AudioFormat.Builder()
69435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi     *                 .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
69549962261b3c05eea70fe66076d27c8c0b80ba280Jean-Michel Trivi     *                 .setSampleRate(44100)
69635ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi     *                 .setChannelMask(AudioFormat.CHANNEL_OUT_STEREO)
69735ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi     *                 .build())
698e27a75173f0eb43c1a5d52f35f543d50a859e144Jean-Michel Trivi     *         .setBufferSizeInBytes(minBuffSize)
69935ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi     *         .build();
70035ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi     * </pre>
70135ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi     * <p>
70235ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi     * If the audio attributes are not set with {@link #setAudioAttributes(AudioAttributes)},
70335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi     * attributes comprising {@link AudioAttributes#USAGE_MEDIA} will be used.
7040f0da49fce053eec4f95ce6a8e553d77f9df62a4Eric Laurent     * <br>If the audio format is not specified or is incomplete, its channel configuration will be
70535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi     * {@link AudioFormat#CHANNEL_OUT_STEREO} and the encoding will be
70635ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi     * {@link AudioFormat#ENCODING_PCM_16BIT}.
7070f0da49fce053eec4f95ce6a8e553d77f9df62a4Eric Laurent     * The sample rate will depend on the device actually selected for playback and can be queried
7080f0da49fce053eec4f95ce6a8e553d77f9df62a4Eric Laurent     * with {@link #getSampleRate()} method.
7094bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung     * <br>If the buffer size is not specified with {@link #setBufferSizeInBytes(int)},
7104bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung     * and the mode is {@link AudioTrack#MODE_STREAM}, the minimum buffer size is used.
71135ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi     * <br>If the transfer mode is not specified with {@link #setTransferMode(int)},
7124bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung     * <code>MODE_STREAM</code> will be used.
71335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi     * <br>If the session ID is not specified with {@link #setSessionId(int)}, a new one will
71435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi     * be generated.
71535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi     */
71635ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi    public static class Builder {
71735ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi        private AudioAttributes mAttributes;
71835ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi        private AudioFormat mFormat;
71935ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi        private int mBufferSizeInBytes;
72035ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi        private int mSessionId = AudioManager.AUDIO_SESSION_ID_GENERATE;
72135ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi        private int mMode = MODE_STREAM;
722ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung        private int mPerformanceMode = PERFORMANCE_MODE_NONE;
72335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi
72435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi        /**
72535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         * Constructs a new Builder with the default values as described above.
72635ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         */
72735ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi        public Builder() {
72835ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi        }
72935ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi
73035ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi        /**
73135ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         * Sets the {@link AudioAttributes}.
73235ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         * @param attributes a non-null {@link AudioAttributes} instance that describes the audio
73335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         *     data to be played.
73435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         * @return the same Builder instance.
73535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         * @throws IllegalArgumentException
73635ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         */
73735ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi        public @NonNull Builder setAudioAttributes(@NonNull AudioAttributes attributes)
73835ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi                throws IllegalArgumentException {
73935ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi            if (attributes == null) {
74035ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi                throw new IllegalArgumentException("Illegal null AudioAttributes argument");
74135ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi            }
74235ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi            // keep reference, we only copy the data when building
74335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi            mAttributes = attributes;
74435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi            return this;
74535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi        }
74635ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi
74735ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi        /**
74835ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         * Sets the format of the audio data to be played by the {@link AudioTrack}.
74935ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         * See {@link AudioFormat.Builder} for configuring the audio format parameters such
75035ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         * as encoding, channel mask and sample rate.
75135ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         * @param format a non-null {@link AudioFormat} instance.
75235ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         * @return the same Builder instance.
75335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         * @throws IllegalArgumentException
75435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         */
75535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi        public @NonNull Builder setAudioFormat(@NonNull AudioFormat format)
75635ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi                throws IllegalArgumentException {
75735ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi            if (format == null) {
75835ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi                throw new IllegalArgumentException("Illegal null AudioFormat argument");
75935ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi            }
76035ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi            // keep reference, we only copy the data when building
76135ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi            mFormat = format;
76235ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi            return this;
76335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi        }
76435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi
76535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi        /**
76635ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         * Sets the total size (in bytes) of the buffer where audio data is read from for playback.
76735ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         * If using the {@link AudioTrack} in streaming mode
76835ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         * (see {@link AudioTrack#MODE_STREAM}, you can write data into this buffer in smaller
76935ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         * chunks than this size. See {@link #getMinBufferSize(int, int, int)} to determine
7701d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten         * the estimated minimum buffer size for the creation of an AudioTrack instance
7711d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten         * in streaming mode.
77235ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         * <br>If using the <code>AudioTrack</code> in static mode (see
77335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         * {@link AudioTrack#MODE_STATIC}), this is the maximum size of the sound that will be
77435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         * played by this instance.
77535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         * @param bufferSizeInBytes
77635ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         * @return the same Builder instance.
77735ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         * @throws IllegalArgumentException
77835ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         */
77935ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi        public @NonNull Builder setBufferSizeInBytes(int bufferSizeInBytes)
78035ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi                throws IllegalArgumentException {
78135ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi            if (bufferSizeInBytes <= 0) {
78235ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi                throw new IllegalArgumentException("Invalid buffer size " + bufferSizeInBytes);
78335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi            }
78435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi            mBufferSizeInBytes = bufferSizeInBytes;
78535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi            return this;
78635ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi        }
78735ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi
78835ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi        /**
78935ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         * Sets the mode under which buffers of audio data are transferred from the
79035ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         * {@link AudioTrack} to the framework.
79135ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         * @param mode one of {@link AudioTrack#MODE_STREAM}, {@link AudioTrack#MODE_STATIC}.
79235ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         * @return the same Builder instance.
79335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         * @throws IllegalArgumentException
79435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         */
79535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi        public @NonNull Builder setTransferMode(@TransferMode int mode)
79635ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi                throws IllegalArgumentException {
79735ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi            switch(mode) {
79835ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi                case MODE_STREAM:
79935ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi                case MODE_STATIC:
80035ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi                    mMode = mode;
80135ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi                    break;
80235ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi                default:
80335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi                    throw new IllegalArgumentException("Invalid transfer mode " + mode);
80435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi            }
80535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi            return this;
80635ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi        }
80735ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi
80835ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi        /**
80935ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         * Sets the session ID the {@link AudioTrack} will be attached to.
81035ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         * @param sessionId a strictly positive ID number retrieved from another
81135ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         *     <code>AudioTrack</code> via {@link AudioTrack#getAudioSessionId()} or allocated by
81235ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         *     {@link AudioManager} via {@link AudioManager#generateAudioSessionId()}, or
81335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         *     {@link AudioManager#AUDIO_SESSION_ID_GENERATE}.
81435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         * @return the same Builder instance.
81535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         * @throws IllegalArgumentException
81635ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         */
81735ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi        public @NonNull Builder setSessionId(int sessionId)
81835ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi                throws IllegalArgumentException {
81935ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi            if ((sessionId != AudioManager.AUDIO_SESSION_ID_GENERATE) && (sessionId < 1)) {
82035ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi                throw new IllegalArgumentException("Invalid audio session ID " + sessionId);
82135ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi            }
82235ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi            mSessionId = sessionId;
82335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi            return this;
82435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi        }
82535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi
82635ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi        /**
827ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung         * Sets the {@link AudioTrack} performance mode.  This is an advisory request which
828ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung         * may not be supported by the particular device, and the framework is free
829ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung         * to ignore such request if it is incompatible with other requests or hardware.
830ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung         *
831ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung         * @param performanceMode one of
832ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung         * {@link AudioTrack#PERFORMANCE_MODE_NONE},
833ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung         * {@link AudioTrack#PERFORMANCE_MODE_LOW_LATENCY},
834ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung         * or {@link AudioTrack#PERFORMANCE_MODE_POWER_SAVING}.
835ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung         * @return the same Builder instance.
836ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung         * @throws IllegalArgumentException if {@code performanceMode} is not valid.
837ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung         */
838ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung        public @NonNull Builder setPerformanceMode(@PerformanceMode int performanceMode) {
839ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung            switch (performanceMode) {
840ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung                case PERFORMANCE_MODE_NONE:
841ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung                case PERFORMANCE_MODE_LOW_LATENCY:
842ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung                case PERFORMANCE_MODE_POWER_SAVING:
843ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung                    mPerformanceMode = performanceMode;
844ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung                    break;
845ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung                default:
846ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung                    throw new IllegalArgumentException(
847ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung                            "Invalid performance mode " + performanceMode);
848ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung            }
849ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung            return this;
850ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung        }
851ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung
852ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung        /**
85335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         * Builds an {@link AudioTrack} instance initialized with all the parameters set
85435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         * on this <code>Builder</code>.
8552d2d89363f0b794cbb63f389584fa4c5557ff51aAndy Hung         * @return a new successfully initialized {@link AudioTrack} instance.
85635ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         * @throws UnsupportedOperationException if the parameters set on the <code>Builder</code>
8572d2d89363f0b794cbb63f389584fa4c5557ff51aAndy Hung         *     were incompatible, or if they are not supported by the device,
8582d2d89363f0b794cbb63f389584fa4c5557ff51aAndy Hung         *     or if the device was not available.
85935ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi         */
86035ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi        public @NonNull AudioTrack build() throws UnsupportedOperationException {
86135ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi            if (mAttributes == null) {
86235ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi                mAttributes = new AudioAttributes.Builder()
86335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi                        .setUsage(AudioAttributes.USAGE_MEDIA)
86435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi                        .build();
86535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi            }
866ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung            switch (mPerformanceMode) {
867ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung            case PERFORMANCE_MODE_LOW_LATENCY:
868ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung                mAttributes = new AudioAttributes.Builder(mAttributes)
869ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung                    .replaceFlags((mAttributes.getAllFlags()
870ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung                            | AudioAttributes.FLAG_LOW_LATENCY)
871ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung                            & ~AudioAttributes.FLAG_DEEP_BUFFER)
872ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung                    .build();
873ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung                break;
874ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung            case PERFORMANCE_MODE_NONE:
8759025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung                if (!shouldEnablePowerSaving(mAttributes, mFormat, mBufferSizeInBytes, mMode)) {
8769025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung                    break; // do not enable deep buffer mode.
8779025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung                }
8789025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung                // permitted to fall through to enable deep buffer
879ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung            case PERFORMANCE_MODE_POWER_SAVING:
880ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung                mAttributes = new AudioAttributes.Builder(mAttributes)
881ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung                .replaceFlags((mAttributes.getAllFlags()
882ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung                        | AudioAttributes.FLAG_DEEP_BUFFER)
883ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung                        & ~AudioAttributes.FLAG_LOW_LATENCY)
884ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung                .build();
885ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung                break;
886ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung            }
887ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung
88835ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi            if (mFormat == null) {
88935ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi                mFormat = new AudioFormat.Builder()
89035ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi                        .setChannelMask(AudioFormat.CHANNEL_OUT_STEREO)
8911cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten                        //.setSampleRate(AudioFormat.SAMPLE_RATE_UNSPECIFIED)
89235ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi                        .setEncoding(AudioFormat.ENCODING_DEFAULT)
89335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi                        .build();
89435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi            }
89535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi            try {
8964bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung                // If the buffer size is not specified in streaming mode,
8974bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung                // use a single frame for the buffer size and let the
8984bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung                // native code figure out the minimum buffer size.
8994bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung                if (mMode == MODE_STREAM && mBufferSizeInBytes == 0) {
9004bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung                    mBufferSizeInBytes = mFormat.getChannelCount()
9014bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung                            * mFormat.getBytesPerSample(mFormat.getEncoding());
9024bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung                }
9032d2d89363f0b794cbb63f389584fa4c5557ff51aAndy Hung                final AudioTrack track = new AudioTrack(
9042d2d89363f0b794cbb63f389584fa4c5557ff51aAndy Hung                        mAttributes, mFormat, mBufferSizeInBytes, mMode, mSessionId);
9052d2d89363f0b794cbb63f389584fa4c5557ff51aAndy Hung                if (track.getState() == STATE_UNINITIALIZED) {
9062d2d89363f0b794cbb63f389584fa4c5557ff51aAndy Hung                    // release is not necessary
9072d2d89363f0b794cbb63f389584fa4c5557ff51aAndy Hung                    throw new UnsupportedOperationException("Cannot create AudioTrack");
9082d2d89363f0b794cbb63f389584fa4c5557ff51aAndy Hung                }
9092d2d89363f0b794cbb63f389584fa4c5557ff51aAndy Hung                return track;
91035ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi            } catch (IllegalArgumentException e) {
91135ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi                throw new UnsupportedOperationException(e.getMessage());
91235ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi            }
91335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi        }
91435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi    }
91535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi
916340a6d09bdba7d4d99cef52a83a90fb96842c58aGlenn Kasten    // mask of all the positional channels supported, however the allowed combinations
917340a6d09bdba7d4d99cef52a83a90fb96842c58aGlenn Kasten    // are further restricted by the matching left/right rule and CHANNEL_COUNT_MAX
9181b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi    private static final int SUPPORTED_OUT_CHANNELS =
9191b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi            AudioFormat.CHANNEL_OUT_FRONT_LEFT |
9201b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi            AudioFormat.CHANNEL_OUT_FRONT_RIGHT |
9211b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi            AudioFormat.CHANNEL_OUT_FRONT_CENTER |
9221b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi            AudioFormat.CHANNEL_OUT_LOW_FREQUENCY |
9231b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi            AudioFormat.CHANNEL_OUT_BACK_LEFT |
9241b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi            AudioFormat.CHANNEL_OUT_BACK_RIGHT |
925ad720aeea741d9058a7b4d326c9ab1b3ebcd7c62Andy Hung            AudioFormat.CHANNEL_OUT_BACK_CENTER |
926ad720aeea741d9058a7b4d326c9ab1b3ebcd7c62Andy Hung            AudioFormat.CHANNEL_OUT_SIDE_LEFT |
927ad720aeea741d9058a7b4d326c9ab1b3ebcd7c62Andy Hung            AudioFormat.CHANNEL_OUT_SIDE_RIGHT;
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9299025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung    // Returns a boolean whether the attributes, format, bufferSizeInBytes, mode allow
9309025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung    // power saving to be automatically enabled for an AudioTrack. Returns false if
9319025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung    // power saving is already enabled in the attributes parameter.
9329025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung    private static boolean shouldEnablePowerSaving(
9339025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung            @Nullable AudioAttributes attributes, @Nullable AudioFormat format,
9349025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung            int bufferSizeInBytes, int mode) {
9359025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung        // If no attributes, OK
9369025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung        // otherwise check attributes for USAGE_MEDIA and CONTENT_UNKNOWN, MUSIC, or MOVIE.
9379025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung        if (attributes != null &&
9389025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung                (attributes.getAllFlags() != 0  // cannot have any special flags
9399025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung                || attributes.getUsage() != AudioAttributes.USAGE_MEDIA
9409025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung                || (attributes.getContentType() != AudioAttributes.CONTENT_TYPE_UNKNOWN
9419025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung                    && attributes.getContentType() != AudioAttributes.CONTENT_TYPE_MUSIC
9429025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung                    && attributes.getContentType() != AudioAttributes.CONTENT_TYPE_MOVIE))) {
9439025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung            return false;
9449025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung        }
9459025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung
9469025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung        // Format must be fully specified and be linear pcm
9479025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung        if (format == null
9489025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung                || format.getSampleRate() == AudioFormat.SAMPLE_RATE_UNSPECIFIED
9499025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung                || !AudioFormat.isEncodingLinearPcm(format.getEncoding())
9509025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung                || !AudioFormat.isValidEncoding(format.getEncoding())
9519025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung                || format.getChannelCount() < 1) {
9529025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung            return false;
9539025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung        }
9549025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung
9559025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung        // Mode must be streaming
9569025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung        if (mode != MODE_STREAM) {
9579025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung            return false;
9589025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung        }
9599025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung
9609025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung        // A buffer size of 0 is always compatible with deep buffer (when called from the Builder)
9619025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung        // but for app compatibility we only use deep buffer power saving for large buffer sizes.
9629025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung        if (bufferSizeInBytes != 0) {
9639025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung            final long BUFFER_TARGET_MODE_STREAM_MS = 100;
9649025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung            final int MILLIS_PER_SECOND = 1000;
9659025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung            final long bufferTargetSize =
9669025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung                    BUFFER_TARGET_MODE_STREAM_MS
9679025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung                    * format.getChannelCount()
9689025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung                    * format.getBytesPerSample(format.getEncoding())
9699025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung                    * format.getSampleRate()
9709025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung                    / MILLIS_PER_SECOND;
9719025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung            if (bufferSizeInBytes < bufferTargetSize) {
9729025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung                return false;
9739025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung            }
9749025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung        }
9759025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung
9769025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung        return true;
9779025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung    }
9789025cc090bf9fcb78f4417a63e24e41c8ea41dc0Andy Hung
9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Convenience method for the constructor's parameter checks.
9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // This is where constructor IllegalArgumentException-s are thrown
9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // postconditions:
9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //    mChannelCount is valid
9839ea5e5564812bb88e62d0c4fae8f1d40d8a6e7e0Glenn Kasten    //    mChannelMask is valid
9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //    mAudioFormat is valid
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //    mSampleRate is valid
9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //    mDataLoadMode is valid
987a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung    private void audioParamCheck(int sampleRateInHz, int channelConfig, int channelIndexMask,
988a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung                                 int audioFormat, int mode) {
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //--------------
9905c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten        // sample rate, note these values are subject to change
9911cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten        if ((sampleRateInHz < AudioFormat.SAMPLE_RATE_HZ_MIN ||
9921cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten                sampleRateInHz > AudioFormat.SAMPLE_RATE_HZ_MAX) &&
9931cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten                sampleRateInHz != AudioFormat.SAMPLE_RATE_UNSPECIFIED) {
994f4e58051e22ad4e21c7cd436c37cc5665c194d1cGlenn Kasten            throw new IllegalArgumentException(sampleRateInHz
995f4e58051e22ad4e21c7cd436c37cc5665c194d1cGlenn Kasten                    + "Hz is not a supported sample rate.");
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
997896a7f5fee46c24d31e9403abdf5813e4bb84ca5Glenn Kasten        mSampleRate = sampleRateInHz;
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
999621dbc874047b7f8c227f12fe15f977618f1f2f8Phil Burk        // IEC61937 is based on stereo. We could coerce it to stereo.
1000621dbc874047b7f8c227f12fe15f977618f1f2f8Phil Burk        // But the application needs to know the stream is stereo so that
1001621dbc874047b7f8c227f12fe15f977618f1f2f8Phil Burk        // it is encoded and played correctly. So better to just reject it.
1002621dbc874047b7f8c227f12fe15f977618f1f2f8Phil Burk        if (audioFormat == AudioFormat.ENCODING_IEC61937
1003621dbc874047b7f8c227f12fe15f977618f1f2f8Phil Burk                && channelConfig != AudioFormat.CHANNEL_OUT_STEREO) {
1004621dbc874047b7f8c227f12fe15f977618f1f2f8Phil Burk            throw new IllegalArgumentException(
1005621dbc874047b7f8c227f12fe15f977618f1f2f8Phil Burk                    "ENCODING_IEC61937 must be configured as CHANNEL_OUT_STEREO");
1006621dbc874047b7f8c227f12fe15f977618f1f2f8Phil Burk        }
1007621dbc874047b7f8c227f12fe15f977618f1f2f8Phil Burk
10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //--------------
10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // channel config
10103026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent        mChannelConfiguration = channelConfig;
10113026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent
10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (channelConfig) {
10133026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent        case AudioFormat.CHANNEL_OUT_DEFAULT: //AudioFormat.CHANNEL_CONFIGURATION_DEFAULT
1014a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent        case AudioFormat.CHANNEL_OUT_MONO:
10153026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent        case AudioFormat.CHANNEL_CONFIGURATION_MONO:
10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mChannelCount = 1;
10179ea5e5564812bb88e62d0c4fae8f1d40d8a6e7e0Glenn Kasten            mChannelMask = AudioFormat.CHANNEL_OUT_MONO;
10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
1019a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent        case AudioFormat.CHANNEL_OUT_STEREO:
10203026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent        case AudioFormat.CHANNEL_CONFIGURATION_STEREO:
10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mChannelCount = 2;
10229ea5e5564812bb88e62d0c4fae8f1d40d8a6e7e0Glenn Kasten            mChannelMask = AudioFormat.CHANNEL_OUT_STEREO;
10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        default:
1025a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung            if (channelConfig == AudioFormat.CHANNEL_INVALID && channelIndexMask != 0) {
1026a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung                mChannelCount = 0;
1027a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung                break; // channel index configuration only
1028a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung            }
1029d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi            if (!isMultichannelConfigSupported(channelConfig)) {
10301b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi                // input channel configuration features unsupported channels
1031f4e58051e22ad4e21c7cd436c37cc5665c194d1cGlenn Kasten                throw new IllegalArgumentException("Unsupported channel configuration.");
10321b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi            }
10339ea5e5564812bb88e62d0c4fae8f1d40d8a6e7e0Glenn Kasten            mChannelMask = channelConfig;
10348528ed43b41ff02535675c5da7425bef5195e73bAndy Hung            mChannelCount = AudioFormat.channelCountFromOutChannelMask(channelConfig);
10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1036a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung        // check the channel index configuration (if present)
1037a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung        mChannelIndexMask = channelIndexMask;
1038a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung        if (mChannelIndexMask != 0) {
1039a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung            // restrictive: indexMask could allow up to AUDIO_CHANNEL_BITS_LOG2
1040a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung            final int indexMask = (1 << CHANNEL_COUNT_MAX) - 1;
1041a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung            if ((channelIndexMask & ~indexMask) != 0) {
1042a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung                throw new IllegalArgumentException("Unsupported channel index configuration "
1043a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung                        + channelIndexMask);
1044a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung            }
1045a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung            int channelIndexCount = Integer.bitCount(channelIndexMask);
1046a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung            if (mChannelCount == 0) {
1047a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung                 mChannelCount = channelIndexCount;
1048a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung            } else if (mChannelCount != channelIndexCount) {
1049a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung                throw new IllegalArgumentException("Channel count must match");
1050a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung            }
1051a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung        }
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //--------------
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // audio format
1055ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent        if (audioFormat == AudioFormat.ENCODING_DEFAULT) {
1056ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent            audioFormat = AudioFormat.ENCODING_PCM_16BIT;
1057ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent        }
1058ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent
1059cae346633321e237f824f3ca10d7e6fff2307b2fEric Laurent        if (!AudioFormat.isPublicEncoding(audioFormat)) {
1060ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent            throw new IllegalArgumentException("Unsupported audio encoding.");
10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1062ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent        mAudioFormat = audioFormat;
10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //--------------
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // audio load mode
1066ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent        if (((mode != MODE_STREAM) && (mode != MODE_STATIC)) ||
1067ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent                ((mode != MODE_STREAM) && !AudioFormat.isEncodingLinearPcm(mAudioFormat))) {
1068f4e58051e22ad4e21c7cd436c37cc5665c194d1cGlenn Kasten            throw new IllegalArgumentException("Invalid mode.");
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1070896a7f5fee46c24d31e9403abdf5813e4bb84ca5Glenn Kasten        mDataLoadMode = mode;
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1073d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi    /**
1074d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi     * Convenience method to check that the channel configuration (a.k.a channel mask) is supported
1075d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi     * @param channelConfig the mask to validate
1076d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi     * @return false if the AudioTrack can't be used with such a mask
1077d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi     */
1078d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi    private static boolean isMultichannelConfigSupported(int channelConfig) {
1079d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi        // check for unsupported channels
1080d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi        if ((channelConfig & SUPPORTED_OUT_CHANNELS) != channelConfig) {
10811f61d01508651b4475397414e1fe06af1ab8fadaGlenn Kasten            loge("Channel configuration features unsupported channels");
1082d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi            return false;
1083d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi        }
10848528ed43b41ff02535675c5da7425bef5195e73bAndy Hung        final int channelCount = AudioFormat.channelCountFromOutChannelMask(channelConfig);
1085ad720aeea741d9058a7b4d326c9ab1b3ebcd7c62Andy Hung        if (channelCount > CHANNEL_COUNT_MAX) {
1086ad720aeea741d9058a7b4d326c9ab1b3ebcd7c62Andy Hung            loge("Channel configuration contains too many channels " +
1087ad720aeea741d9058a7b4d326c9ab1b3ebcd7c62Andy Hung                    channelCount + ">" + CHANNEL_COUNT_MAX);
1088ad720aeea741d9058a7b4d326c9ab1b3ebcd7c62Andy Hung            return false;
1089ad720aeea741d9058a7b4d326c9ab1b3ebcd7c62Andy Hung        }
1090d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi        // check for unsupported multichannel combinations:
1091d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi        // - FL/FR must be present
1092d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi        // - L/R channels must be paired (e.g. no single L channel)
1093d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi        final int frontPair =
1094d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi                AudioFormat.CHANNEL_OUT_FRONT_LEFT | AudioFormat.CHANNEL_OUT_FRONT_RIGHT;
1095d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi        if ((channelConfig & frontPair) != frontPair) {
10961f61d01508651b4475397414e1fe06af1ab8fadaGlenn Kasten                loge("Front channels must be present in multichannel configurations");
1097d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi                return false;
1098d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi        }
1099d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi        final int backPair =
1100d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi                AudioFormat.CHANNEL_OUT_BACK_LEFT | AudioFormat.CHANNEL_OUT_BACK_RIGHT;
1101d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi        if ((channelConfig & backPair) != 0) {
1102d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi            if ((channelConfig & backPair) != backPair) {
11031f61d01508651b4475397414e1fe06af1ab8fadaGlenn Kasten                loge("Rear channels can't be used independently");
1104d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi                return false;
1105d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi            }
1106d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi        }
1107ad720aeea741d9058a7b4d326c9ab1b3ebcd7c62Andy Hung        final int sidePair =
1108ad720aeea741d9058a7b4d326c9ab1b3ebcd7c62Andy Hung                AudioFormat.CHANNEL_OUT_SIDE_LEFT | AudioFormat.CHANNEL_OUT_SIDE_RIGHT;
1109ad720aeea741d9058a7b4d326c9ab1b3ebcd7c62Andy Hung        if ((channelConfig & sidePair) != 0
1110ad720aeea741d9058a7b4d326c9ab1b3ebcd7c62Andy Hung                && (channelConfig & sidePair) != sidePair) {
1111ad720aeea741d9058a7b4d326c9ab1b3ebcd7c62Andy Hung            loge("Side channels can't be used independently");
1112ad720aeea741d9058a7b4d326c9ab1b3ebcd7c62Andy Hung            return false;
1113ad720aeea741d9058a7b4d326c9ab1b3ebcd7c62Andy Hung        }
1114d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi        return true;
1115d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi    }
1116d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1118e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten    // Convenience method for the constructor's audio buffer size check.
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // preconditions:
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //    mChannelCount is valid
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //    mAudioFormat is valid
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // postcondition:
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //    mNativeBufferSizeInBytes is valid (multiple of frame size, positive)
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void audioBuffSizeCheck(int audioBufferSize) {
112543f4b276a56e6fb5a3c9637c0e3a6865657e3be7Phil Burk        // NB: this section is only valid with PCM or IEC61937 data.
11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //     To update when supporting compressed formats
1127ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent        int frameSizeInBytes;
112843f4b276a56e6fb5a3c9637c0e3a6865657e3be7Phil Burk        if (AudioFormat.isEncodingLinearFrames(mAudioFormat)) {
1129340a6d09bdba7d4d99cef52a83a90fb96842c58aGlenn Kasten            frameSizeInBytes = mChannelCount * AudioFormat.getBytesPerSample(mAudioFormat);
1130ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent        } else {
1131ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent            frameSizeInBytes = 1;
1132ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent        }
11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((audioBufferSize % frameSizeInBytes != 0) || (audioBufferSize < 1)) {
1134f4e58051e22ad4e21c7cd436c37cc5665c194d1cGlenn Kasten            throw new IllegalArgumentException("Invalid audio buffer size.");
11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNativeBufferSizeInBytes = audioBufferSize;
1138e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten        mNativeBufferSizeInFrames = audioBufferSize / frameSizeInBytes;
11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Releases the native AudioTrack resources.
11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void release() {
11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // even though native_release() stops the native AudioTrack, we need to stop
11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // AudioTrack subclasses too.
11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            stop();
1150fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten        } catch(IllegalStateException ise) {
11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // don't raise an exception, we're releasing the resources.
11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11533c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi        baseRelease();
11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        native_release();
11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mState = STATE_UNINITIALIZED;
11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void finalize() {
11603c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi        baseRelease();
11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        native_finalize();
11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //--------------------------------------------------------------------------
11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Getters
11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //--------------------
11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
116878cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * Returns the minimum gain value, which is the constant 0.0.
116978cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * Gain values less than 0.0 will be clamped to 0.0.
117078cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * <p>The word "volume" in the API name is historical; this is actually a linear gain.
117178cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * @return the minimum value, which is the constant 0.0.
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static public float getMinVolume() {
117478cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten        return GAIN_MIN;
11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
117878cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * Returns the maximum gain value, which is greater than or equal to 1.0.
117978cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * Gain values greater than the maximum will be clamped to the maximum.
118078cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * <p>The word "volume" in the API name is historical; this is actually a gain.
118178cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * expressed as a linear multiplier on sample values, where a maximum value of 1.0
118278cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * corresponds to a gain of 0 dB (sample values left unmodified).
118378cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * @return the maximum value, which is greater than or equal to 1.0.
11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static public float getMaxVolume() {
118678cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten        return GAIN_MAX;
11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11901cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten     * Returns the configured audio source sample rate in Hz.
11911cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten     * The initial source sample rate depends on the constructor parameters,
11921cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten     * but the source sample rate may change if {@link #setPlaybackRate(int)} is called.
11931cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten     * If the constructor had a specific sample rate, then the initial sink sample rate is that
11941cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten     * value.
11951cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten     * If the constructor had {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED},
11961cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten     * then the initial sink sample rate is a route-dependent default value based on the source [sic].
11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getSampleRate() {
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mSampleRate;
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1201fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten
12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1203263b4c97823295c41900210515d0c769a236190cAndy Hung     * Returns the current playback sample rate rate in Hz.
12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getPlaybackRate() {
12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return native_get_playback_rate();
12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12105f68c7a3f8400bcef233bf02d9a722f6d21f5c34Glenn Kasten     * Returns the current playback parameters.
12115f68c7a3f8400bcef233bf02d9a722f6d21f5c34Glenn Kasten     * See {@link #setPlaybackParams(PlaybackParams)} to set playback parameters
12122d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia     * @return current {@link PlaybackParams}.
1213263b4c97823295c41900210515d0c769a236190cAndy Hung     * @throws IllegalStateException if track is not initialized.
1214263b4c97823295c41900210515d0c769a236190cAndy Hung     */
12152d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia    public @NonNull PlaybackParams getPlaybackParams() {
12162d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia        return native_get_playback_params();
1217263b4c97823295c41900210515d0c769a236190cAndy Hung    }
1218263b4c97823295c41900210515d0c769a236190cAndy Hung
1219263b4c97823295c41900210515d0c769a236190cAndy Hung    /**
1220463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung     * Returns the configured audio data encoding. See {@link AudioFormat#ENCODING_PCM_8BIT},
1221463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung     * {@link AudioFormat#ENCODING_PCM_16BIT}, and {@link AudioFormat#ENCODING_PCM_FLOAT}.
12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getAudioFormat() {
12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mAudioFormat;
12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12282f7511fd065aa121287da3d4b5b8bea3e528b0bcJean-Michel Trivi     * Returns the volume stream type of this AudioTrack.
12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Compare the result against {@link AudioManager#STREAM_VOICE_CALL},
12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link AudioManager#STREAM_SYSTEM}, {@link AudioManager#STREAM_RING},
12315c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten     * {@link AudioManager#STREAM_MUSIC}, {@link AudioManager#STREAM_ALARM},
12322f7511fd065aa121287da3d4b5b8bea3e528b0bcJean-Michel Trivi     * {@link AudioManager#STREAM_NOTIFICATION}, {@link AudioManager#STREAM_DTMF} or
12332f7511fd065aa121287da3d4b5b8bea3e528b0bcJean-Michel Trivi     * {@link AudioManager#STREAM_ACCESSIBILITY}.
12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getStreamType() {
12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mStreamType;
12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1240a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung     * Returns the configured channel position mask.
1241463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung     * <p> For example, refer to {@link AudioFormat#CHANNEL_OUT_MONO},
1242a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung     * {@link AudioFormat#CHANNEL_OUT_STEREO}, {@link AudioFormat#CHANNEL_OUT_5POINT1}.
1243463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung     * This method may return {@link AudioFormat#CHANNEL_INVALID} if
1244340a6d09bdba7d4d99cef52a83a90fb96842c58aGlenn Kasten     * a channel index mask was used. Consider
1245463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung     * {@link #getFormat()} instead, to obtain an {@link AudioFormat},
1246463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung     * which contains both the channel position mask and the channel index mask.
12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getChannelConfiguration() {
12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mChannelConfiguration;
12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1253463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung     * Returns the configured <code>AudioTrack</code> format.
1254463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung     * @return an {@link AudioFormat} containing the
1255463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung     * <code>AudioTrack</code> parameters at the time of configuration.
1256463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung     */
1257463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung    public @NonNull AudioFormat getFormat() {
1258463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung        AudioFormat.Builder builder = new AudioFormat.Builder()
1259463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung            .setSampleRate(mSampleRate)
1260463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung            .setEncoding(mAudioFormat);
1261463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung        if (mChannelConfiguration != AudioFormat.CHANNEL_INVALID) {
1262463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung            builder.setChannelMask(mChannelConfiguration);
1263463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung        }
1264463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung        if (mChannelIndexMask != AudioFormat.CHANNEL_INVALID /* 0 */) {
1265463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung            builder.setChannelIndexMask(mChannelIndexMask);
1266463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung        }
1267463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung        return builder.build();
1268463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung    }
1269463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung
1270463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung    /**
12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the configured number of channels.
12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getChannelCount() {
12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mChannelCount;
12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the state of the AudioTrack instance. This is useful after the
12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * AudioTrack instance has been created to check if it was initialized
1280e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * properly. This ensures that the appropriate resources have been acquired.
1281340a6d09bdba7d4d99cef52a83a90fb96842c58aGlenn Kasten     * @see #STATE_UNINITIALIZED
1282ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * @see #STATE_INITIALIZED
1283ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * @see #STATE_NO_STATIC_DATA
12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getState() {
12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mState;
12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the playback state of the AudioTrack instance.
12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #PLAYSTATE_STOPPED
12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #PLAYSTATE_PAUSED
12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #PLAYSTATE_PLAYING
12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getPlayState() {
129606e0333c7eb50533cc6e0f7b61812d2840844296Narayan Kamath        synchronized (mPlayStateLock) {
129706e0333c7eb50533cc6e0f7b61812d2840844296Narayan Kamath            return mPlayState;
129806e0333c7eb50533cc6e0f7b61812d2840844296Narayan Kamath        }
12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1301cd0e210651da3d0f35f3ae164379c7ab71eb58ccPhil Burk
130210a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk    /**
1303cd0e210651da3d0f35f3ae164379c7ab71eb58ccPhil Burk     * Returns the effective size of the <code>AudioTrack</code> buffer
130410a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk     * that the application writes to.
1305cd0e210651da3d0f35f3ae164379c7ab71eb58ccPhil Burk     * <p> This will be less than or equal to the result of
1306cd0e210651da3d0f35f3ae164379c7ab71eb58ccPhil Burk     * {@link #getBufferCapacityInFrames()}.
1307cd0e210651da3d0f35f3ae164379c7ab71eb58ccPhil Burk     * It will be equal if {@link #setBufferSizeInFrames(int)} has never been called.
1308cd0e210651da3d0f35f3ae164379c7ab71eb58ccPhil Burk     * <p> If the track is subsequently routed to a different output sink, the buffer
1309cd0e210651da3d0f35f3ae164379c7ab71eb58ccPhil Burk     * size and capacity may enlarge to accommodate.
1310cd0e210651da3d0f35f3ae164379c7ab71eb58ccPhil Burk     * <p> If the <code>AudioTrack</code> encoding indicates compressed data,
1311cd0e210651da3d0f35f3ae164379c7ab71eb58ccPhil Burk     * e.g. {@link AudioFormat#ENCODING_AC3}, then the frame count returned is
13121d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     * the size of the <code>AudioTrack</code> buffer in bytes.
1313cd0e210651da3d0f35f3ae164379c7ab71eb58ccPhil Burk     * <p> See also {@link AudioManager#getProperty(String)} for key
1314cd0e210651da3d0f35f3ae164379c7ab71eb58ccPhil Burk     * {@link AudioManager#PROPERTY_OUTPUT_FRAMES_PER_BUFFER}.
1315cd0e210651da3d0f35f3ae164379c7ab71eb58ccPhil Burk     * @return current size in frames of the <code>AudioTrack</code> buffer.
1316eeecfa44010321952a2f156bb883ca8a1331a451Phil Burk     * @throws IllegalStateException if track is not initialized.
131710a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk     */
131810a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk    public int getBufferSizeInFrames() {
131910a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk        return native_get_buffer_size_frames();
132010a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk    }
132110a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk
132210a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk    /**
132310a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk     * Limits the effective size of the <code>AudioTrack</code> buffer
132410a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk     * that the application writes to.
132510a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk     * <p> A write to this AudioTrack will not fill the buffer beyond this limit.
13261d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     * If a blocking write is used then the write will block until the data
132710a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk     * can fit within this limit.
132810a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk     * <p>Changing this limit modifies the latency associated with
132910a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk     * the buffer for this track. A smaller size will give lower latency
133010a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk     * but there may be more glitches due to buffer underruns.
1331cd0e210651da3d0f35f3ae164379c7ab71eb58ccPhil Burk     * <p>The actual size used may not be equal to this requested size.
133210a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk     * It will be limited to a valid range with a maximum of
1333cd0e210651da3d0f35f3ae164379c7ab71eb58ccPhil Burk     * {@link #getBufferCapacityInFrames()}.
133410a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk     * It may also be adjusted slightly for internal reasons.
133510a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk     * If bufferSizeInFrames is less than zero then {@link #ERROR_BAD_VALUE}
133610a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk     * will be returned.
133710a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk     * <p>This method is only supported for PCM audio.
133810a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk     * It is not supported for compressed audio tracks.
133910a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk     *
13401d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     * @param bufferSizeInFrames requested buffer size in frames
1341cd0e210651da3d0f35f3ae164379c7ab71eb58ccPhil Burk     * @return the actual buffer size in frames or an error code,
1342cd0e210651da3d0f35f3ae164379c7ab71eb58ccPhil Burk     *    {@link #ERROR_BAD_VALUE}, {@link #ERROR_INVALID_OPERATION}
1343eeecfa44010321952a2f156bb883ca8a1331a451Phil Burk     * @throws IllegalStateException if track is not initialized.
134410a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk     */
134510a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk    public int setBufferSizeInFrames(int bufferSizeInFrames) {
134610a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk        if (mDataLoadMode == MODE_STATIC || mState == STATE_UNINITIALIZED) {
134710a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk            return ERROR_INVALID_OPERATION;
134810a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk        }
134910a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk        if (bufferSizeInFrames < 0) {
135010a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk            return ERROR_BAD_VALUE;
135110a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk        }
135210a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk        return native_set_buffer_size_frames(bufferSizeInFrames);
135310a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk    }
135410a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk
13559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
13561d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *  Returns the maximum size of the <code>AudioTrack</code> buffer in frames.
13574bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung     *  <p> If the track's creation mode is {@link #MODE_STATIC},
13584bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung     *  it is equal to the specified bufferSizeInBytes on construction, converted to frame units.
13591d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *  A static track's frame count will not change.
13604bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung     *  <p> If the track's creation mode is {@link #MODE_STREAM},
13614bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung     *  it is greater than or equal to the specified bufferSizeInBytes converted to frame units.
13624bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung     *  For streaming tracks, this value may be rounded up to a larger value if needed by
13634bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung     *  the target output sink, and
13641d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *  if the track is subsequently routed to a different output sink, the
13654bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung     *  frame count may enlarge to accommodate.
1366e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung     *  <p> If the <code>AudioTrack</code> encoding indicates compressed data,
1367e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung     *  e.g. {@link AudioFormat#ENCODING_AC3}, then the frame count returned is
13681d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     *  the size of the <code>AudioTrack</code> buffer in bytes.
1369e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung     *  <p> See also {@link AudioManager#getProperty(String)} for key
137055a3218f242a611afb3569d88970c0c5dbf8ce54Glenn Kasten     *  {@link AudioManager#PROPERTY_OUTPUT_FRAMES_PER_BUFFER}.
137110a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk     *  @return maximum size in frames of the <code>AudioTrack</code> buffer.
1372eeecfa44010321952a2f156bb883ca8a1331a451Phil Burk     *  @throws IllegalStateException if track is not initialized.
13739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
137410a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk    public int getBufferCapacityInFrames() {
137510a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk        return native_get_buffer_capacity_frames();
1376e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung    }
1377e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung
1378e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung    /**
1379e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung     *  Returns the frame count of the native <code>AudioTrack</code> buffer.
1380e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung     *  @return current size in frames of the <code>AudioTrack</code> buffer.
1381e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung     *  @throws IllegalStateException
1382e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung     *  @deprecated Use the identical public method {@link #getBufferSizeInFrames()} instead.
1383e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung     */
1384e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung    @Deprecated
1385e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung    protected int getNativeFrameCount() {
138610a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk        return native_get_buffer_capacity_frames();
13879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1390ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * Returns marker position expressed in frames.
1391e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * @return marker position in wrapping frame units similar to {@link #getPlaybackHeadPosition},
1392e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * or zero if marker is disabled.
13939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
13949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getNotificationMarkerPosition() {
13959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return native_get_marker_pos();
13969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1399ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * Returns the notification update period expressed in frames.
1400e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * Zero means that no position update notifications are being delivered.
14019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
14029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getPositionNotificationPeriod() {
14039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return native_get_pos_update_period();
14049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1407e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * Returns the playback head position expressed in frames.
1408e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * Though the "int" type is signed 32-bits, the value should be reinterpreted as if it is
1409e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * unsigned 32-bits.  That is, the next position after 0x7FFFFFFF is (int) 0x80000000.
1410e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * This is a continuously advancing counter.  It will wrap (overflow) periodically,
1411e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * for example approximately once every 27:03:11 hours:minutes:seconds at 44.1 kHz.
1412ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     * It is reset to zero by {@link #flush()}, {@link #reloadStaticData()}, and {@link #stop()}.
1413ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     * If the track's creation mode is {@link #MODE_STATIC}, the return value indicates
1414ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     * the total number of frames played since reset,
1415ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     * <i>not</i> the current offset within the buffer.
14169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
14179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getPlaybackHeadPosition() {
14189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return native_get_position();
14199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
142261dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman     * Returns this track's estimated latency in milliseconds. This includes the latency due
142361dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman     * to AudioTrack buffer size, AudioMixer (if any) and audio hardware driver.
142461dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman     *
142561dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman     * DO NOT UNHIDE. The existing approach for doing A/V sync has too many problems. We need
142661dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman     * a better solution.
142761dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman     * @hide
142861dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman     */
142961dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman    public int getLatency() {
143061dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman        return native_get_latency();
143161dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman    }
143261dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman
143361dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman    /**
143403f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk     * Returns the number of underrun occurrences in the application-level write buffer
143503f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk     * since the AudioTrack was created.
143603f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk     * An underrun occurs if the application does not write audio
143703f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk     * data quickly enough, causing the buffer to underflow
143803f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk     * and a potential audio glitch or pop.
14392bf39d8e9f9bdcbe548f8bd8acb89def382b467dPhil Burk     * <p>
144003f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk     * Underruns are less likely when buffer sizes are large.
14412bf39d8e9f9bdcbe548f8bd8acb89def382b467dPhil Burk     * It may be possible to eliminate underruns by recreating the AudioTrack with
14422bf39d8e9f9bdcbe548f8bd8acb89def382b467dPhil Burk     * a larger buffer.
14432bf39d8e9f9bdcbe548f8bd8acb89def382b467dPhil Burk     * Or by using {@link #setBufferSizeInFrames(int)} to dynamically increase the
14442bf39d8e9f9bdcbe548f8bd8acb89def382b467dPhil Burk     * effective size of the buffer.
144503f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk     */
144603f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk    public int getUnderrunCount() {
144703f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk        return native_get_underrun_count();
144803f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk    }
144903f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk
145003f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk    /**
1451ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * Returns the current performance mode of the {@link AudioTrack}.
1452ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     *
1453ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * @return one of {@link AudioTrack#PERFORMANCE_MODE_NONE},
1454ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * {@link AudioTrack#PERFORMANCE_MODE_LOW_LATENCY},
1455ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * or {@link AudioTrack#PERFORMANCE_MODE_POWER_SAVING}.
1456ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * Use {@link AudioTrack.Builder#setPerformanceMode}
1457ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * in the {@link AudioTrack.Builder} to enable a performance mode.
1458ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     * @throws IllegalStateException if track is not initialized.
1459ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung     */
1460ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung    public @PerformanceMode int getPerformanceMode() {
1461ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung        final int flags = native_get_flags();
1462ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung        if ((flags & AUDIO_OUTPUT_FLAG_FAST) != 0) {
1463ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung            return PERFORMANCE_MODE_LOW_LATENCY;
1464ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung        } else if ((flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) != 0) {
1465ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung            return PERFORMANCE_MODE_POWER_SAVING;
1466ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung        } else {
1467ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung            return PERFORMANCE_MODE_NONE;
1468ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung        }
1469ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung    }
1470ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung
1471ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung    /**
1472e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     *  Returns the output sample rate in Hz for the specified stream type.
14739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
14749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static public int getNativeOutputSampleRate(int streamType) {
14759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return native_get_output_sample_rate(streamType);
14769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1477fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten
14789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
14791d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     * Returns the estimated minimum buffer size required for an AudioTrack
14801d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     * object to be created in the {@link #MODE_STREAM} mode.
14811d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     * The size is an estimate because it does not consider either the route or the sink,
14821d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten     * since neither is known yet.  Note that this size doesn't
1483ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * guarantee a smooth playback under load, and higher values should be chosen according to
1484fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten     * the expected frequency at which the buffer will be refilled with additional data to play.
14858d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten     * For example, if you intend to dynamically set the source sample rate of an AudioTrack
14868d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten     * to a higher value than the initial source sample rate, be sure to configure the buffer size
14878d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten     * based on the highest planned sample rate.
14888d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten     * @param sampleRateInHz the source sample rate expressed in Hz.
14891cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten     *   {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED} is not permitted.
1490fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten     * @param channelConfig describes the configuration of the audio channels.
1491a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent     *   See {@link AudioFormat#CHANNEL_OUT_MONO} and
1492a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent     *   {@link AudioFormat#CHANNEL_OUT_STEREO}
1493fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten     * @param audioFormat the format in which the audio data is represented.
1494fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten     *   See {@link AudioFormat#ENCODING_PCM_16BIT} and
14957d60bcd2d950e3571c00ce9f1c492c6bd58334c9Glenn Kasten     *   {@link AudioFormat#ENCODING_PCM_8BIT},
14967d60bcd2d950e3571c00ce9f1c492c6bd58334c9Glenn Kasten     *   and {@link AudioFormat#ENCODING_PCM_FLOAT}.
14979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return {@link #ERROR_BAD_VALUE} if an invalid parameter was passed,
1498e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     *   or {@link #ERROR} if unable to query for output properties,
1499ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     *   or the minimum buffer size expressed in bytes.
15009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
15019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static public int getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat) {
15029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int channelCount = 0;
15039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch(channelConfig) {
1504a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent        case AudioFormat.CHANNEL_OUT_MONO:
15053026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent        case AudioFormat.CHANNEL_CONFIGURATION_MONO:
15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            channelCount = 1;
15079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
1508a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent        case AudioFormat.CHANNEL_OUT_STEREO:
15093026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent        case AudioFormat.CHANNEL_CONFIGURATION_STEREO:
15109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            channelCount = 2;
15119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
15129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        default:
1513a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung            if (!isMultichannelConfigSupported(channelConfig)) {
15141b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi                loge("getMinBufferSize(): Invalid channel configuration.");
1515df3cb5279857cac41909643c6703e8fc1621fad1Glenn Kasten                return ERROR_BAD_VALUE;
15161b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi            } else {
15178528ed43b41ff02535675c5da7425bef5195e73bAndy Hung                channelCount = AudioFormat.channelCountFromOutChannelMask(channelConfig);
15181b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi            }
15199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1520fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten
1521cae346633321e237f824f3ca10d7e6fff2307b2fEric Laurent        if (!AudioFormat.isPublicEncoding(audioFormat)) {
15229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            loge("getMinBufferSize(): Invalid audio format.");
1523df3cb5279857cac41909643c6703e8fc1621fad1Glenn Kasten            return ERROR_BAD_VALUE;
15249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1525fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten
15265c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten        // sample rate, note these values are subject to change
15271cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten        // Note: AudioFormat.SAMPLE_RATE_UNSPECIFIED is not allowed
15281cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten        if ( (sampleRateInHz < AudioFormat.SAMPLE_RATE_HZ_MIN) ||
15291cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten                (sampleRateInHz > AudioFormat.SAMPLE_RATE_HZ_MAX) ) {
1530ad67c9546494a7c4d9336b57889a7c19a7dbb945Glenn Kasten            loge("getMinBufferSize(): " + sampleRateInHz + " Hz is not a supported sample rate.");
1531df3cb5279857cac41909643c6703e8fc1621fad1Glenn Kasten            return ERROR_BAD_VALUE;
15329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1533fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten
15349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int size = native_get_min_buff_size(sampleRateInHz, channelCount, audioFormat);
1535a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten        if (size <= 0) {
15369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            loge("getMinBufferSize(): error querying hardware");
1537df3cb5279857cac41909643c6703e8fc1621fad1Glenn Kasten            return ERROR;
15389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        else {
15409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return size;
15419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1544619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent    /**
1545619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     * Returns the audio session ID.
1546619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     *
1547619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     * @return the ID of the audio session this AudioTrack belongs to.
1548619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     */
1549619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent    public int getAudioSessionId() {
1550619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent        return mSessionId;
1551619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent    }
15529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1553948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten   /**
1554948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    * Poll for a timestamp on demand.
1555486918b41584cd2589c46c5217b3fba1e7d18874Glenn Kasten    * <p>
1556486918b41584cd2589c46c5217b3fba1e7d18874Glenn Kasten    * If you need to track timestamps during initial warmup or after a routing or mode change,
155700908b6c6964346af4d2512ba161a109912d97b8Glenn Kasten    * you should request a new timestamp periodically until the reported timestamps
155800908b6c6964346af4d2512ba161a109912d97b8Glenn Kasten    * show that the frame position is advancing, or until it becomes clear that
155900908b6c6964346af4d2512ba161a109912d97b8Glenn Kasten    * timestamps are unavailable for this route.
156000908b6c6964346af4d2512ba161a109912d97b8Glenn Kasten    * <p>
156100908b6c6964346af4d2512ba161a109912d97b8Glenn Kasten    * After the clock is advancing at a stable rate,
156200908b6c6964346af4d2512ba161a109912d97b8Glenn Kasten    * query for a new timestamp approximately once every 10 seconds to once per minute.
1563486918b41584cd2589c46c5217b3fba1e7d18874Glenn Kasten    * Calling this method more often is inefficient.
1564486918b41584cd2589c46c5217b3fba1e7d18874Glenn Kasten    * It is also counter-productive to call this method more often than recommended,
1565486918b41584cd2589c46c5217b3fba1e7d18874Glenn Kasten    * because the short-term differences between successive timestamp reports are not meaningful.
1566486918b41584cd2589c46c5217b3fba1e7d18874Glenn Kasten    * If you need a high-resolution mapping between frame position and presentation time,
1567948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    * consider implementing that at application level, based on low-resolution timestamps.
1568486918b41584cd2589c46c5217b3fba1e7d18874Glenn Kasten    * <p>
1569948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    * The audio data at the returned position may either already have been
1570948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    * presented, or may have not yet been presented but is committed to be presented.
1571948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    * It is not possible to request the time corresponding to a particular position,
1572948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    * or to request the (fractional) position corresponding to a particular time.
1573948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    * If you need such features, consider implementing them at application level.
1574948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    *
1575948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    * @param timestamp a reference to a non-null AudioTimestamp instance allocated
1576596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten    *        and owned by caller.
1577596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten    * @return true if a timestamp is available, or false if no timestamp is available.
1578596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten    *         If a timestamp if available,
1579948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    *         the AudioTimestamp instance is filled in with a position in frame units, together
1580948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    *         with the estimated time when that frame was presented or is committed to
1581948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    *         be presented.
1582948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    *         In the case that no timestamp is available, any supplied instance is left unaltered.
1583c52f4e25e21719d5d637a588e3200be941b9fe4dGlenn Kasten    *         A timestamp may be temporarily unavailable while the audio clock is stabilizing,
1584c52f4e25e21719d5d637a588e3200be941b9fe4dGlenn Kasten    *         or during and immediately after a route change.
158500908b6c6964346af4d2512ba161a109912d97b8Glenn Kasten    *         A timestamp is permanently unavailable for a given route if the route does not support
158600908b6c6964346af4d2512ba161a109912d97b8Glenn Kasten    *         timestamps.  In this case, the approximate frame position can be obtained
158700908b6c6964346af4d2512ba161a109912d97b8Glenn Kasten    *         using {@link #getPlaybackHeadPosition}.
158800908b6c6964346af4d2512ba161a109912d97b8Glenn Kasten    *         However, it may be useful to continue to query for
158900908b6c6964346af4d2512ba161a109912d97b8Glenn Kasten    *         timestamps occasionally, to recover after a route change.
1590948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    */
1591486918b41584cd2589c46c5217b3fba1e7d18874Glenn Kasten    // Add this text when the "on new timestamp" API is added:
1592486918b41584cd2589c46c5217b3fba1e7d18874Glenn Kasten    //   Use if you need to get the most recent timestamp outside of the event callback handler.
1593596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten    public boolean getTimestamp(AudioTimestamp timestamp)
1594948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    {
1595596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten        if (timestamp == null) {
1596596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten            throw new IllegalArgumentException();
1597596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten        }
1598948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten        // It's unfortunate, but we have to either create garbage every time or use synchronized
1599948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten        long[] longArray = new long[2];
1600948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten        int ret = native_get_timestamp(longArray);
1601596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten        if (ret != SUCCESS) {
1602596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten            return false;
1603948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten        }
1604596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten        timestamp.framePosition = longArray[0];
1605596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten        timestamp.nanoTime = longArray[1];
1606596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten        return true;
1607948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    }
1608948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten
16094e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent    /**
16104e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent     * Poll for a timestamp on demand.
16114e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent     * <p>
16124e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent     * Same as {@link #getTimestamp(AudioTimestamp)} but with a more useful return code.
16134e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent     *
16144e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent     * @param timestamp a reference to a non-null AudioTimestamp instance allocated
16154e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent     *        and owned by caller.
16164e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent     * @return {@link #SUCCESS} if a timestamp is available
16174e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent     *         {@link #ERROR_WOULD_BLOCK} if called in STOPPED or FLUSHED state, or if called
16184e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent     *         immediately after start/ACTIVE, when the number of frames consumed is less than the
16194e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent     *         overall hardware latency to physical output. In WOULD_BLOCK cases, one might poll
16204e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent     *         again, or use {@link #getPlaybackHeadPosition}, or use 0 position and current time
16214e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent     *         for the timestamp.
16224e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent     *         {@link #ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
16234e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent     *         needs to be recreated.
16244e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent     *         {@link #ERROR_INVALID_OPERATION} if current route does not support
16254e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent     *         timestamps. In this case, the approximate frame position can be obtained
16264e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent     *         using {@link #getPlaybackHeadPosition}.
16274e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent     *
16284e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent     *         The AudioTimestamp instance is filled in with a position in frame units, together
16294e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent     *         with the estimated time when that frame was presented or is committed to
16304e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent     *         be presented.
16314e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent     * @hide
16324e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent     */
16334e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent     // Add this text when the "on new timestamp" API is added:
16344e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent     //   Use if you need to get the most recent timestamp outside of the event callback handler.
16354e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent     public int getTimestampWithStatus(AudioTimestamp timestamp)
16364e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent     {
16374e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent         if (timestamp == null) {
16384e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent             throw new IllegalArgumentException();
16394e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent         }
16404e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent         // It's unfortunate, but we have to either create garbage every time or use synchronized
16414e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent         long[] longArray = new long[2];
16424e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent         int ret = native_get_timestamp(longArray);
16434e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent         timestamp.framePosition = longArray[0];
16444e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent         timestamp.nanoTime = longArray[1];
16454e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent         return ret;
16464e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent     }
1647948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten
16489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //--------------------------------------------------------------------------
16499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Initialization / configuration
16509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //--------------------
16519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
16524df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     * Sets the listener the AudioTrack notifies when a previously set marker is reached or
16534df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     * for each periodic playback head position update.
1654ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * Notifications will be received in the same thread as the one in which the AudioTrack
1655ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * instance was created.
16569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param listener
16579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
16584df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    public void setPlaybackPositionUpdateListener(OnPlaybackPositionUpdateListener listener) {
16594df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        setPlaybackPositionUpdateListener(listener, null);
16609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1661fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten
1662ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi    /**
1663ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * Sets the listener the AudioTrack notifies when a previously set marker is reached or
1664ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * for each periodic playback head position update.
1665ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * Use this method to receive AudioTrack events in the Handler associated with another
1666ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * thread than the one in which you created the AudioTrack instance.
1667ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * @param listener
1668ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * @param handler the Handler that will receive the event notification messages.
1669ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     */
1670fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten    public void setPlaybackPositionUpdateListener(OnPlaybackPositionUpdateListener listener,
16714df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                                                    Handler handler) {
16724df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        if (listener != null) {
1673d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean            mEventHandlerDelegate = new NativePositionEventHandlerDelegate(this, listener, handler);
167495bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten        } else {
167595bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten            mEventHandlerDelegate = null;
16769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
168078cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten    private static float clampGainOrLevel(float gainOrLevel) {
168178cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten        if (Float.isNaN(gainOrLevel)) {
168278cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten            throw new IllegalArgumentException();
168378cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten        }
168478cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten        if (gainOrLevel < GAIN_MIN) {
168578cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten            gainOrLevel = GAIN_MIN;
168678cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten        } else if (gainOrLevel > GAIN_MAX) {
168778cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten            gainOrLevel = GAIN_MAX;
168878cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten        }
168978cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten        return gainOrLevel;
169078cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten    }
169178cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten
16924df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project
16939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     /**
169478cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * Sets the specified left and right output gain values on the AudioTrack.
169578cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * <p>Gain values are clamped to the closed interval [0.0, max] where
169678cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * max is the value of {@link #getMaxVolume}.
169778cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * A value of 0.0 results in zero gain (silence), and
169878cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * a value of 1.0 means unity gain (signal unchanged).
169978cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * The default value is 1.0 meaning unity gain.
170078cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * <p>The word "volume" in the API name is historical; this is actually a linear gain.
170178cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * @param leftGain output gain for the left channel.
170278cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * @param rightGain output gain for the right channel
17039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return error code or success, see {@link #SUCCESS},
17049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *    {@link #ERROR_INVALID_OPERATION}
170578cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * @deprecated Applications should use {@link #setVolume} instead, as it
170678cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * more gracefully scales down to mono, and up to multi-channel content beyond stereo.
17079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1708ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey    @Deprecated
170978cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten    public int setStereoVolume(float leftGain, float rightGain) {
17103b4df62704a6184878afd9272830cf3db7bd2d66Glenn Kasten        if (mState == STATE_UNINITIALIZED) {
17119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ERROR_INVALID_OPERATION;
17129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17143c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi        baseSetVolume(leftGain, rightGain);
17153c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi        return SUCCESS;
17163c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi    }
17179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17183c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi    @Override
17198e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi    void playerSetVolume(boolean muting, float leftVolume, float rightVolume) {
17208e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi        leftVolume = clampGainOrLevel(muting ? 0.0f : leftVolume);
17218e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi        rightVolume = clampGainOrLevel(muting ? 0.0f : rightVolume);
17229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17233c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi        native_setVolume(leftVolume, rightVolume);
17249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
172878cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * Sets the specified output gain value on all channels of this track.
172978cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * <p>Gain values are clamped to the closed interval [0.0, max] where
173078cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * max is the value of {@link #getMaxVolume}.
173178cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * A value of 0.0 results in zero gain (silence), and
173278cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * a value of 1.0 means unity gain (signal unchanged).
173378cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * The default value is 1.0 meaning unity gain.
173478cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * <p>This API is preferred over {@link #setStereoVolume}, as it
173578cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * more gracefully scales down to mono, and up to multi-channel content beyond stereo.
173678cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * <p>The word "volume" in the API name is historical; this is actually a linear gain.
173778cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * @param gain output gain for all channels.
17383e21cc8140e42bdcd924590e5e12446b6c55ad2aGlenn Kasten     * @return error code or success, see {@link #SUCCESS},
17393e21cc8140e42bdcd924590e5e12446b6c55ad2aGlenn Kasten     *    {@link #ERROR_INVALID_OPERATION}
1740068225de0197df07a0247b2877666ea91c22c992Glenn Kasten     */
174178cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten    public int setVolume(float gain) {
174278cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten        return setStereoVolume(gain, gain);
1743068225de0197df07a0247b2877666ea91c22c992Glenn Kasten    }
1744068225de0197df07a0247b2877666ea91c22c992Glenn Kasten
1745035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung    @Override
1746035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung    /* package */ int playerApplyVolumeShaper(
1747035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            @NonNull VolumeShaper.Configuration configuration,
1748035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            @NonNull VolumeShaper.Operation operation) {
1749035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        return native_applyVolumeShaper(configuration, operation);
1750035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung    }
1751035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung
1752035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung    @Override
1753035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung    /* package */ @Nullable VolumeShaper.State playerGetVolumeShaperState(int id) {
1754035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung        return native_getVolumeShaperState(id);
1755035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung    }
1756068225de0197df07a0247b2877666ea91c22c992Glenn Kasten
1757fef734cec10420c4a008bb41c184c143333d7570Andy Hung    @Override
1758fef734cec10420c4a008bb41c184c143333d7570Andy Hung    public @NonNull VolumeShaper createVolumeShaper(
1759fef734cec10420c4a008bb41c184c143333d7570Andy Hung            @NonNull VolumeShaper.Configuration configuration) {
1760fef734cec10420c4a008bb41c184c143333d7570Andy Hung        return new VolumeShaper(configuration, this);
1761fef734cec10420c4a008bb41c184c143333d7570Andy Hung    }
1762fef734cec10420c4a008bb41c184c143333d7570Andy Hung
1763068225de0197df07a0247b2877666ea91c22c992Glenn Kasten    /**
17649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the playback sample rate for this track. This sets the sampling rate at which
17658d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten     * the audio data will be consumed and played back
17668d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten     * (as set by the sampleRateInHz parameter in the
17678d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten     * {@link #AudioTrack(int, int, int, int, int, int)} constructor),
17688d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten     * not the original sampling rate of the
1769e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * content. For example, setting it to half the sample rate of the content will cause the
1770e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * playback to last twice as long, but will also result in a pitch shift down by one octave.
1771e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * The valid sample rate range is from 1 Hz to twice the value returned by
177288e209dcf8c2ebddda5c272f46d1bd5478bc639cEric Laurent     * {@link #getNativeOutputSampleRate(int)}.
17732d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia     * Use {@link #setPlaybackParams(PlaybackParams)} for speed control.
1774e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung     * <p> This method may also be used to repurpose an existing <code>AudioTrack</code>
1775e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung     * for playback of content of differing sample rate,
1776e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung     * but with identical encoding and channel mask.
1777ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * @param sampleRateInHz the sample rate expressed in Hz
17789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE},
17799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *    {@link #ERROR_INVALID_OPERATION}
17809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
17819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int setPlaybackRate(int sampleRateInHz) {
1782f19395db6343efdf80d064e0ba7c3b9aa4dbae75Glenn Kasten        if (mState != STATE_INITIALIZED) {
17839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ERROR_INVALID_OPERATION;
17849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (sampleRateInHz <= 0) {
17869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ERROR_BAD_VALUE;
17879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
178888e209dcf8c2ebddda5c272f46d1bd5478bc639cEric Laurent        return native_set_playback_rate(sampleRateInHz);
17899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
17935f68c7a3f8400bcef233bf02d9a722f6d21f5c34Glenn Kasten     * Sets the playback parameters.
17945f68c7a3f8400bcef233bf02d9a722f6d21f5c34Glenn Kasten     * This method returns failure if it cannot apply the playback parameters.
1795263b4c97823295c41900210515d0c769a236190cAndy Hung     * One possible cause is that the parameters for speed or pitch are out of range.
1796263b4c97823295c41900210515d0c769a236190cAndy Hung     * Another possible cause is that the <code>AudioTrack</code> is streaming
1797263b4c97823295c41900210515d0c769a236190cAndy Hung     * (see {@link #MODE_STREAM}) and the
1798263b4c97823295c41900210515d0c769a236190cAndy Hung     * buffer size is too small. For speeds greater than 1.0f, the <code>AudioTrack</code> buffer
1799263b4c97823295c41900210515d0c769a236190cAndy Hung     * on configuration must be larger than the speed multiplied by the minimum size
1800263b4c97823295c41900210515d0c769a236190cAndy Hung     * {@link #getMinBufferSize(int, int, int)}) to allow proper playback.
18012d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia     * @param params see {@link PlaybackParams}. In particular,
1802263b4c97823295c41900210515d0c769a236190cAndy Hung     * speed, pitch, and audio mode should be set.
18035f68c7a3f8400bcef233bf02d9a722f6d21f5c34Glenn Kasten     * @throws IllegalArgumentException if the parameters are invalid or not accepted.
1804263b4c97823295c41900210515d0c769a236190cAndy Hung     * @throws IllegalStateException if track is not initialized.
1805263b4c97823295c41900210515d0c769a236190cAndy Hung     */
18062d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia    public void setPlaybackParams(@NonNull PlaybackParams params) {
18072d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia        if (params == null) {
18082d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia            throw new IllegalArgumentException("params is null");
1809263b4c97823295c41900210515d0c769a236190cAndy Hung        }
18102d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia        native_set_playback_params(params);
1811263b4c97823295c41900210515d0c769a236190cAndy Hung    }
1812263b4c97823295c41900210515d0c769a236190cAndy Hung
1813263b4c97823295c41900210515d0c769a236190cAndy Hung
1814263b4c97823295c41900210515d0c769a236190cAndy Hung    /**
1815e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * Sets the position of the notification marker.  At most one marker can be active.
1816e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * @param markerInFrames marker position in wrapping frame units similar to
1817e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * {@link #getPlaybackHeadPosition}, or zero to disable the marker.
1818e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * To set a marker at a position which would appear as zero due to wraparound,
1819e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * a workaround is to use a non-zero position near zero, such as -1 or 1.
18209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE},
18219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *  {@link #ERROR_INVALID_OPERATION}
18229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
18239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int setNotificationMarkerPosition(int markerInFrames) {
18243b4df62704a6184878afd9272830cf3db7bd2d66Glenn Kasten        if (mState == STATE_UNINITIALIZED) {
18259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ERROR_INVALID_OPERATION;
18269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return native_set_marker_pos(markerInFrames);
18289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1832ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * Sets the period for the periodic notification event.
1833ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     * @param periodInFrames update period expressed in frames.
1834ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     * Zero period means no position updates.  A negative period is not allowed.
18359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_INVALID_OPERATION}
18369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
18379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int setPositionNotificationPeriod(int periodInFrames) {
18383b4df62704a6184878afd9272830cf3db7bd2d66Glenn Kasten        if (mState == STATE_UNINITIALIZED) {
18399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ERROR_INVALID_OPERATION;
18409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return native_set_pos_update_period(periodInFrames);
18429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1846ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     * Sets the playback head position within the static buffer.
1847a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten     * The track must be stopped or paused for the position to be changed,
1848a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten     * and must use the {@link #MODE_STATIC} mode.
1849ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     * @param positionInFrames playback head position within buffer, expressed in frames.
1850e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * Zero corresponds to start of buffer.
1851e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * The position must not be greater than the buffer size in frames, or negative.
1852ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     * Though this method and {@link #getPlaybackHeadPosition()} have similar names,
1853ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     * the position values have different meanings.
1854ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     * <br>
1855ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     * If looping is currently enabled and the new position is greater than or equal to the
185635e576e79292122fad462ebccd8520822552a6d7Andy Hung     * loop end marker, the behavior varies by API level:
18570e3de6cacaffcfeda4d6353be61e2f1f9ed80705Dianne Hackborn     * as of {@link android.os.Build.VERSION_CODES#M},
1858ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     * the looping is first disabled and then the position is set.
1859ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     * For earlier API levels, the behavior is unspecified.
18609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE},
18619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *    {@link #ERROR_INVALID_OPERATION}
18629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
18639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int setPlaybackHeadPosition(int positionInFrames) {
186478bfa6322bf34e49d5e4426296c701a64f705e49Andy Hung        if (mDataLoadMode == MODE_STREAM || mState == STATE_UNINITIALIZED ||
1865a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten                getPlayState() == PLAYSTATE_PLAYING) {
1866a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten            return ERROR_INVALID_OPERATION;
18679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1868e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten        if (!(0 <= positionInFrames && positionInFrames <= mNativeBufferSizeInFrames)) {
1869e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten            return ERROR_BAD_VALUE;
1870e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten        }
1871a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten        return native_set_position(positionInFrames);
18729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
18759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the loop points and the loop count. The loop can be infinite.
1876a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten     * Similarly to setPlaybackHeadPosition,
1877e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * the track must be stopped or paused for the loop points to be changed,
1878a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten     * and must use the {@link #MODE_STATIC} mode.
1879ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     * @param startInFrames loop start marker expressed in frames.
1880e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * Zero corresponds to start of buffer.
1881e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * The start marker must not be greater than or equal to the buffer size in frames, or negative.
1882ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     * @param endInFrames loop end marker expressed in frames.
1883e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * The total buffer size in frames corresponds to end of buffer.
1884e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * The end marker must not be greater than the buffer size in frames.
1885e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * For looping, the end marker must not be less than or equal to the start marker,
1886e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * but to disable looping
1887e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * it is permitted for start marker, end marker, and loop count to all be 0.
1888ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     * If any input parameters are out of range, this method returns {@link #ERROR_BAD_VALUE}.
1889ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     * If the loop period (endInFrames - startInFrames) is too small for the implementation to
1890ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     * support,
1891ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     * {@link #ERROR_BAD_VALUE} is returned.
1892ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     * The loop range is the interval [startInFrames, endInFrames).
1893ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     * <br>
18940e3de6cacaffcfeda4d6353be61e2f1f9ed80705Dianne Hackborn     * As of {@link android.os.Build.VERSION_CODES#M}, the position is left unchanged,
1895ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     * unless it is greater than or equal to the loop end marker, in which case
1896ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     * it is forced to the loop start marker.
1897ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     * For earlier API levels, the effect on position is unspecified.
1898ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     * @param loopCount the number of times the loop is looped; must be greater than or equal to -1.
1899e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     *    A value of -1 means infinite looping, and 0 disables looping.
1900ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     *    A value of positive N means to "loop" (go back) N times.  For example,
1901ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     *    a value of one means to play the region two times in total.
19029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE},
19039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *    {@link #ERROR_INVALID_OPERATION}
19049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
19059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int setLoopPoints(int startInFrames, int endInFrames, int loopCount) {
190678bfa6322bf34e49d5e4426296c701a64f705e49Andy Hung        if (mDataLoadMode == MODE_STREAM || mState == STATE_UNINITIALIZED ||
1907a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten                getPlayState() == PLAYSTATE_PLAYING) {
19089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ERROR_INVALID_OPERATION;
19099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1910e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten        if (loopCount == 0) {
1911e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten            ;   // explicitly allowed as an exception to the loop region range check
1912e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten        } else if (!(0 <= startInFrames && startInFrames < mNativeBufferSizeInFrames &&
1913e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten                startInFrames < endInFrames && endInFrames <= mNativeBufferSizeInFrames)) {
1914e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten            return ERROR_BAD_VALUE;
1915e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten        }
19169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return native_set_loop(startInFrames, endInFrames, loopCount);
19179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
192055a3218f242a611afb3569d88970c0c5dbf8ce54Glenn Kasten     * Sets the initialization state of the instance. This method was originally intended to be used
192155a3218f242a611afb3569d88970c0c5dbf8ce54Glenn Kasten     * in an AudioTrack subclass constructor to set a subclass-specific post-initialization state.
192255a3218f242a611afb3569d88970c0c5dbf8ce54Glenn Kasten     * However, subclasses of AudioTrack are no longer recommended, so this method is obsolete.
19239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param state the state of the AudioTrack instance
192455a3218f242a611afb3569d88970c0c5dbf8ce54Glenn Kasten     * @deprecated Only accessible by subclasses, which are not recommended for AudioTrack.
19259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
192655a3218f242a611afb3569d88970c0c5dbf8ce54Glenn Kasten    @Deprecated
19279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void setState(int state) {
19289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mState = state;
19299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //---------------------------------------------------------
19339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Transport control methods
19349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //--------------------
19359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
19369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Starts playing an AudioTrack.
1937659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * <p>
1938ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     * If track's creation mode is {@link #MODE_STATIC}, you must have called one of
1939659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * the write methods ({@link #write(byte[], int, int)}, {@link #write(byte[], int, int, int)},
1940659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * {@link #write(short[], int, int)}, {@link #write(short[], int, int, int)},
1941659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * {@link #write(float[], int, int, int)}, or {@link #write(ByteBuffer, int, int)}) prior to
1942659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * play().
1943659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * <p>
1944659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * If the mode is {@link #MODE_STREAM}, you can optionally prime the data path prior to
1945659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * calling play(), by writing up to <code>bufferSizeInBytes</code> (from constructor).
1946e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung     * If you don't call write() first, or if you call write() but with an insufficient amount of
1947659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * data, then the track will be in underrun state at play().  In this case,
1948659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * playback will not actually start playing until the data path is filled to a
1949659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * device-specific minimum level.  This requirement for the path to be filled
1950659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * to a minimum level is also true when resuming audio playback after calling stop().
1951659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * Similarly the buffer will need to be filled up again after
1952659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * the track underruns due to failure to call write() in a timely manner with sufficient data.
1953659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * For portability, an application should prime the data path to the maximum allowed
1954659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * by writing data until the write() method returns a short transfer count.
1955659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * This allows play() to start immediately, and reduces the chance of underrun.
195688bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath     *
1957659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * @throws IllegalStateException if the track isn't properly initialized
19589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
19599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void play()
19609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    throws IllegalStateException {
19619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mState != STATE_INITIALIZED) {
1962f4e58051e22ad4e21c7cd436c37cc5665c194d1cGlenn Kasten            throw new IllegalStateException("play() called on uninitialized AudioTrack.");
19639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
196499489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi        //FIXME use lambda to pass startImpl to superclass
196599489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi        final int delay = getStartDelayMs();
196699489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi        if (delay == 0) {
196799489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi            startImpl();
196899489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi        } else {
196999489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi            new Thread() {
197099489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                public void run() {
197199489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                    try {
197299489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                        Thread.sleep(delay);
197399489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                    } catch (InterruptedException e) {
197499489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                        e.printStackTrace();
197599489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                    }
197699489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                    baseSetStartDelayMs(0);
197710ffc783044afe038101c732edf336d5dcb9b51fJean-Michel Trivi                    try {
197810ffc783044afe038101c732edf336d5dcb9b51fJean-Michel Trivi                        startImpl();
197910ffc783044afe038101c732edf336d5dcb9b51fJean-Michel Trivi                    } catch (IllegalStateException e) {
198010ffc783044afe038101c732edf336d5dcb9b51fJean-Michel Trivi                        // fail silently for a state exception when it is happening after
198110ffc783044afe038101c732edf336d5dcb9b51fJean-Michel Trivi                        // a delayed start, as the player state could have changed between the
198210ffc783044afe038101c732edf336d5dcb9b51fJean-Michel Trivi                        // call to start() and the execution of startImpl()
198310ffc783044afe038101c732edf336d5dcb9b51fJean-Michel Trivi                    }
198499489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                }
198599489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi            }.start();
198699489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi        }
198799489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi    }
198899489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi
198999489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi    private void startImpl() {
19909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized(mPlayStateLock) {
1991292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi            baseStart();
19929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            native_start();
19939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPlayState = PLAYSTATE_PLAYING;
19949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
19989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Stops playing the audio data.
1999a701da8ebabb3d63ac57b7718055698abb21804aJean-Michel Trivi     * When used on an instance created in {@link #MODE_STREAM} mode, audio will stop playing
2000a701da8ebabb3d63ac57b7718055698abb21804aJean-Michel Trivi     * after the last buffer that was written has been played. For an immediate stop, use
2001a701da8ebabb3d63ac57b7718055698abb21804aJean-Michel Trivi     * {@link #pause()}, followed by {@link #flush()} to discard audio data that hasn't been played
2002a701da8ebabb3d63ac57b7718055698abb21804aJean-Michel Trivi     * back yet.
20039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalStateException
20049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
20059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void stop()
20069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    throws IllegalStateException {
20079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mState != STATE_INITIALIZED) {
2008f4e58051e22ad4e21c7cd436c37cc5665c194d1cGlenn Kasten            throw new IllegalStateException("stop() called on uninitialized AudioTrack.");
20099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // stop playing
20129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized(mPlayStateLock) {
20139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            native_stop();
2014292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi            baseStop();
20159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPlayState = PLAYSTATE_STOPPED;
2016cfe964a09ca05778e5dd84f2fd24119b89401696Rachad            mAvSyncHeader = null;
2017cfe964a09ca05778e5dd84f2fd24119b89401696Rachad            mAvSyncBytesRemaining = 0;
20189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
202288bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath     * Pauses the playback of the audio data. Data that has not been played
202388bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath     * back will not be discarded. Subsequent calls to {@link #play} will play
2024a701da8ebabb3d63ac57b7718055698abb21804aJean-Michel Trivi     * this data back. See {@link #flush()} to discard this data.
202588bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath     *
20269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalStateException
20279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
20289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void pause()
20299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    throws IllegalStateException {
20309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mState != STATE_INITIALIZED) {
2031f4e58051e22ad4e21c7cd436c37cc5665c194d1cGlenn Kasten            throw new IllegalStateException("pause() called on uninitialized AudioTrack.");
20329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // pause playback
20359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized(mPlayStateLock) {
20369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            native_pause();
2037292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi            basePause();
20389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPlayState = PLAYSTATE_PAUSED;
20399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //---------------------------------------------------------
20449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Audio data supply
20459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //--------------------
20469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
204888bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath     * Flushes the audio data currently queued for playback. Any data that has
20497a121563d5c94ca0b88539afd8a7e86cc9118b60Glenn Kasten     * been written but not yet presented will be discarded.  No-op if not stopped or paused,
2050e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * or if the track's creation mode is not {@link #MODE_STREAM}.
20517a121563d5c94ca0b88539afd8a7e86cc9118b60Glenn Kasten     * <BR> Note that although data written but not yet presented is discarded, there is no
20527a121563d5c94ca0b88539afd8a7e86cc9118b60Glenn Kasten     * guarantee that all of the buffer space formerly used by that data
20537a121563d5c94ca0b88539afd8a7e86cc9118b60Glenn Kasten     * is available for a subsequent write.
20547a121563d5c94ca0b88539afd8a7e86cc9118b60Glenn Kasten     * For example, a call to {@link #write(byte[], int, int)} with <code>sizeInBytes</code>
20557a121563d5c94ca0b88539afd8a7e86cc9118b60Glenn Kasten     * less than or equal to the total buffer size
20567a121563d5c94ca0b88539afd8a7e86cc9118b60Glenn Kasten     * may return a short actual transfer count.
20579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
20589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void flush() {
20599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mState == STATE_INITIALIZED) {
20609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // flush the data in native layer
20619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            native_flush();
2062cfe964a09ca05778e5dd84f2fd24119b89401696Rachad            mAvSyncHeader = null;
2063cfe964a09ca05778e5dd84f2fd24119b89401696Rachad            mAvSyncBytesRemaining = 0;
20649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2069e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * Writes the audio data to the audio sink for playback (streaming mode),
2070e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * or copies audio data for later playback (static buffer mode).
20714aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     * The format specified in the AudioTrack constructor should be
20724aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     * {@link AudioFormat#ENCODING_PCM_8BIT} to correspond to the data in the array.
2073518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten     * The format can be {@link AudioFormat#ENCODING_PCM_16BIT}, but this is deprecated.
2074659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * <p>
2075659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * In streaming mode, the write will normally block until all the data has been enqueued for
2076659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * playback, and will return a full transfer count.  However, if the track is stopped or paused
2077659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * on entry, or another thread interrupts the write by calling stop or pause, or an I/O error
2078659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * occurs during the write, then the write may return a short transfer count.
2079659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * <p>
2080e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * In static buffer mode, copies the data to the buffer starting at offset 0.
2081659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * Note that the actual playback of this data might occur after this function returns.
208288bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath     *
20839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param audioData the array that holds the data to play.
2084679f1e26d03ebb5574ed389187f2ebc619832d52Glenn Kasten     * @param offsetInBytes the offset expressed in bytes in audioData where the data to write
2085ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     *    starts.
2086518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten     *    Must not be negative, or cause the data access to go out of bounds of the array.
2087679f1e26d03ebb5574ed389187f2ebc619832d52Glenn Kasten     * @param sizeInBytes the number of bytes to write in audioData after the offset.
2088518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten     *    Must not be negative, or cause the data access to go out of bounds of the array.
2089219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * @return zero or the positive number of bytes that were written, or one of the following
2090219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     *    error codes. The number of bytes will be a multiple of the frame size in bytes
2091518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten     *    not to exceed sizeInBytes.
2092219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * <ul>
2093219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * <li>{@link #ERROR_INVALID_OPERATION} if the track isn't properly initialized</li>
2094219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
2095219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * <li>{@link #ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
2096219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     *    needs to be recreated. The dead object error code is not returned if some data was
2097219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     *    successfully transferred. In this case, the error is returned at the next write()</li>
2098219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * <li>{@link #ERROR} in case of other error</li>
2099219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * </ul>
2100659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * This is equivalent to {@link #write(byte[], int, int, int)} with <code>writeMode</code>
2101659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * set to  {@link #WRITE_BLOCKING}.
21029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
21034aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung    public int write(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes) {
21044aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung        return write(audioData, offsetInBytes, sizeInBytes, WRITE_BLOCKING);
21054aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung    }
21069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21074aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung    /**
21084aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     * Writes the audio data to the audio sink for playback (streaming mode),
21094aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     * or copies audio data for later playback (static buffer mode).
21104aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     * The format specified in the AudioTrack constructor should be
21114aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     * {@link AudioFormat#ENCODING_PCM_8BIT} to correspond to the data in the array.
2112518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten     * The format can be {@link AudioFormat#ENCODING_PCM_16BIT}, but this is deprecated.
2113659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * <p>
2114659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * In streaming mode, the blocking behavior depends on the write mode.  If the write mode is
2115659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * {@link #WRITE_BLOCKING}, the write will normally block until all the data has been enqueued
2116659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * for playback, and will return a full transfer count.  However, if the write mode is
2117659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * {@link #WRITE_NON_BLOCKING}, or the track is stopped or paused on entry, or another thread
2118659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * interrupts the write by calling stop or pause, or an I/O error
2119659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * occurs during the write, then the write may return a short transfer count.
2120659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * <p>
2121659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * In static buffer mode, copies the data to the buffer starting at offset 0,
2122659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * and the write mode is ignored.
2123659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * Note that the actual playback of this data might occur after this function returns.
21244aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     *
21254aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     * @param audioData the array that holds the data to play.
2126679f1e26d03ebb5574ed389187f2ebc619832d52Glenn Kasten     * @param offsetInBytes the offset expressed in bytes in audioData where the data to write
21274aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     *    starts.
2128518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten     *    Must not be negative, or cause the data access to go out of bounds of the array.
2129679f1e26d03ebb5574ed389187f2ebc619832d52Glenn Kasten     * @param sizeInBytes the number of bytes to write in audioData after the offset.
2130518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten     *    Must not be negative, or cause the data access to go out of bounds of the array.
21314aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     * @param writeMode one of {@link #WRITE_BLOCKING}, {@link #WRITE_NON_BLOCKING}. It has no
21324aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     *     effect in static mode.
21334aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     *     <br>With {@link #WRITE_BLOCKING}, the write will block until all data has been written
21344aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     *         to the audio sink.
21354aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     *     <br>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after
21364aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     *     queuing as much audio data for playback as possible without blocking.
2137219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * @return zero or the positive number of bytes that were written, or one of the following
2138219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     *    error codes. The number of bytes will be a multiple of the frame size in bytes
2139518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten     *    not to exceed sizeInBytes.
2140219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * <ul>
2141219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * <li>{@link #ERROR_INVALID_OPERATION} if the track isn't properly initialized</li>
2142219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
2143219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * <li>{@link #ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
2144219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     *    needs to be recreated. The dead object error code is not returned if some data was
2145219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     *    successfully transferred. In this case, the error is returned at the next write()</li>
2146219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * <li>{@link #ERROR} in case of other error</li>
2147219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * </ul>
21484aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     */
21494aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung    public int write(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes,
21504aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung            @WriteMode int writeMode) {
21519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
215254955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten        if (mState == STATE_UNINITIALIZED || mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT) {
21539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ERROR_INVALID_OPERATION;
21549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
21559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21564aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung        if ((writeMode != WRITE_BLOCKING) && (writeMode != WRITE_NON_BLOCKING)) {
21574aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung            Log.e(TAG, "AudioTrack.write() called with invalid blocking mode");
21584aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung            return ERROR_BAD_VALUE;
21594aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung        }
21604aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung
2161fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten        if ( (audioData == null) || (offsetInBytes < 0 ) || (sizeInBytes < 0)
2162a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten                || (offsetInBytes + sizeInBytes < 0)    // detect integer overflow
21639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                || (offsetInBytes + sizeInBytes > audioData.length)) {
21649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ERROR_BAD_VALUE;
21659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
21669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21677ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi        int ret = native_write_byte(audioData, offsetInBytes, sizeInBytes, mAudioFormat,
21684aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung                writeMode == WRITE_BLOCKING);
2169a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten
2170a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten        if ((mDataLoadMode == MODE_STATIC)
2171a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten                && (mState == STATE_NO_STATIC_DATA)
2172a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten                && (ret > 0)) {
2173a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten            // benign race with respect to other APIs that read mState
2174a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten            mState = STATE_INITIALIZED;
2175a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten        }
2176a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten
2177a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten        return ret;
21789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
21799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2181e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * Writes the audio data to the audio sink for playback (streaming mode),
2182e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * or copies audio data for later playback (static buffer mode).
21834aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     * The format specified in the AudioTrack constructor should be
21844aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     * {@link AudioFormat#ENCODING_PCM_16BIT} to correspond to the data in the array.
2185659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * <p>
2186659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * In streaming mode, the write will normally block until all the data has been enqueued for
2187659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * playback, and will return a full transfer count.  However, if the track is stopped or paused
2188659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * on entry, or another thread interrupts the write by calling stop or pause, or an I/O error
2189659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * occurs during the write, then the write may return a short transfer count.
2190659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * <p>
2191e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * In static buffer mode, copies the data to the buffer starting at offset 0.
2192659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * Note that the actual playback of this data might occur after this function returns.
219388bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath     *
21949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param audioData the array that holds the data to play.
2195ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * @param offsetInShorts the offset expressed in shorts in audioData where the data to play
2196ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     *     starts.
2197518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten     *    Must not be negative, or cause the data access to go out of bounds of the array.
2198e8c82a37050e568f211d47951480b182a61d42b4Glenn Kasten     * @param sizeInShorts the number of shorts to read in audioData after the offset.
2199518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten     *    Must not be negative, or cause the data access to go out of bounds of the array.
2200219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * @return zero or the positive number of shorts that were written, or one of the following
2201219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     *    error codes. The number of shorts will be a multiple of the channel count not to
2202219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     *    exceed sizeInShorts.
2203219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * <ul>
2204219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * <li>{@link #ERROR_INVALID_OPERATION} if the track isn't properly initialized</li>
2205219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
2206219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * <li>{@link #ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
2207219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     *    needs to be recreated. The dead object error code is not returned if some data was
2208219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     *    successfully transferred. In this case, the error is returned at the next write()</li>
2209219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * <li>{@link #ERROR} in case of other error</li>
2210219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * </ul>
2211659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * This is equivalent to {@link #write(short[], int, int, int)} with <code>writeMode</code>
2212659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * set to  {@link #WRITE_BLOCKING}.
22139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
22144aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung    public int write(@NonNull short[] audioData, int offsetInShorts, int sizeInShorts) {
22154aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung        return write(audioData, offsetInShorts, sizeInShorts, WRITE_BLOCKING);
22164aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung    }
22179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22184aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung    /**
22194aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     * Writes the audio data to the audio sink for playback (streaming mode),
22204aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     * or copies audio data for later playback (static buffer mode).
22214aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     * The format specified in the AudioTrack constructor should be
22224aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     * {@link AudioFormat#ENCODING_PCM_16BIT} to correspond to the data in the array.
2223659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * <p>
2224659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * In streaming mode, the blocking behavior depends on the write mode.  If the write mode is
2225659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * {@link #WRITE_BLOCKING}, the write will normally block until all the data has been enqueued
2226659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * for playback, and will return a full transfer count.  However, if the write mode is
2227659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * {@link #WRITE_NON_BLOCKING}, or the track is stopped or paused on entry, or another thread
2228659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * interrupts the write by calling stop or pause, or an I/O error
2229659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * occurs during the write, then the write may return a short transfer count.
2230659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * <p>
22314aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     * In static buffer mode, copies the data to the buffer starting at offset 0.
2232659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * Note that the actual playback of this data might occur after this function returns.
22334aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     *
2234679f1e26d03ebb5574ed389187f2ebc619832d52Glenn Kasten     * @param audioData the array that holds the data to write.
2235679f1e26d03ebb5574ed389187f2ebc619832d52Glenn Kasten     * @param offsetInShorts the offset expressed in shorts in audioData where the data to write
22364aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     *     starts.
2237518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten     *    Must not be negative, or cause the data access to go out of bounds of the array.
22384aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     * @param sizeInShorts the number of shorts to read in audioData after the offset.
2239518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten     *    Must not be negative, or cause the data access to go out of bounds of the array.
22404aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     * @param writeMode one of {@link #WRITE_BLOCKING}, {@link #WRITE_NON_BLOCKING}. It has no
22414aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     *     effect in static mode.
22424aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     *     <br>With {@link #WRITE_BLOCKING}, the write will block until all data has been written
22434aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     *         to the audio sink.
22444aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     *     <br>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after
22454aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     *     queuing as much audio data for playback as possible without blocking.
2246219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * @return zero or the positive number of shorts that were written, or one of the following
2247219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     *    error codes. The number of shorts will be a multiple of the channel count not to
2248219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     *    exceed sizeInShorts.
2249219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * <ul>
2250219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * <li>{@link #ERROR_INVALID_OPERATION} if the track isn't properly initialized</li>
2251219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
2252219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * <li>{@link #ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
2253219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     *    needs to be recreated. The dead object error code is not returned if some data was
2254219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     *    successfully transferred. In this case, the error is returned at the next write()</li>
2255219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * <li>{@link #ERROR} in case of other error</li>
2256219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * </ul>
22574aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     */
22584aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung    public int write(@NonNull short[] audioData, int offsetInShorts, int sizeInShorts,
22594aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung            @WriteMode int writeMode) {
2260fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten
2261c56b8085919771b6f027dc64ed6a44915e392464Glenn Kasten        if (mState == STATE_UNINITIALIZED || mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT) {
22629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ERROR_INVALID_OPERATION;
22639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
22649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22654aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung        if ((writeMode != WRITE_BLOCKING) && (writeMode != WRITE_NON_BLOCKING)) {
22664aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung            Log.e(TAG, "AudioTrack.write() called with invalid blocking mode");
22674aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung            return ERROR_BAD_VALUE;
22684aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung        }
22694aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung
2270fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten        if ( (audioData == null) || (offsetInShorts < 0 ) || (sizeInShorts < 0)
2271a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten                || (offsetInShorts + sizeInShorts < 0)  // detect integer overflow
22729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                || (offsetInShorts + sizeInShorts > audioData.length)) {
22739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ERROR_BAD_VALUE;
22749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
22759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22764aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung        int ret = native_write_short(audioData, offsetInShorts, sizeInShorts, mAudioFormat,
22774aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung                writeMode == WRITE_BLOCKING);
2278a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten
2279a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten        if ((mDataLoadMode == MODE_STATIC)
2280a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten                && (mState == STATE_NO_STATIC_DATA)
2281a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten                && (ret > 0)) {
2282a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten            // benign race with respect to other APIs that read mState
2283a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten            mState = STATE_INITIALIZED;
2284a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten        }
2285a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten
2286a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten        return ret;
22879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
22889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
22907ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi     * Writes the audio data to the audio sink for playback (streaming mode),
22917ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi     * or copies audio data for later playback (static buffer mode).
22924aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     * The format specified in the AudioTrack constructor should be
22934aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     * {@link AudioFormat#ENCODING_PCM_FLOAT} to correspond to the data in the array.
229454955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     * <p>
2295659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * In streaming mode, the blocking behavior depends on the write mode.  If the write mode is
2296659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * {@link #WRITE_BLOCKING}, the write will normally block until all the data has been enqueued
2297659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * for playback, and will return a full transfer count.  However, if the write mode is
2298659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * {@link #WRITE_NON_BLOCKING}, or the track is stopped or paused on entry, or another thread
2299659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * interrupts the write by calling stop or pause, or an I/O error
2300659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * occurs during the write, then the write may return a short transfer count.
230154955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     * <p>
2302659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * In static buffer mode, copies the data to the buffer starting at offset 0,
2303659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * and the write mode is ignored.
2304659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * Note that the actual playback of this data might occur after this function returns.
2305659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     *
2306679f1e26d03ebb5574ed389187f2ebc619832d52Glenn Kasten     * @param audioData the array that holds the data to write.
230754955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     *     The implementation does not clip for sample values within the nominal range
230854955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     *     [-1.0f, 1.0f], provided that all gains in the audio pipeline are
230954955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     *     less than or equal to unity (1.0f), and in the absence of post-processing effects
231054955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     *     that could add energy, such as reverb.  For the convenience of applications
231154955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     *     that compute samples using filters with non-unity gain,
231254955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     *     sample values +3 dB beyond the nominal range are permitted.
231354955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     *     However such values may eventually be limited or clipped, depending on various gains
231454955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     *     and later processing in the audio path.  Therefore applications are encouraged
231554955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     *     to provide samples values within the nominal range.
231654955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     * @param offsetInFloats the offset, expressed as a number of floats,
2317679f1e26d03ebb5574ed389187f2ebc619832d52Glenn Kasten     *     in audioData where the data to write starts.
2318518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten     *    Must not be negative, or cause the data access to go out of bounds of the array.
2319679f1e26d03ebb5574ed389187f2ebc619832d52Glenn Kasten     * @param sizeInFloats the number of floats to write in audioData after the offset.
2320518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten     *    Must not be negative, or cause the data access to go out of bounds of the array.
232154955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     * @param writeMode one of {@link #WRITE_BLOCKING}, {@link #WRITE_NON_BLOCKING}. It has no
232254955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     *     effect in static mode.
23234aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     *     <br>With {@link #WRITE_BLOCKING}, the write will block until all data has been written
232454955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     *         to the audio sink.
23254aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung     *     <br>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after
232654955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     *     queuing as much audio data for playback as possible without blocking.
2327219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * @return zero or the positive number of floats that were written, or one of the following
2328219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     *    error codes. The number of floats will be a multiple of the channel count not to
2329219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     *    exceed sizeInFloats.
2330219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * <ul>
2331219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * <li>{@link #ERROR_INVALID_OPERATION} if the track isn't properly initialized</li>
2332219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
2333219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * <li>{@link #ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
2334219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     *    needs to be recreated. The dead object error code is not returned if some data was
2335219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     *    successfully transferred. In this case, the error is returned at the next write()</li>
2336219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * <li>{@link #ERROR} in case of other error</li>
2337219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * </ul>
233854955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     */
23394aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung    public int write(@NonNull float[] audioData, int offsetInFloats, int sizeInFloats,
234054955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten            @WriteMode int writeMode) {
234154955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten
234254955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten        if (mState == STATE_UNINITIALIZED) {
234354955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten            Log.e(TAG, "AudioTrack.write() called in invalid state STATE_UNINITIALIZED");
234454955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten            return ERROR_INVALID_OPERATION;
234554955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten        }
234654955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten
234754955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten        if (mAudioFormat != AudioFormat.ENCODING_PCM_FLOAT) {
234854955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten            Log.e(TAG, "AudioTrack.write(float[] ...) requires format ENCODING_PCM_FLOAT");
234954955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten            return ERROR_INVALID_OPERATION;
235054955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten        }
235154955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten
235254955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten        if ((writeMode != WRITE_BLOCKING) && (writeMode != WRITE_NON_BLOCKING)) {
235354955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten            Log.e(TAG, "AudioTrack.write() called with invalid blocking mode");
235454955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten            return ERROR_BAD_VALUE;
235554955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten        }
235654955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten
235754955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten        if ( (audioData == null) || (offsetInFloats < 0 ) || (sizeInFloats < 0)
235854955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten                || (offsetInFloats + sizeInFloats < 0)  // detect integer overflow
235954955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten                || (offsetInFloats + sizeInFloats > audioData.length)) {
236054955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten            Log.e(TAG, "AudioTrack.write() called with invalid array, offset, or size");
236154955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten            return ERROR_BAD_VALUE;
236254955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten        }
236354955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten
236454955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten        int ret = native_write_float(audioData, offsetInFloats, sizeInFloats, mAudioFormat,
236554955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten                writeMode == WRITE_BLOCKING);
236654955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten
236754955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten        if ((mDataLoadMode == MODE_STATIC)
236854955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten                && (mState == STATE_NO_STATIC_DATA)
236954955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten                && (ret > 0)) {
237054955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten            // benign race with respect to other APIs that read mState
237154955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten            mState = STATE_INITIALIZED;
237254955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten        }
237354955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten
237454955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten        return ret;
237554955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten    }
237654955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten
237754955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten
237854955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten    /**
237954955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     * Writes the audio data to the audio sink for playback (streaming mode),
238054955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     * or copies audio data for later playback (static buffer mode).
2381659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * The audioData in ByteBuffer should match the format specified in the AudioTrack constructor.
2382659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * <p>
2383659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * In streaming mode, the blocking behavior depends on the write mode.  If the write mode is
2384659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * {@link #WRITE_BLOCKING}, the write will normally block until all the data has been enqueued
2385659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * for playback, and will return a full transfer count.  However, if the write mode is
2386659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * {@link #WRITE_NON_BLOCKING}, or the track is stopped or paused on entry, or another thread
2387659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * interrupts the write by calling stop or pause, or an I/O error
2388659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * occurs during the write, then the write may return a short transfer count.
2389659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * <p>
2390659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * In static buffer mode, copies the data to the buffer starting at offset 0,
2391659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * and the write mode is ignored.
2392659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * Note that the actual playback of this data might occur after this function returns.
2393659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     *
2394679f1e26d03ebb5574ed389187f2ebc619832d52Glenn Kasten     * @param audioData the buffer that holds the data to write, starting at the position reported
23957ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi     *     by <code>audioData.position()</code>.
23965d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi     *     <BR>Note that upon return, the buffer position (<code>audioData.position()</code>) will
23975d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi     *     have been advanced to reflect the amount of data that was successfully written to
23985d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi     *     the AudioTrack.
2399518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten     * @param sizeInBytes number of bytes to write.  It is recommended but not enforced
2400518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten     *     that the number of bytes requested be a multiple of the frame size (sample size in
2401518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten     *     bytes multiplied by the channel count).
24025d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi     *     <BR>Note this may differ from <code>audioData.remaining()</code>, but cannot exceed it.
24037ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi     * @param writeMode one of {@link #WRITE_BLOCKING}, {@link #WRITE_NON_BLOCKING}. It has no
24047ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi     *     effect in static mode.
24057ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi     *     <BR>With {@link #WRITE_BLOCKING}, the write will block until all data has been written
24067ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi     *         to the audio sink.
24077ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi     *     <BR>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after
24087ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi     *     queuing as much audio data for playback as possible without blocking.
2409219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * @return zero or the positive number of bytes that were written, or one of the following
2410219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     *    error codes.
2411219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * <ul>
2412219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * <li>{@link #ERROR_INVALID_OPERATION} if the track isn't properly initialized</li>
2413219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
2414219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * <li>{@link #ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
2415219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     *    needs to be recreated. The dead object error code is not returned if some data was
2416219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     *    successfully transferred. In this case, the error is returned at the next write()</li>
2417219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * <li>{@link #ERROR} in case of other error</li>
2418219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * </ul>
24197ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi     */
24204aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung    public int write(@NonNull ByteBuffer audioData, int sizeInBytes,
24217ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi            @WriteMode int writeMode) {
24227ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi
24237ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi        if (mState == STATE_UNINITIALIZED) {
24247ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi            Log.e(TAG, "AudioTrack.write() called in invalid state STATE_UNINITIALIZED");
24257ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi            return ERROR_INVALID_OPERATION;
24267ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi        }
24277ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi
24287ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi        if ((writeMode != WRITE_BLOCKING) && (writeMode != WRITE_NON_BLOCKING)) {
24297ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi            Log.e(TAG, "AudioTrack.write() called with invalid blocking mode");
24307ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi            return ERROR_BAD_VALUE;
24317ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi        }
24327ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi
24335d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi        if ( (audioData == null) || (sizeInBytes < 0) || (sizeInBytes > audioData.remaining())) {
24345d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi            Log.e(TAG, "AudioTrack.write() called with invalid size (" + sizeInBytes + ") value");
24357ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi            return ERROR_BAD_VALUE;
24367ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi        }
24377ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi
24387ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi        int ret = 0;
24397ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi        if (audioData.isDirect()) {
24407ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi            ret = native_write_native_bytes(audioData,
24415d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi                    audioData.position(), sizeInBytes, mAudioFormat,
24427ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi                    writeMode == WRITE_BLOCKING);
24437ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi        } else {
24447ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi            ret = native_write_byte(NioUtils.unsafeArray(audioData),
24455d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi                    NioUtils.unsafeArrayOffset(audioData) + audioData.position(),
24467ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi                    sizeInBytes, mAudioFormat,
24477ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi                    writeMode == WRITE_BLOCKING);
24487ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi        }
24497ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi
24507ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi        if ((mDataLoadMode == MODE_STATIC)
24517ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi                && (mState == STATE_NO_STATIC_DATA)
24527ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi                && (ret > 0)) {
24537ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi            // benign race with respect to other APIs that read mState
24547ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi            mState = STATE_INITIALIZED;
24557ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi        }
24567ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi
24575d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi        if (ret > 0) {
24585d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi            audioData.position(audioData.position() + ret);
24595d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi        }
24605d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi
24617ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi        return ret;
24627ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi    }
24637ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi
24647ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi    /**
2465659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * Writes the audio data to the audio sink for playback in streaming mode on a HW_AV_SYNC track.
2466659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten     * The blocking behavior will depend on the write mode.
2467679f1e26d03ebb5574ed389187f2ebc619832d52Glenn Kasten     * @param audioData the buffer that holds the data to write, starting at the position reported
2468cfe964a09ca05778e5dd84f2fd24119b89401696Rachad     *     by <code>audioData.position()</code>.
2469cfe964a09ca05778e5dd84f2fd24119b89401696Rachad     *     <BR>Note that upon return, the buffer position (<code>audioData.position()</code>) will
2470cfe964a09ca05778e5dd84f2fd24119b89401696Rachad     *     have been advanced to reflect the amount of data that was successfully written to
2471cfe964a09ca05778e5dd84f2fd24119b89401696Rachad     *     the AudioTrack.
2472518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten     * @param sizeInBytes number of bytes to write.  It is recommended but not enforced
2473518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten     *     that the number of bytes requested be a multiple of the frame size (sample size in
2474518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten     *     bytes multiplied by the channel count).
2475cfe964a09ca05778e5dd84f2fd24119b89401696Rachad     *     <BR>Note this may differ from <code>audioData.remaining()</code>, but cannot exceed it.
2476cfe964a09ca05778e5dd84f2fd24119b89401696Rachad     * @param writeMode one of {@link #WRITE_BLOCKING}, {@link #WRITE_NON_BLOCKING}.
2477cfe964a09ca05778e5dd84f2fd24119b89401696Rachad     *     <BR>With {@link #WRITE_BLOCKING}, the write will block until all data has been written
2478cfe964a09ca05778e5dd84f2fd24119b89401696Rachad     *         to the audio sink.
2479cfe964a09ca05778e5dd84f2fd24119b89401696Rachad     *     <BR>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after
2480cfe964a09ca05778e5dd84f2fd24119b89401696Rachad     *     queuing as much audio data for playback as possible without blocking.
2481cfe964a09ca05778e5dd84f2fd24119b89401696Rachad     * @param timestamp The timestamp of the first decodable audio frame in the provided audioData.
2482219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * @return zero or the positive number of bytes that were written, or one of the following
2483219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     *    error codes.
2484219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * <ul>
2485219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * <li>{@link #ERROR_INVALID_OPERATION} if the track isn't properly initialized</li>
2486219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
2487219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * <li>{@link #ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
2488219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     *    needs to be recreated. The dead object error code is not returned if some data was
2489219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     *    successfully transferred. In this case, the error is returned at the next write()</li>
2490219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * <li>{@link #ERROR} in case of other error</li>
2491219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent     * </ul>
2492cfe964a09ca05778e5dd84f2fd24119b89401696Rachad     */
249368d5ebd1da6bd4744314749d4fdbaf216414ea94Glenn Kasten    public int write(@NonNull ByteBuffer audioData, int sizeInBytes,
2494cfe964a09ca05778e5dd84f2fd24119b89401696Rachad            @WriteMode int writeMode, long timestamp) {
2495cfe964a09ca05778e5dd84f2fd24119b89401696Rachad
249668d5ebd1da6bd4744314749d4fdbaf216414ea94Glenn Kasten        if (mState == STATE_UNINITIALIZED) {
249768d5ebd1da6bd4744314749d4fdbaf216414ea94Glenn Kasten            Log.e(TAG, "AudioTrack.write() called in invalid state STATE_UNINITIALIZED");
249868d5ebd1da6bd4744314749d4fdbaf216414ea94Glenn Kasten            return ERROR_INVALID_OPERATION;
249968d5ebd1da6bd4744314749d4fdbaf216414ea94Glenn Kasten        }
250068d5ebd1da6bd4744314749d4fdbaf216414ea94Glenn Kasten
250168d5ebd1da6bd4744314749d4fdbaf216414ea94Glenn Kasten        if ((writeMode != WRITE_BLOCKING) && (writeMode != WRITE_NON_BLOCKING)) {
250268d5ebd1da6bd4744314749d4fdbaf216414ea94Glenn Kasten            Log.e(TAG, "AudioTrack.write() called with invalid blocking mode");
250368d5ebd1da6bd4744314749d4fdbaf216414ea94Glenn Kasten            return ERROR_BAD_VALUE;
250468d5ebd1da6bd4744314749d4fdbaf216414ea94Glenn Kasten        }
250568d5ebd1da6bd4744314749d4fdbaf216414ea94Glenn Kasten
250668d5ebd1da6bd4744314749d4fdbaf216414ea94Glenn Kasten        if (mDataLoadMode != MODE_STREAM) {
250768d5ebd1da6bd4744314749d4fdbaf216414ea94Glenn Kasten            Log.e(TAG, "AudioTrack.write() with timestamp called for non-streaming mode track");
250868d5ebd1da6bd4744314749d4fdbaf216414ea94Glenn Kasten            return ERROR_INVALID_OPERATION;
250968d5ebd1da6bd4744314749d4fdbaf216414ea94Glenn Kasten        }
251068d5ebd1da6bd4744314749d4fdbaf216414ea94Glenn Kasten
2511cfe964a09ca05778e5dd84f2fd24119b89401696Rachad        if ((mAttributes.getFlags() & AudioAttributes.FLAG_HW_AV_SYNC) == 0) {
2512cfe964a09ca05778e5dd84f2fd24119b89401696Rachad            Log.d(TAG, "AudioTrack.write() called on a regular AudioTrack. Ignoring pts...");
2513cfe964a09ca05778e5dd84f2fd24119b89401696Rachad            return write(audioData, sizeInBytes, writeMode);
2514cfe964a09ca05778e5dd84f2fd24119b89401696Rachad        }
2515cfe964a09ca05778e5dd84f2fd24119b89401696Rachad
2516cfe964a09ca05778e5dd84f2fd24119b89401696Rachad        if ((audioData == null) || (sizeInBytes < 0) || (sizeInBytes > audioData.remaining())) {
2517cfe964a09ca05778e5dd84f2fd24119b89401696Rachad            Log.e(TAG, "AudioTrack.write() called with invalid size (" + sizeInBytes + ") value");
2518cfe964a09ca05778e5dd84f2fd24119b89401696Rachad            return ERROR_BAD_VALUE;
2519cfe964a09ca05778e5dd84f2fd24119b89401696Rachad        }
2520cfe964a09ca05778e5dd84f2fd24119b89401696Rachad
2521cfe964a09ca05778e5dd84f2fd24119b89401696Rachad        // create timestamp header if none exists
2522cfe964a09ca05778e5dd84f2fd24119b89401696Rachad        if (mAvSyncHeader == null) {
2523cfe964a09ca05778e5dd84f2fd24119b89401696Rachad            mAvSyncHeader = ByteBuffer.allocate(16);
2524cfe964a09ca05778e5dd84f2fd24119b89401696Rachad            mAvSyncHeader.order(ByteOrder.BIG_ENDIAN);
2525cfe964a09ca05778e5dd84f2fd24119b89401696Rachad            mAvSyncHeader.putInt(0x55550001);
25263b3ed7af3b4837440af62e7af4fe5e0e2df17559Paul McLean        }
25273b3ed7af3b4837440af62e7af4fe5e0e2df17559Paul McLean
25283b3ed7af3b4837440af62e7af4fe5e0e2df17559Paul McLean        if (mAvSyncBytesRemaining == 0) {
25293b3ed7af3b4837440af62e7af4fe5e0e2df17559Paul McLean            mAvSyncHeader.putInt(4, sizeInBytes);
25303b3ed7af3b4837440af62e7af4fe5e0e2df17559Paul McLean            mAvSyncHeader.putLong(8, timestamp);
2531cfe964a09ca05778e5dd84f2fd24119b89401696Rachad            mAvSyncHeader.position(0);
2532cfe964a09ca05778e5dd84f2fd24119b89401696Rachad            mAvSyncBytesRemaining = sizeInBytes;
2533cfe964a09ca05778e5dd84f2fd24119b89401696Rachad        }
2534cfe964a09ca05778e5dd84f2fd24119b89401696Rachad
2535cfe964a09ca05778e5dd84f2fd24119b89401696Rachad        // write timestamp header if not completely written already
2536cfe964a09ca05778e5dd84f2fd24119b89401696Rachad        int ret = 0;
2537cfe964a09ca05778e5dd84f2fd24119b89401696Rachad        if (mAvSyncHeader.remaining() != 0) {
2538cfe964a09ca05778e5dd84f2fd24119b89401696Rachad            ret = write(mAvSyncHeader, mAvSyncHeader.remaining(), writeMode);
2539cfe964a09ca05778e5dd84f2fd24119b89401696Rachad            if (ret < 0) {
2540cfe964a09ca05778e5dd84f2fd24119b89401696Rachad                Log.e(TAG, "AudioTrack.write() could not write timestamp header!");
2541cfe964a09ca05778e5dd84f2fd24119b89401696Rachad                mAvSyncHeader = null;
2542cfe964a09ca05778e5dd84f2fd24119b89401696Rachad                mAvSyncBytesRemaining = 0;
2543cfe964a09ca05778e5dd84f2fd24119b89401696Rachad                return ret;
2544cfe964a09ca05778e5dd84f2fd24119b89401696Rachad            }
2545cfe964a09ca05778e5dd84f2fd24119b89401696Rachad            if (mAvSyncHeader.remaining() > 0) {
2546cfe964a09ca05778e5dd84f2fd24119b89401696Rachad                Log.v(TAG, "AudioTrack.write() partial timestamp header written.");
2547cfe964a09ca05778e5dd84f2fd24119b89401696Rachad                return 0;
2548cfe964a09ca05778e5dd84f2fd24119b89401696Rachad            }
2549cfe964a09ca05778e5dd84f2fd24119b89401696Rachad        }
2550cfe964a09ca05778e5dd84f2fd24119b89401696Rachad
2551cfe964a09ca05778e5dd84f2fd24119b89401696Rachad        // write audio data
2552cfe964a09ca05778e5dd84f2fd24119b89401696Rachad        int sizeToWrite = Math.min(mAvSyncBytesRemaining, sizeInBytes);
2553cfe964a09ca05778e5dd84f2fd24119b89401696Rachad        ret = write(audioData, sizeToWrite, writeMode);
2554cfe964a09ca05778e5dd84f2fd24119b89401696Rachad        if (ret < 0) {
2555cfe964a09ca05778e5dd84f2fd24119b89401696Rachad            Log.e(TAG, "AudioTrack.write() could not write audio data!");
2556cfe964a09ca05778e5dd84f2fd24119b89401696Rachad            mAvSyncHeader = null;
2557cfe964a09ca05778e5dd84f2fd24119b89401696Rachad            mAvSyncBytesRemaining = 0;
2558cfe964a09ca05778e5dd84f2fd24119b89401696Rachad            return ret;
2559cfe964a09ca05778e5dd84f2fd24119b89401696Rachad        }
2560cfe964a09ca05778e5dd84f2fd24119b89401696Rachad
2561cfe964a09ca05778e5dd84f2fd24119b89401696Rachad        mAvSyncBytesRemaining -= ret;
2562cfe964a09ca05778e5dd84f2fd24119b89401696Rachad
2563cfe964a09ca05778e5dd84f2fd24119b89401696Rachad        return ret;
2564cfe964a09ca05778e5dd84f2fd24119b89401696Rachad    }
2565cfe964a09ca05778e5dd84f2fd24119b89401696Rachad
2566cfe964a09ca05778e5dd84f2fd24119b89401696Rachad
2567cfe964a09ca05778e5dd84f2fd24119b89401696Rachad    /**
2568ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     * Sets the playback head position within the static buffer to zero,
2569ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     * that is it rewinds to start of static buffer.
2570ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     * The track must be stopped or paused, and
2571ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     * the track's creation mode must be {@link #MODE_STATIC}.
2572ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     * <p>
25730e3de6cacaffcfeda4d6353be61e2f1f9ed80705Dianne Hackborn     * As of {@link android.os.Build.VERSION_CODES#M}, also resets the value returned by
2574ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     * {@link #getPlaybackHeadPosition()} to zero.
2575ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     * For earlier API levels, the reset behavior is unspecified.
2576ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten     * <p>
257735e576e79292122fad462ebccd8520822552a6d7Andy Hung     * Use {@link #setPlaybackHeadPosition(int)} with a zero position
257835e576e79292122fad462ebccd8520822552a6d7Andy Hung     * if the reset of <code>getPlaybackHeadPosition()</code> is not needed.
25799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE},
25809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *  {@link #ERROR_INVALID_OPERATION}
25819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
25829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int reloadStaticData() {
2583a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten        if (mDataLoadMode == MODE_STREAM || mState != STATE_INITIALIZED) {
25849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ERROR_INVALID_OPERATION;
25859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
25869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return native_reload_static();
25879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
25889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
25897070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent    //--------------------------------------------------------------------------
25907070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent    // Audio effects management
25917070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent    //--------------------
25927070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent
25937070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent    /**
25941a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent     * Attaches an auxiliary effect to the audio track. A typical auxiliary
25951a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent     * effect is a reverberation effect which can be applied on any sound source
25961a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent     * that directs a certain amount of its energy to this effect. This amount
25971a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent     * is defined by setAuxEffectSendLevel().
25987070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent     * {@see #setAuxEffectSendLevel(float)}.
25991a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent     * <p>After creating an auxiliary effect (e.g.
26001a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent     * {@link android.media.audiofx.EnvironmentalReverb}), retrieve its ID with
26011a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent     * {@link android.media.audiofx.AudioEffect#getId()} and use it when calling
26027070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent     * this method to attach the audio track to the effect.
26031a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent     * <p>To detach the effect from the audio track, call this method with a
26041a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent     * null effect id.
26057070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent     *
26067070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent     * @param effectId system wide unique id of the effect to attach
26077070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent     * @return error code or success, see {@link #SUCCESS},
26087070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent     *    {@link #ERROR_INVALID_OPERATION}, {@link #ERROR_BAD_VALUE}
26097070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent     */
26107070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent    public int attachAuxEffect(int effectId) {
26113b4df62704a6184878afd9272830cf3db7bd2d66Glenn Kasten        if (mState == STATE_UNINITIALIZED) {
26127070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent            return ERROR_INVALID_OPERATION;
26137070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent        }
26147070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent        return native_attachAuxEffect(effectId);
26157070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent    }
26167070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent
26177070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent    /**
26187070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent     * Sets the send level of the audio track to the attached auxiliary effect
261978cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * {@link #attachAuxEffect(int)}.  Effect levels
262078cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * are clamped to the closed interval [0.0, max] where
262178cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * max is the value of {@link #getMaxVolume}.
262278cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * A value of 0.0 results in no effect, and a value of 1.0 is full send.
2623e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * <p>By default the send level is 0.0f, so even if an effect is attached to the player
26247070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent     * this method must be called for the effect to be applied.
262578cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * <p>Note that the passed level value is a linear scalar. UI controls should be scaled
262678cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * logarithmically: the gain applied by audio framework ranges from -72dB to at least 0dB,
26277070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent     * so an appropriate conversion from linear UI input x to level is:
26285c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten     * x == 0 -&gt; level = 0
26295c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten     * 0 &lt; x &lt;= R -&gt; level = 10^(72*(x-R)/20/R)
26307070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent     *
263178cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * @param level linear send level
26327070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent     * @return error code or success, see {@link #SUCCESS},
26333009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten     *    {@link #ERROR_INVALID_OPERATION}, {@link #ERROR}
26347070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent     */
26357070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent    public int setAuxEffectSendLevel(float level) {
26363b4df62704a6184878afd9272830cf3db7bd2d66Glenn Kasten        if (mState == STATE_UNINITIALIZED) {
26377070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent            return ERROR_INVALID_OPERATION;
26387070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent        }
26393c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi        return baseSetAuxEffectSendLevel(level);
26403c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi    }
26413c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi
26423c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi    @Override
26438e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi    int playerSetAuxEffectSendLevel(boolean muting, float level) {
26448e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi        level = clampGainOrLevel(muting ? 0.0f : level);
26453009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten        int err = native_setAuxEffectSendLevel(level);
26463009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten        return err == 0 ? SUCCESS : ERROR;
26477070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent    }
26489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
264988e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean    //--------------------------------------------------------------------------
265088e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean    // Explicit Routing
265188e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean    //--------------------
265288e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean    private AudioDeviceInfo mPreferredDevice = null;
265388e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean
265488e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean    /**
26552d6de4c38c899707e0596b7fa4dad9bbb3eb6b60Paul McLean     * Specifies an audio device (via an {@link AudioDeviceInfo} object) to route
265688e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean     * the output from this AudioTrack.
26579e29086d5df800532e736d8f31e2b9159b102524Glenn Kasten     * @param deviceInfo The {@link AudioDeviceInfo} specifying the audio sink.
26589e29086d5df800532e736d8f31e2b9159b102524Glenn Kasten     *  If deviceInfo is null, default routing is restored.
265988e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean     * @return true if succesful, false if the specified {@link AudioDeviceInfo} is non-null and
266088e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean     * does not correspond to a valid audio output device.
266188e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean     */
2662ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey    @Override
2663e3383cc4539921756232ae4f3f54e99b95fb20ccPaul McLean    public boolean setPreferredDevice(AudioDeviceInfo deviceInfo) {
266488e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean        // Do some validation....
26652d6de4c38c899707e0596b7fa4dad9bbb3eb6b60Paul McLean        if (deviceInfo != null && !deviceInfo.isSink()) {
266688e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean            return false;
266788e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean        }
26684bcdba848449b33d7022de527c526943aff1f5fdEric Laurent        int preferredDeviceId = deviceInfo != null ? deviceInfo.getId() : 0;
26694bcdba848449b33d7022de527c526943aff1f5fdEric Laurent        boolean status = native_setOutputDevice(preferredDeviceId);
26704bcdba848449b33d7022de527c526943aff1f5fdEric Laurent        if (status == true) {
26714bcdba848449b33d7022de527c526943aff1f5fdEric Laurent            synchronized (this) {
26724bcdba848449b33d7022de527c526943aff1f5fdEric Laurent                mPreferredDevice = deviceInfo;
26734bcdba848449b33d7022de527c526943aff1f5fdEric Laurent            }
26744bcdba848449b33d7022de527c526943aff1f5fdEric Laurent        }
26754bcdba848449b33d7022de527c526943aff1f5fdEric Laurent        return status;
267688e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean    }
267788e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean
267888e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean    /**
2679e3383cc4539921756232ae4f3f54e99b95fb20ccPaul McLean     * Returns the selected output specified by {@link #setPreferredDevice}. Note that this
26802d6de4c38c899707e0596b7fa4dad9bbb3eb6b60Paul McLean     * is not guaranteed to correspond to the actual device being used for playback.
268188e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean     */
2682ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey    @Override
2683e3383cc4539921756232ae4f3f54e99b95fb20ccPaul McLean    public AudioDeviceInfo getPreferredDevice() {
26844bcdba848449b33d7022de527c526943aff1f5fdEric Laurent        synchronized (this) {
26854bcdba848449b33d7022de527c526943aff1f5fdEric Laurent            return mPreferredDevice;
26864bcdba848449b33d7022de527c526943aff1f5fdEric Laurent        }
268788e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean    }
268888e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean
2689d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean    /**
2690d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean     * Returns an {@link AudioDeviceInfo} identifying the current routing of this AudioTrack.
26918e6c9f46172458624349755c9b1bc051f420d36dPaul McLean     * Note: The query is only valid if the AudioTrack is currently playing. If it is not,
26928e6c9f46172458624349755c9b1bc051f420d36dPaul McLean     * <code>getRoutedDevice()</code> will return null.
2693d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean     */
2694ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey    @Override
2695d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean    public AudioDeviceInfo getRoutedDevice() {
26964bcdba848449b33d7022de527c526943aff1f5fdEric Laurent        int deviceId = native_getRoutedDeviceId();
26974bcdba848449b33d7022de527c526943aff1f5fdEric Laurent        if (deviceId == 0) {
26984bcdba848449b33d7022de527c526943aff1f5fdEric Laurent            return null;
26994bcdba848449b33d7022de527c526943aff1f5fdEric Laurent        }
27004bcdba848449b33d7022de527c526943aff1f5fdEric Laurent        AudioDeviceInfo[] devices =
2701e3383cc4539921756232ae4f3f54e99b95fb20ccPaul McLean                AudioManager.getDevicesStatic(AudioManager.GET_DEVICES_OUTPUTS);
27024bcdba848449b33d7022de527c526943aff1f5fdEric Laurent        for (int i = 0; i < devices.length; i++) {
27034bcdba848449b33d7022de527c526943aff1f5fdEric Laurent            if (devices[i].getId() == deviceId) {
27044bcdba848449b33d7022de527c526943aff1f5fdEric Laurent                return devices[i];
27054bcdba848449b33d7022de527c526943aff1f5fdEric Laurent            }
27064bcdba848449b33d7022de527c526943aff1f5fdEric Laurent        }
2707d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean        return null;
2708d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean    }
2709d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean
2710ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean    /*
2711ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean     * Call BEFORE adding a routing callback handler.
2712ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean     */
2713ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey    private void testEnableNativeRoutingCallbacksLocked() {
2714ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey        if (mRoutingChangeListeners.size() == 0) {
2715ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean            native_enableDeviceCallback();
2716ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean        }
2717ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean    }
2718ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean
2719ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean    /*
2720ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean     * Call AFTER removing a routing callback handler.
2721ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean     */
2722ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey    private void testDisableNativeRoutingCallbacksLocked() {
2723ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey        if (mRoutingChangeListeners.size() == 0) {
2724ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean            native_disableDeviceCallback();
2725ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean        }
2726ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean    }
2727ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean
2728ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean    //--------------------------------------------------------------------------
2729ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey    // (Re)Routing Info
2730ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean    //--------------------
2731ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean    /**
2732ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean     * The list of AudioRouting.OnRoutingChangedListener interfaces added (with
2733688b9cb656fbab4a9b5c5c969bdcfabd034c1eeeJean-Michel Trivi     * {@link #addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, Handler)}
2734688b9cb656fbab4a9b5c5c969bdcfabd034c1eeeJean-Michel Trivi     * by an app to receive (re)routing notifications.
2735ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean     */
2736ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey    @GuardedBy("mRoutingChangeListeners")
2737ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey    private ArrayMap<AudioRouting.OnRoutingChangedListener,
2738ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey            NativeRoutingEventHandlerDelegate> mRoutingChangeListeners = new ArrayMap<>();
2739ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean
2740ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean   /**
2741ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean    * Adds an {@link AudioRouting.OnRoutingChangedListener} to receive notifications of routing
2742ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean    * changes on this AudioTrack.
2743ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean    * @param listener The {@link AudioRouting.OnRoutingChangedListener} interface to receive
2744ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean    * notifications of rerouting events.
2745ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean    * @param handler  Specifies the {@link Handler} object for the thread on which to execute
2746ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean    * the callback. If <code>null</code>, the {@link Handler} associated with the main
2747ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean    * {@link Looper} will be used.
2748ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean    */
2749ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey    @Override
2750ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey    public void addOnRoutingChangedListener(AudioRouting.OnRoutingChangedListener listener,
2751ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean            Handler handler) {
2752ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey        synchronized (mRoutingChangeListeners) {
2753ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey            if (listener != null && !mRoutingChangeListeners.containsKey(listener)) {
2754ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey                testEnableNativeRoutingCallbacksLocked();
2755ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey                mRoutingChangeListeners.put(
2756ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey                        listener, new NativeRoutingEventHandlerDelegate(this, listener,
2757ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey                                handler != null ? handler : new Handler(mInitializationLooper)));
2758ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean            }
2759ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean        }
2760ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean    }
2761ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean
2762ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean    /**
2763ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean     * Removes an {@link AudioRouting.OnRoutingChangedListener} which has been previously added
2764ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean     * to receive rerouting notifications.
2765ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean     * @param listener The previously added {@link AudioRouting.OnRoutingChangedListener} interface
2766ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean     * to remove.
2767ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean     */
2768ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey    @Override
2769ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey    public void removeOnRoutingChangedListener(AudioRouting.OnRoutingChangedListener listener) {
2770ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey        synchronized (mRoutingChangeListeners) {
2771ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey            if (mRoutingChangeListeners.containsKey(listener)) {
2772ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey                mRoutingChangeListeners.remove(listener);
2773ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey            }
2774ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey            testDisableNativeRoutingCallbacksLocked();
2775ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean        }
2776ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean    }
2777ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean
2778ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean    //--------------------------------------------------------------------------
2779ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey    // (Re)Routing Info
2780ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean    //--------------------
2781ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean    /**
2782ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey     * Defines the interface by which applications can receive notifications of
2783ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey     * routing changes for the associated {@link AudioTrack}.
2784ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey     *
2785ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey     * @deprecated users should switch to the general purpose
2786ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey     *             {@link AudioRouting.OnRoutingChangedListener} class instead.
2787ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean     */
2788ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean    @Deprecated
2789ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey    public interface OnRoutingChangedListener extends AudioRouting.OnRoutingChangedListener {
2790ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean        /**
2791ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey         * Called when the routing of an AudioTrack changes from either and
2792ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey         * explicit or policy rerouting. Use {@link #getRoutedDevice()} to
2793ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey         * retrieve the newly routed-to device.
2794ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean         */
2795ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean        public void onRoutingChanged(AudioTrack audioTrack);
2796ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean
2797ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey        @Override
2798ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey        default public void onRoutingChanged(AudioRouting router) {
2799ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey            if (router instanceof AudioTrack) {
2800ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey                onRoutingChanged((AudioTrack) router);
2801ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey            }
2802ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey        }
2803ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey    }
2804d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean
2805d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean    /**
2806e3383cc4539921756232ae4f3f54e99b95fb20ccPaul McLean     * Adds an {@link OnRoutingChangedListener} to receive notifications of routing changes
2807d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean     * on this AudioTrack.
28088e6c9f46172458624349755c9b1bc051f420d36dPaul McLean     * @param listener The {@link OnRoutingChangedListener} interface to receive notifications
28098e6c9f46172458624349755c9b1bc051f420d36dPaul McLean     * of rerouting events.
28108e6c9f46172458624349755c9b1bc051f420d36dPaul McLean     * @param handler  Specifies the {@link Handler} object for the thread on which to execute
28118e6c9f46172458624349755c9b1bc051f420d36dPaul McLean     * the callback. If <code>null</code>, the {@link Handler} associated with the main
28128e6c9f46172458624349755c9b1bc051f420d36dPaul McLean     * {@link Looper} will be used.
2813ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey     * @deprecated users should switch to the general purpose
2814ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey     *             {@link AudioRouting.OnRoutingChangedListener} class instead.
2815d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean     */
2816ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean    @Deprecated
2817e3383cc4539921756232ae4f3f54e99b95fb20ccPaul McLean    public void addOnRoutingChangedListener(OnRoutingChangedListener listener,
2818d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean            android.os.Handler handler) {
2819ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey        addOnRoutingChangedListener((AudioRouting.OnRoutingChangedListener) listener, handler);
2820d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean    }
2821d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean
2822d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean    /**
2823e3383cc4539921756232ae4f3f54e99b95fb20ccPaul McLean     * Removes an {@link OnRoutingChangedListener} which has been previously added
28248e6c9f46172458624349755c9b1bc051f420d36dPaul McLean     * to receive rerouting notifications.
28258e6c9f46172458624349755c9b1bc051f420d36dPaul McLean     * @param listener The previously added {@link OnRoutingChangedListener} interface to remove.
2826ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey     * @deprecated users should switch to the general purpose
2827ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey     *             {@link AudioRouting.OnRoutingChangedListener} class instead.
2828d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean     */
2829ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean    @Deprecated
2830e3383cc4539921756232ae4f3f54e99b95fb20ccPaul McLean    public void removeOnRoutingChangedListener(OnRoutingChangedListener listener) {
2831ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey        removeOnRoutingChangedListener((AudioRouting.OnRoutingChangedListener) listener);
2832d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean    }
2833d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean
2834d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean    /**
2835d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean     * Sends device list change notification to all listeners.
2836d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean     */
2837d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean    private void broadcastRoutingChange() {
2838ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean        AudioManager.resetAudioPortGeneration();
2839d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean        synchronized (mRoutingChangeListeners) {
2840ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey            for (NativeRoutingEventHandlerDelegate delegate : mRoutingChangeListeners.values()) {
2841ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey                Handler handler = delegate.getHandler();
2842ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey                if (handler != null) {
2843ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey                    handler.sendEmptyMessage(AudioSystem.NATIVE_EVENT_ROUTING_CHANGE);
2844ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey                }
2845ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean            }
2846ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean        }
2847d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean    }
2848d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean
28499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //---------------------------------------------------------
28509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Interface definitions
28519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //--------------------
28529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
28534df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     * Interface definition for a callback to be invoked when the playback head position of
28544df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     * an AudioTrack has reached a notification marker or has increased by a certain period.
28559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
28564df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    public interface OnPlaybackPositionUpdateListener  {
28579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
28589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Called on the listener to notify it that the previously set marker has been reached
28599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * by the playback head.
28609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
28619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void onMarkerReached(AudioTrack track);
2862fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten
28639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
28649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Called on the listener to periodically notify it that the playback head has reached
28659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * a multiple of the notification period.
28669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
28679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void onPeriodicNotification(AudioTrack track);
28689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
28699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
28709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //---------------------------------------------------------
28719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Inner classes
28729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //--------------------
28739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
28744df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     * Helper class to handle the forwarding of native events to the appropriate listener
28754df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     * (potentially) handled in a different thread
28765c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten     */
2877d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean    private class NativePositionEventHandlerDelegate {
28784df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        private final Handler mHandler;
2879fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten
2880d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean        NativePositionEventHandlerDelegate(final AudioTrack track,
288195bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten                                   final OnPlaybackPositionUpdateListener listener,
288295bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten                                   Handler handler) {
28834df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            // find the looper for our new event handler
28844df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            Looper looper;
28854df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            if (handler != null) {
28864df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                looper = handler.getLooper();
28874df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            } else {
2888105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                // no given handler, use the looper the AudioTrack was created in
2889105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                looper = mInitializationLooper;
28909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2891fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten
28924df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            // construct the event handler with this looper
28934df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            if (looper != null) {
28944df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                // implement the event handler delegate
28954df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                mHandler = new Handler(looper) {
28964df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                    @Override
28974df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                    public void handleMessage(Message msg) {
289895bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten                        if (track == null) {
28994df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            return;
29004df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        }
29014df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        switch(msg.what) {
29024df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        case NATIVE_EVENT_MARKER:
29034df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            if (listener != null) {
290495bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten                                listener.onMarkerReached(track);
29054df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            }
29064df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            break;
29074df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        case NATIVE_EVENT_NEW_POS:
29084df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            if (listener != null) {
290995bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten                                listener.onPeriodicNotification(track);
29104df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            }
29114df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            break;
29124df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        default:
29131f61d01508651b4475397414e1fe06af1ab8fadaGlenn Kasten                            loge("Unknown native event type: " + msg.what);
29144df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            break;
29154df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        }
29164df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                    }
29174df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                };
29184df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            } else {
29194df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                mHandler = null;
2920fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten            }
29214df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        }
2922fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten
29234df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        Handler getHandler() {
29244df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            return mHandler;
29259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
29269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
29279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2928d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean    /**
2929d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean     * Helper class to handle the forwarding of native events to the appropriate listener
2930d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean     * (potentially) handled in a different thread
2931d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean     */
2932d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean    private class NativeRoutingEventHandlerDelegate {
2933d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean        private final Handler mHandler;
2934d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean
2935d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean        NativeRoutingEventHandlerDelegate(final AudioTrack track,
2936ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean                                   final AudioRouting.OnRoutingChangedListener listener,
2937ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean                                   Handler handler) {
2938ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean            // find the looper for our new event handler
2939ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean            Looper looper;
2940ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean            if (handler != null) {
2941ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean                looper = handler.getLooper();
2942ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean            } else {
2943ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean                // no given handler, use the looper the AudioTrack was created in
2944d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean                looper = mInitializationLooper;
2945d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean            }
2946d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean
2947d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean            // construct the event handler with this looper
2948d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean            if (looper != null) {
2949d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean                // implement the event handler delegate
2950d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean                mHandler = new Handler(looper) {
2951d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean                    @Override
2952d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean                    public void handleMessage(Message msg) {
2953d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean                        if (track == null) {
2954d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean                            return;
2955d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean                        }
2956d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean                        switch(msg.what) {
29574bcdba848449b33d7022de527c526943aff1f5fdEric Laurent                        case AudioSystem.NATIVE_EVENT_ROUTING_CHANGE:
2958d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean                            if (listener != null) {
2959e3383cc4539921756232ae4f3f54e99b95fb20ccPaul McLean                                listener.onRoutingChanged(track);
2960d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean                            }
2961d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean                            break;
2962d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean                        default:
2963d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean                            loge("Unknown native event type: " + msg.what);
2964d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean                            break;
2965d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean                        }
2966d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean                    }
2967d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean                };
2968d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean            } else {
2969d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean                mHandler = null;
2970d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean            }
2971d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean        }
2972d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean
2973d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean        Handler getHandler() {
2974d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean            return mHandler;
2975d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean        }
2976d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean    }
29779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
29789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //---------------------------------------------------------
29799dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi    // Methods for IPlayer interface
29809dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi    //--------------------
29819dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi    @Override
29829dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi    void playerStart() {
29839dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi        play();
29849dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi    }
29859dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi
29869dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi    @Override
29879dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi    void playerPause() {
29889dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi        pause();
29899dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi    }
29909dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi
29919dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi    @Override
29929dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi    void playerStop() {
29939dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi        stop();
29949dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi    }
29959dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi
29969dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi    //---------------------------------------------------------
29979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Java methods called from the native side
29989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //--------------------
29999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @SuppressWarnings("unused")
30009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static void postEventFromNative(Object audiotrack_ref,
30019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int what, int arg1, int arg2, Object obj) {
30029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //logd("Event posted from the native side: event="+ what + " args="+ arg1+" "+arg2);
30039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        AudioTrack track = (AudioTrack)((WeakReference)audiotrack_ref).get();
30049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (track == null) {
30059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
30069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
30079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
30084bcdba848449b33d7022de527c526943aff1f5fdEric Laurent        if (what == AudioSystem.NATIVE_EVENT_ROUTING_CHANGE) {
30094bcdba848449b33d7022de527c526943aff1f5fdEric Laurent            track.broadcastRoutingChange();
30104bcdba848449b33d7022de527c526943aff1f5fdEric Laurent            return;
30114bcdba848449b33d7022de527c526943aff1f5fdEric Laurent        }
3012d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean        NativePositionEventHandlerDelegate delegate = track.mEventHandlerDelegate;
301395bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten        if (delegate != null) {
301495bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten            Handler handler = delegate.getHandler();
301595bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten            if (handler != null) {
301695bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten                Message m = handler.obtainMessage(what, arg1, arg2, obj);
301795bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten                handler.sendMessage(m);
301895bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten            }
30199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
30209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
30219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
30229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
30239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //---------------------------------------------------------
30249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Native methods called from the Java side
30259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //--------------------
30269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3027a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi    // post-condition: mStreamType is overwritten with a value
3028a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi    //     that reflects the audio attributes (e.g. an AudioAttributes object with a usage of
3029a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi    //     AudioAttributes.USAGE_MEDIA will map to AudioManager.STREAM_MUSIC
3030a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi    private native final int native_setup(Object /*WeakReference<AudioTrack>*/ audiotrack_this,
3031a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi            Object /*AudioAttributes*/ attributes,
30321cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten            int[] sampleRate, int channelMask, int channelIndexMask, int audioFormat,
30339b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean            int buffSizeInBytes, int mode, int[] sessionId, long nativeAudioTrack);
30349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
30359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final void native_finalize();
30369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3037c69ac54111b271bdaf2dd9e40218906435bbde9fPaul McLean    /**
3038c69ac54111b271bdaf2dd9e40218906435bbde9fPaul McLean     * @hide
3039c69ac54111b271bdaf2dd9e40218906435bbde9fPaul McLean     */
3040c69ac54111b271bdaf2dd9e40218906435bbde9fPaul McLean    public native final void native_release();
30419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
30429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final void native_start();
30439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
30449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final void native_stop();
30459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
30469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final void native_pause();
30479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
30489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final void native_flush();
30499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
30509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final int native_write_byte(byte[] audioData,
30517ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi                                               int offsetInBytes, int sizeInBytes, int format,
30527ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi                                               boolean isBlocking);
30539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
30549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final int native_write_short(short[] audioData,
30554aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung                                                int offsetInShorts, int sizeInShorts, int format,
30564aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung                                                boolean isBlocking);
30579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
305854955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten    private native final int native_write_float(float[] audioData,
305954955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten                                                int offsetInFloats, int sizeInFloats, int format,
306054955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten                                                boolean isBlocking);
306154955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten
30627ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi    private native final int native_write_native_bytes(Object audioData,
30635d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi            int positionInBytes, int sizeInBytes, int format, boolean blocking);
30647ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi
30659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final int native_reload_static();
30669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
306710a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk    private native final int native_get_buffer_size_frames();
306810a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk    private native final int native_set_buffer_size_frames(int bufferSizeInFrames);
306910a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk    private native final int native_get_buffer_capacity_frames();
30709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
30719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final void native_setVolume(float leftVolume, float rightVolume);
30729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
307388e209dcf8c2ebddda5c272f46d1bd5478bc639cEric Laurent    private native final int native_set_playback_rate(int sampleRateInHz);
307488e209dcf8c2ebddda5c272f46d1bd5478bc639cEric Laurent    private native final int native_get_playback_rate();
30759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
30762d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia    private native final void native_set_playback_params(@NonNull PlaybackParams params);
30772d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia    private native final @NonNull PlaybackParams native_get_playback_params();
3078263b4c97823295c41900210515d0c769a236190cAndy Hung
30799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final int native_set_marker_pos(int marker);
30809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final int native_get_marker_pos();
30819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
30829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final int native_set_pos_update_period(int updatePeriod);
30839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final int native_get_pos_update_period();
30849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
30859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final int native_set_position(int position);
30869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final int native_get_position();
30879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
308861dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman    private native final int native_get_latency();
308961dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman
309003f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk    private native final int native_get_underrun_count();
309103f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk
3092ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung    private native final int native_get_flags();
3093ebc2c14b0777042f2325d437078b0e7815129b75Andy Hung
3094948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    // longArray must be a non-null array of length >= 2
3095948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    // [0] is assigned the frame position
3096948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    // [1] is assigned the time in CLOCK_MONOTONIC nanoseconds
3097948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    private native final int native_get_timestamp(long[] longArray);
3098948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten
30999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final int native_set_loop(int start, int end, int loopCount);
31009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
31019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static private native final int native_get_output_sample_rate(int streamType);
31029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static private native final int native_get_min_buff_size(
31039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int sampleRateInHz, int channelConfig, int audioFormat);
31049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
31057070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent    private native final int native_attachAuxEffect(int effectId);
31063009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten    private native final int native_setAuxEffectSendLevel(float level);
31077070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent
310888e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean    private native final boolean native_setOutputDevice(int deviceId);
31094bcdba848449b33d7022de527c526943aff1f5fdEric Laurent    private native final int native_getRoutedDeviceId();
31104bcdba848449b33d7022de527c526943aff1f5fdEric Laurent    private native final void native_enableDeviceCallback();
31114bcdba848449b33d7022de527c526943aff1f5fdEric Laurent    private native final void native_disableDeviceCallback();
311225d3c7c49bafb22723138bfab2e315d2d0a926fbGlenn Kasten    static private native int native_get_FCC_8();
311388e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean
3114035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung    private native int native_applyVolumeShaper(
3115035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            @NonNull VolumeShaper.Configuration configuration,
3116035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung            @NonNull VolumeShaper.Operation operation);
3117035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung
3118035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung    private native @Nullable VolumeShaper.State native_getVolumeShaperState(int id);
3119035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung
31209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //---------------------------------------------------------
31219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Utility methods
31229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //------------------
31239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
31249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static void logd(String msg) {
31251f61d01508651b4475397414e1fe06af1ab8fadaGlenn Kasten        Log.d(TAG, msg);
31269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
31279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
31289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static void loge(String msg) {
31291f61d01508651b4475397414e1fe06af1ab8fadaGlenn Kasten        Log.e(TAG, msg);
31309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
31319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3132