AudioTrack.java revision 54955e33c8612a737a76177408f3e7c8482cfcf4
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;
227ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Triviimport java.nio.ByteBuffer;
237ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Triviimport java.nio.NioUtils;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
257ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Triviimport android.annotation.IntDef;
261af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlockimport android.app.ActivityThread;
271af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlockimport android.app.AppOpsManager;
281af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlockimport android.content.Context;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
301af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlockimport android.os.IBinder;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Looper;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message;
331af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlockimport android.os.Process;
341af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlockimport android.os.RemoteException;
351af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlockimport android.os.ServiceManager;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
381af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlockimport com.android.internal.app.IAppOpsService;
391af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The AudioTrack class manages and plays a single audio resource for Java applications.
43e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * It allows streaming of PCM audio buffers to the audio sink for playback. This is
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * achieved by "pushing" the data to the AudioTrack object using one of the
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *  {@link #write(byte[], int, int)} and {@link #write(short[], int, int)} methods.
4688bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath *
47ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi * <p>An AudioTrack instance can operate under two modes: static or streaming.<br>
48ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi * In Streaming mode, the application writes a continuous stream of data to the AudioTrack, using
4988bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath * one of the {@code write()} methods. These are blocking and return when the data has been
5088bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath * transferred from the Java layer to the native layer and queued for playback. The streaming
5188bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath * mode is most useful when playing blocks of audio data that for instance are:
5288bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath *
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul>
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   <li>too big to fit in memory because of the duration of the sound to play,</li>
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *   <li>too big to fit in memory because of the characteristics of the audio data
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *         (high sampling rate, bits per sample ...)</li>
57ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi *   <li>received or generated while previously queued audio is playing.</li>
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </ul>
5988bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath *
605c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten * The static mode should be chosen when dealing with short sounds that fit in memory and
6188bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath * that need to be played with the smallest latency possible. The static mode will
6288bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath * therefore be preferred for UI and game sounds that are played often, and with the
6388bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath * smallest overhead possible.
6488bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath *
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Upon creation, an AudioTrack object initializes its associated audio buffer.
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The size of this buffer, specified during the construction, determines how long an AudioTrack
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * can play before running out of data.<br>
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * For an AudioTrack using the static mode, this size is the maximum size of the sound that can
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be played from it.<br>
70e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * For the streaming mode, data will be written to the audio sink in chunks of
715c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten * sizes less than or equal to the total buffer size.
7255a3218f242a611afb3569d88970c0c5dbf8ce54Glenn Kasten *
7355a3218f242a611afb3569d88970c0c5dbf8ce54Glenn Kasten * AudioTrack is not final and thus permits subclasses, but such use is not recommended.
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
7554955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten// add {@link #write(float[], int, int)} when @hide removed
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class AudioTrack
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //---------------------------------------------------------
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Constants
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //--------------------
8178cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten    /** Minimum value for a linear gain or auxiliary effect level.
8278cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     *  This value must be exactly equal to 0.0f; do not change it.
8378cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     */
8478cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten    private static final float GAIN_MIN = 0.0f;
8578cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten    /** Maximum value for a linear gain or auxiliary effect level.
8678cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     *  This value must be greater than or equal to 1.0f.
8778cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     */
8878cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten    private static final float GAIN_MAX = 1.0f;
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
90ad67c9546494a7c4d9336b57889a7c19a7dbb945Glenn Kasten    /** Minimum value for sample rate */
91ad67c9546494a7c4d9336b57889a7c19a7dbb945Glenn Kasten    private static final int SAMPLE_RATE_HZ_MIN = 4000;
92ad67c9546494a7c4d9336b57889a7c19a7dbb945Glenn Kasten    /** Maximum value for sample rate */
93ad67c9546494a7c4d9336b57889a7c19a7dbb945Glenn Kasten    private static final int SAMPLE_RATE_HZ_MAX = 48000;
94ad67c9546494a7c4d9336b57889a7c19a7dbb945Glenn Kasten
95ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi    /** indicates AudioTrack state is stopped */
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int PLAYSTATE_STOPPED = 1;  // matches SL_PLAYSTATE_STOPPED
97ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi    /** indicates AudioTrack state is paused */
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int PLAYSTATE_PAUSED  = 2;  // matches SL_PLAYSTATE_PAUSED
99ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi    /** indicates AudioTrack state is playing */
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int PLAYSTATE_PLAYING = 3;  // matches SL_PLAYSTATE_PLAYING
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1025c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten    // keep these values in sync with android_media_AudioTrack.cpp
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Creation mode where audio data is transferred from Java to the native layer
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * only once before the audio starts playing.
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int MODE_STATIC = 0;
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Creation mode where audio data is streamed from Java to the native layer
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * as the audio is playing.
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int MODE_STREAM = 1;
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
115ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * State of an AudioTrack that was not successfully initialized upon creation.
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int STATE_UNINITIALIZED = 0;
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * State of an AudioTrack that is ready to be used.
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int STATE_INITIALIZED   = 1;
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * State of a successfully initialized AudioTrack that uses static data,
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * but that hasn't received that data yet.
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int STATE_NO_STATIC_DATA = 2;
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Error codes:
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // to keep in sync with frameworks/base/core/jni/android_media_AudioTrack.cpp
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Denotes a successful operation.
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public  static final int SUCCESS                               = 0;
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Denotes a generic operation failure.
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public  static final int ERROR                                 = -1;
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Denotes a failure due to the use of an invalid value.
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public  static final int ERROR_BAD_VALUE                       = -2;
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Denotes a failure due to the improper use of a method.
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public  static final int ERROR_INVALID_OPERATION               = -3;
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int ERROR_NATIVESETUP_AUDIOSYSTEM         = -16;
148a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent    private static final int ERROR_NATIVESETUP_INVALIDCHANNELMASK  = -17;
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int ERROR_NATIVESETUP_INVALIDFORMAT       = -18;
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int ERROR_NATIVESETUP_INVALIDSTREAMTYPE   = -19;
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int ERROR_NATIVESETUP_NATIVEINITFAILED    = -20;
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Events:
154e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten    // to keep in sync with frameworks/av/include/media/AudioTrack.h
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
156ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * Event id denotes when playback head has reached a previously set marker.
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int NATIVE_EVENT_MARKER  = 3;
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
160ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * Event id denotes when previously set update period has elapsed during playback.
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int NATIVE_EVENT_NEW_POS = 4;
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1641f61d01508651b4475397414e1fe06af1ab8fadaGlenn Kasten    private final static String TAG = "android.media.AudioTrack";
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1677ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi    /** @hide */
1687ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi    @IntDef({
1697ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi        WRITE_BLOCKING,
1707ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi        WRITE_NON_BLOCKING
1717ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi    })
1727ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi    @Retention(RetentionPolicy.SOURCE)
1737ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi    public @interface WriteMode {}
1747ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi
1757ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi    /**
1767ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi     * The write mode indicating the write operation will block until all data has been written,
1778b520c8f8e176f07ed496a171ddae75e66b3bc4fJean-Michel Trivi     * to be used in {@link #write(ByteBuffer, int, int)}
1787ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi     */
1797ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi    public final static int WRITE_BLOCKING = 0;
1807ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi    /**
1817ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi     * The write mode indicating the write operation will return immediately after
1827ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi     * queuing as much audio data for playback as possible without blocking, to be used in
1838b520c8f8e176f07ed496a171ddae75e66b3bc4fJean-Michel Trivi     * {@link #write(ByteBuffer, int, int)}.
1847ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi     */
1857ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi    public final static int WRITE_NON_BLOCKING = 1;
1867ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //--------------------------------------------------------------------------
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Member variables
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //--------------------
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
191ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * Indicates the state of the AudioTrack instance.
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mState = STATE_UNINITIALIZED;
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
195ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * Indicates the play state of the AudioTrack instance.
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mPlayState = PLAYSTATE_STOPPED;
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Lock to make sure mPlayState updates are reflecting the actual state of the object.
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Object mPlayStateLock = new Object();
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
203e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * Sizes of the native audio buffer.
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mNativeBufferSizeInBytes = 0;
206e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten    private int mNativeBufferSizeInFrames = 0;
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
20886fad47e68e344b19fabeab1156c5e6742d8dfadGlenn Kasten     * Handler for events coming from the native code.
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
21095bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten    private NativeEventHandlerDelegate mEventHandlerDelegate;
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
212ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * Looper associated with the thread that creates the AudioTrack instance.
213105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project     */
214b09707a041957f055cee3d290c85763cfef8d986Glenn Kasten    private final Looper mInitializationLooper;
215105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    /**
2168d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten     * The audio data source sampling rate in Hz.
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2185c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten    private int mSampleRate; // initialized by all constructors
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2203026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent     * The number of audio output channels (1 is mono, 2 is stereo).
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mChannelCount = 1;
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2243026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent     * The audio channel mask.
2253026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent     */
2263026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent    private int mChannels = AudioFormat.CHANNEL_OUT_MONO;
2273026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent
2283026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent    /**
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The type of the audio stream to play. See
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   {@link AudioManager#STREAM_VOICE_CALL}, {@link AudioManager#STREAM_SYSTEM},
2315c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten     *   {@link AudioManager#STREAM_RING}, {@link AudioManager#STREAM_MUSIC},
232b282e08ab641d4fc74d0324b7a0ce30926638dd5Glenn Kasten     *   {@link AudioManager#STREAM_ALARM}, {@link AudioManager#STREAM_NOTIFICATION}, and
233b282e08ab641d4fc74d0324b7a0ce30926638dd5Glenn Kasten     *   {@link AudioManager#STREAM_DTMF}.
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mStreamType = AudioManager.STREAM_MUSIC;
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
237e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * The way audio is consumed by the audio sink, streaming or static.
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mDataLoadMode = MODE_STREAM;
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
241ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * The current audio channel configuration.
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
243a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent    private int mChannelConfiguration = AudioFormat.CHANNEL_OUT_MONO;
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The encoding of the audio samples.
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see AudioFormat#ENCODING_PCM_8BIT
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see AudioFormat#ENCODING_PCM_16BIT
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
24954955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten    // add @see AudioFormat#ENCODING_PCM_FLOAT when @hide removed
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mAudioFormat = AudioFormat.ENCODING_PCM_16BIT;
251619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent    /**
252619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     * Audio session ID
253619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     */
25460bd67f7b1b85ed0ee19f77b056b90350a3d5343Glenn Kasten    private int mSessionId = AudioSystem.AUDIO_SESSION_ALLOCATE;
2551af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock    /**
2561af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock     * Reference to the app-ops service.
2571af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock     */
2581af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock    private final IAppOpsService mAppOps;
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //--------------------------------
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Used exclusively by native code
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //--------------------
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
264ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * Accessed by native methods: provides access to C++ AudioTrack object.
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @SuppressWarnings("unused")
267075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    private long mNativeTrackInJavaObj;
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Accessed by native methods: provides access to the JNI data (i.e. resources used by
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the native AudioTrack object, but not stored in it).
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @SuppressWarnings("unused")
273075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    private long mJniData;
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //--------------------------------------------------------------------------
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Constructor, Finalize
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //--------------------
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Class constructor.
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param streamType the type of the audio stream. See
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   {@link AudioManager#STREAM_VOICE_CALL}, {@link AudioManager#STREAM_SYSTEM},
2835c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten     *   {@link AudioManager#STREAM_RING}, {@link AudioManager#STREAM_MUSIC},
2845c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten     *   {@link AudioManager#STREAM_ALARM}, and {@link AudioManager#STREAM_NOTIFICATION}.
2858d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten     * @param sampleRateInHz the initial source sample rate expressed in Hz.
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param channelConfig describes the configuration of the audio channels.
287a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent     *   See {@link AudioFormat#CHANNEL_OUT_MONO} and
288a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent     *   {@link AudioFormat#CHANNEL_OUT_STEREO}
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param audioFormat the format in which the audio data is represented.
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   See {@link AudioFormat#ENCODING_PCM_16BIT} and
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   {@link AudioFormat#ENCODING_PCM_8BIT}
292e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * @param bufferSizeInBytes the total size (in bytes) of the internal buffer where audio data is
293e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     *   read from for playback.
294e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     *   If track's creation mode is {@link #MODE_STREAM}, you can write data into
295e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     *   this buffer in chunks less than or equal to this size, and it is typical to use
296e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     *   chunks of 1/2 of the total size to permit double-buffering.
297e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     *   If the track's creation mode is {@link #MODE_STATIC},
298e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     *   this is the maximum length sample, or audio clip, that can be played by this instance.
299ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     *   See {@link #getMinBufferSize(int, int, int)} to determine the minimum required buffer size
300ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     *   for the successful creation of an AudioTrack instance in streaming mode. Using values
301ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     *   smaller than getMinBufferSize() will result in an initialization failure.
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param mode streaming or static buffer. See {@link #MODE_STATIC} and {@link #MODE_STREAM}
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws java.lang.IllegalArgumentException
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
30554955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten    // add {@link AudioFormat#ENCODING_PCM_FLOAT} to audioFormat section above, when @hide removed
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat,
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int bufferSizeInBytes, int mode)
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    throws IllegalArgumentException {
309619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent        this(streamType, sampleRateInHz, channelConfig, audioFormat,
31060bd67f7b1b85ed0ee19f77b056b90350a3d5343Glenn Kasten                bufferSizeInBytes, mode, AudioSystem.AUDIO_SESSION_ALLOCATE);
311619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent    }
312619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent
313619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent    /**
314619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     * Class constructor with audio session. Use this constructor when the AudioTrack must be
315619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     * attached to a particular audio session. The primary use of the audio session ID is to
316619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     * associate audio effects to a particular instance of AudioTrack: if an audio session ID
317619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     * is provided when creating an AudioEffect, this effect will be applied only to audio tracks
318619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     * and media players in the same session and not to the output mix.
319619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     * When an AudioTrack is created without specifying a session, it will create its own session
3208d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten     * which can be retrieved by calling the {@link #getAudioSessionId()} method.
3215c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten     * If a non-zero session ID is provided, this AudioTrack will share effects attached to this
3225c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten     * session
3235c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten     * with all other media players or audio tracks in the same session, otherwise a new session
3245c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten     * will be created for this track if none is supplied.
325619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     * @param streamType the type of the audio stream. See
326619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     *   {@link AudioManager#STREAM_VOICE_CALL}, {@link AudioManager#STREAM_SYSTEM},
3275c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten     *   {@link AudioManager#STREAM_RING}, {@link AudioManager#STREAM_MUSIC},
3285c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten     *   {@link AudioManager#STREAM_ALARM}, and {@link AudioManager#STREAM_NOTIFICATION}.
3298d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten     * @param sampleRateInHz the initial source sample rate expressed in Hz.
330619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     * @param channelConfig describes the configuration of the audio channels.
331619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     *   See {@link AudioFormat#CHANNEL_OUT_MONO} and
332619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     *   {@link AudioFormat#CHANNEL_OUT_STEREO}
333619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     * @param audioFormat the format in which the audio data is represented.
334619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     *   See {@link AudioFormat#ENCODING_PCM_16BIT} and
335619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     *   {@link AudioFormat#ENCODING_PCM_8BIT}
336619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     * @param bufferSizeInBytes the total size (in bytes) of the buffer where audio data is read
337619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     *   from for playback. If using the AudioTrack in streaming mode, you can write data into
338619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     *   this buffer in smaller chunks than this size. If using the AudioTrack in static mode,
339619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     *   this is the maximum size of the sound that will be played for this instance.
340619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     *   See {@link #getMinBufferSize(int, int, int)} to determine the minimum required buffer size
341619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     *   for the successful creation of an AudioTrack instance in streaming mode. Using values
342619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     *   smaller than getMinBufferSize() will result in an initialization failure.
343619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     * @param mode streaming or static buffer. See {@link #MODE_STATIC} and {@link #MODE_STREAM}
344619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     * @param sessionId Id of audio session the AudioTrack must be attached to
345619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     * @throws java.lang.IllegalArgumentException
346619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     */
34754955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten    // add {@link AudioFormat#ENCODING_PCM_FLOAT} to audioFormat section above, when @hide removed
348619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent    public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat,
349619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent            int bufferSizeInBytes, int mode, int sessionId)
350619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent    throws IllegalArgumentException {
351a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten        // mState already == STATE_UNINITIALIZED
3525c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten
3535c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten        // remember which looper is associated with the AudioTrack instantiation
354b09707a041957f055cee3d290c85763cfef8d986Glenn Kasten        Looper looper;
355b09707a041957f055cee3d290c85763cfef8d986Glenn Kasten        if ((looper = Looper.myLooper()) == null) {
356b09707a041957f055cee3d290c85763cfef8d986Glenn Kasten            looper = Looper.getMainLooper();
357105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
358b09707a041957f055cee3d290c85763cfef8d986Glenn Kasten        mInitializationLooper = looper;
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        audioParamCheck(streamType, sampleRateInHz, channelConfig, audioFormat, mode);
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        audioBuffSizeCheck(bufferSizeInBytes);
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3641af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock        IBinder b = ServiceManager.getService(Context.APP_OPS_SERVICE);
3651af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock        mAppOps = IAppOpsService.Stub.asInterface(b);
3661af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock
367619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent        if (sessionId < 0) {
368f4e58051e22ad4e21c7cd436c37cc5665c194d1cGlenn Kasten            throw new IllegalArgumentException("Invalid audio session ID: "+sessionId);
369619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent        }
370619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent
371619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent        int[] session = new int[1];
372619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent        session[0] = sessionId;
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // native initialization
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int initResult = native_setup(new WeakReference<AudioTrack>(this),
3753026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent                mStreamType, mSampleRate, mChannels, mAudioFormat,
376619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent                mNativeBufferSizeInBytes, mDataLoadMode, session);
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (initResult != SUCCESS) {
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            loge("Error code "+initResult+" when initializing AudioTrack.");
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return; // with mState == STATE_UNINITIALIZED
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
382619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent        mSessionId = session[0];
383619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDataLoadMode == MODE_STATIC) {
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mState = STATE_NO_STATIC_DATA;
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mState = STATE_INITIALIZED;
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3911b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi    // mask of all the channels supported by this implementation
3921b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi    private static final int SUPPORTED_OUT_CHANNELS =
3931b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi            AudioFormat.CHANNEL_OUT_FRONT_LEFT |
3941b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi            AudioFormat.CHANNEL_OUT_FRONT_RIGHT |
3951b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi            AudioFormat.CHANNEL_OUT_FRONT_CENTER |
3961b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi            AudioFormat.CHANNEL_OUT_LOW_FREQUENCY |
3971b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi            AudioFormat.CHANNEL_OUT_BACK_LEFT |
3981b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi            AudioFormat.CHANNEL_OUT_BACK_RIGHT |
3991b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi            AudioFormat.CHANNEL_OUT_BACK_CENTER;
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Convenience method for the constructor's parameter checks.
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // This is where constructor IllegalArgumentException-s are thrown
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // postconditions:
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //    mStreamType is valid
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //    mChannelCount is valid
4063026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent    //    mChannels is valid
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //    mAudioFormat is valid
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //    mSampleRate is valid
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //    mDataLoadMode is valid
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void audioParamCheck(int streamType, int sampleRateInHz,
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                 int channelConfig, int audioFormat, int mode) {
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //--------------
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // stream type
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if( (streamType != AudioManager.STREAM_ALARM) && (streamType != AudioManager.STREAM_MUSIC)
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project           && (streamType != AudioManager.STREAM_RING) && (streamType != AudioManager.STREAM_SYSTEM)
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project           && (streamType != AudioManager.STREAM_VOICE_CALL)
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project           && (streamType != AudioManager.STREAM_NOTIFICATION)
419a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent           && (streamType != AudioManager.STREAM_BLUETOOTH_SCO)
420a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent           && (streamType != AudioManager.STREAM_DTMF)) {
421f4e58051e22ad4e21c7cd436c37cc5665c194d1cGlenn Kasten            throw new IllegalArgumentException("Invalid stream type.");
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
423896a7f5fee46c24d31e9403abdf5813e4bb84ca5Glenn Kasten        mStreamType = streamType;
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //--------------
4265c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten        // sample rate, note these values are subject to change
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ( (sampleRateInHz < 4000) || (sampleRateInHz > 48000) ) {
428f4e58051e22ad4e21c7cd436c37cc5665c194d1cGlenn Kasten            throw new IllegalArgumentException(sampleRateInHz
429f4e58051e22ad4e21c7cd436c37cc5665c194d1cGlenn Kasten                    + "Hz is not a supported sample rate.");
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
431896a7f5fee46c24d31e9403abdf5813e4bb84ca5Glenn Kasten        mSampleRate = sampleRateInHz;
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //--------------
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // channel config
4353026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent        mChannelConfiguration = channelConfig;
4363026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (channelConfig) {
4383026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent        case AudioFormat.CHANNEL_OUT_DEFAULT: //AudioFormat.CHANNEL_CONFIGURATION_DEFAULT
439a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent        case AudioFormat.CHANNEL_OUT_MONO:
4403026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent        case AudioFormat.CHANNEL_CONFIGURATION_MONO:
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mChannelCount = 1;
4423026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent            mChannels = AudioFormat.CHANNEL_OUT_MONO;
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
444a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent        case AudioFormat.CHANNEL_OUT_STEREO:
4453026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent        case AudioFormat.CHANNEL_CONFIGURATION_STEREO:
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mChannelCount = 2;
4473026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent            mChannels = AudioFormat.CHANNEL_OUT_STEREO;
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        default:
450d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi            if (!isMultichannelConfigSupported(channelConfig)) {
4511b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi                // input channel configuration features unsupported channels
452f4e58051e22ad4e21c7cd436c37cc5665c194d1cGlenn Kasten                throw new IllegalArgumentException("Unsupported channel configuration.");
4531b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi            }
454896a7f5fee46c24d31e9403abdf5813e4bb84ca5Glenn Kasten            mChannels = channelConfig;
455896a7f5fee46c24d31e9403abdf5813e4bb84ca5Glenn Kasten            mChannelCount = Integer.bitCount(channelConfig);
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //--------------
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // audio format
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (audioFormat) {
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case AudioFormat.ENCODING_DEFAULT:
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mAudioFormat = AudioFormat.ENCODING_PCM_16BIT;
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case AudioFormat.ENCODING_PCM_16BIT:
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case AudioFormat.ENCODING_PCM_8BIT:
46654955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten        case AudioFormat.ENCODING_PCM_FLOAT:
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mAudioFormat = audioFormat;
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        default:
470f4e58051e22ad4e21c7cd436c37cc5665c194d1cGlenn Kasten            throw new IllegalArgumentException("Unsupported sample encoding."
47154955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten                + " Should be ENCODING_PCM_8BIT or ENCODING_PCM_16BIT"
47254955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten             // + " or ENCODING_PCM_FLOAT" when @hide removed
47354955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten                + ".");
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //--------------
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // audio load mode
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ( (mode != MODE_STREAM) && (mode != MODE_STATIC) ) {
479f4e58051e22ad4e21c7cd436c37cc5665c194d1cGlenn Kasten            throw new IllegalArgumentException("Invalid mode.");
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
481896a7f5fee46c24d31e9403abdf5813e4bb84ca5Glenn Kasten        mDataLoadMode = mode;
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
484d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi    /**
485d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi     * Convenience method to check that the channel configuration (a.k.a channel mask) is supported
486d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi     * @param channelConfig the mask to validate
487d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi     * @return false if the AudioTrack can't be used with such a mask
488d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi     */
489d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi    private static boolean isMultichannelConfigSupported(int channelConfig) {
490d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi        // check for unsupported channels
491d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi        if ((channelConfig & SUPPORTED_OUT_CHANNELS) != channelConfig) {
4921f61d01508651b4475397414e1fe06af1ab8fadaGlenn Kasten            loge("Channel configuration features unsupported channels");
493d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi            return false;
494d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi        }
495d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi        // check for unsupported multichannel combinations:
496d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi        // - FL/FR must be present
497d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi        // - L/R channels must be paired (e.g. no single L channel)
498d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi        final int frontPair =
499d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi                AudioFormat.CHANNEL_OUT_FRONT_LEFT | AudioFormat.CHANNEL_OUT_FRONT_RIGHT;
500d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi        if ((channelConfig & frontPair) != frontPair) {
5011f61d01508651b4475397414e1fe06af1ab8fadaGlenn Kasten                loge("Front channels must be present in multichannel configurations");
502d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi                return false;
503d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi        }
504d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi        final int backPair =
505d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi                AudioFormat.CHANNEL_OUT_BACK_LEFT | AudioFormat.CHANNEL_OUT_BACK_RIGHT;
506d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi        if ((channelConfig & backPair) != 0) {
507d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi            if ((channelConfig & backPair) != backPair) {
5081f61d01508651b4475397414e1fe06af1ab8fadaGlenn Kasten                loge("Rear channels can't be used independently");
509d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi                return false;
510d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi            }
511d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi        }
512d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi        return true;
513d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi    }
514d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
516e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten    // Convenience method for the constructor's audio buffer size check.
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // preconditions:
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //    mChannelCount is valid
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //    mAudioFormat is valid
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // postcondition:
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //    mNativeBufferSizeInBytes is valid (multiple of frame size, positive)
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void audioBuffSizeCheck(int audioBufferSize) {
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // NB: this section is only valid with PCM data.
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //     To update when supporting compressed formats
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int frameSizeInBytes = mChannelCount
52634a37bdebb3d606dac7c7d1dd7a0effdb59bd3d6Glenn Kasten                * (AudioFormat.getBytesPerSample(mAudioFormat));
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((audioBufferSize % frameSizeInBytes != 0) || (audioBufferSize < 1)) {
528f4e58051e22ad4e21c7cd436c37cc5665c194d1cGlenn Kasten            throw new IllegalArgumentException("Invalid audio buffer size.");
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNativeBufferSizeInBytes = audioBufferSize;
532e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten        mNativeBufferSizeInFrames = audioBufferSize / frameSizeInBytes;
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Releases the native AudioTrack resources.
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void release() {
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // even though native_release() stops the native AudioTrack, we need to stop
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // AudioTrack subclasses too.
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            stop();
544fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten        } catch(IllegalStateException ise) {
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // don't raise an exception, we're releasing the resources.
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        native_release();
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mState = STATE_UNINITIALIZED;
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void finalize() {
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        native_finalize();
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //--------------------------------------------------------------------------
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Getters
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //--------------------
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
56078cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * Returns the minimum gain value, which is the constant 0.0.
56178cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * Gain values less than 0.0 will be clamped to 0.0.
56278cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * <p>The word "volume" in the API name is historical; this is actually a linear gain.
56378cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * @return the minimum value, which is the constant 0.0.
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static public float getMinVolume() {
56678cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten        return GAIN_MIN;
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
57078cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * Returns the maximum gain value, which is greater than or equal to 1.0.
57178cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * Gain values greater than the maximum will be clamped to the maximum.
57278cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * <p>The word "volume" in the API name is historical; this is actually a gain.
57378cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * expressed as a linear multiplier on sample values, where a maximum value of 1.0
57478cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * corresponds to a gain of 0 dB (sample values left unmodified).
57578cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * @return the maximum value, which is greater than or equal to 1.0.
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static public float getMaxVolume() {
57878cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten        return GAIN_MAX;
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the configured audio data sample rate in Hz
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getSampleRate() {
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mSampleRate;
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
587fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
58988e209dcf8c2ebddda5c272f46d1bd5478bc639cEric Laurent     * Returns the current playback rate in Hz.
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getPlaybackRate() {
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return native_get_playback_rate();
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the configured audio data format. See {@link AudioFormat#ENCODING_PCM_16BIT}
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * and {@link AudioFormat#ENCODING_PCM_8BIT}.
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getAudioFormat() {
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mAudioFormat;
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the type of audio stream this AudioTrack is configured for.
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Compare the result against {@link AudioManager#STREAM_VOICE_CALL},
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link AudioManager#STREAM_SYSTEM}, {@link AudioManager#STREAM_RING},
6075c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten     * {@link AudioManager#STREAM_MUSIC}, {@link AudioManager#STREAM_ALARM},
608b282e08ab641d4fc74d0324b7a0ce30926638dd5Glenn Kasten     * {@link AudioManager#STREAM_NOTIFICATION}, or {@link AudioManager#STREAM_DTMF}.
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getStreamType() {
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mStreamType;
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the configured channel configuration.
616a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent     * See {@link AudioFormat#CHANNEL_OUT_MONO}
617a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent     * and {@link AudioFormat#CHANNEL_OUT_STEREO}.
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getChannelConfiguration() {
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mChannelConfiguration;
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the configured number of channels.
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getChannelCount() {
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mChannelCount;
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the state of the AudioTrack instance. This is useful after the
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * AudioTrack instance has been created to check if it was initialized
633e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * properly. This ensures that the appropriate resources have been acquired.
634ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * @see #STATE_INITIALIZED
635ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * @see #STATE_NO_STATIC_DATA
636ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * @see #STATE_UNINITIALIZED
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getState() {
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mState;
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the playback state of the AudioTrack instance.
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #PLAYSTATE_STOPPED
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #PLAYSTATE_PAUSED
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #PLAYSTATE_PLAYING
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getPlayState() {
64906e0333c7eb50533cc6e0f7b61812d2840844296Narayan Kamath        synchronized (mPlayStateLock) {
65006e0333c7eb50533cc6e0f7b61812d2840844296Narayan Kamath            return mPlayState;
65106e0333c7eb50533cc6e0f7b61812d2840844296Narayan Kamath        }
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
655e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     *  Returns the "native frame count", derived from the bufferSizeInBytes specified at
656e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     *  creation time and converted to frame units.
657e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     *  If track's creation mode is {@link #MODE_STATIC},
658e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     *  it is equal to the specified bufferSizeInBytes converted to frame units.
659e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     *  If track's creation mode is {@link #MODE_STREAM},
660e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     *  it is typically greater than or equal to the specified bufferSizeInBytes converted to frame
661e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     *  units; it may be rounded up to a larger value if needed by the target device implementation.
66255a3218f242a611afb3569d88970c0c5dbf8ce54Glenn Kasten     *  @deprecated Only accessible by subclasses, which are not recommended for AudioTrack.
66355a3218f242a611afb3569d88970c0c5dbf8ce54Glenn Kasten     *  See {@link AudioManager#getProperty(String)} for key
66455a3218f242a611afb3569d88970c0c5dbf8ce54Glenn Kasten     *  {@link AudioManager#PROPERTY_OUTPUT_FRAMES_PER_BUFFER}.
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
66655a3218f242a611afb3569d88970c0c5dbf8ce54Glenn Kasten    @Deprecated
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected int getNativeFrameCount() {
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return native_get_native_frame_count();
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
672ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * Returns marker position expressed in frames.
673e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * @return marker position in wrapping frame units similar to {@link #getPlaybackHeadPosition},
674e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * or zero if marker is disabled.
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getNotificationMarkerPosition() {
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return native_get_marker_pos();
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
681ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * Returns the notification update period expressed in frames.
682e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * Zero means that no position update notifications are being delivered.
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getPositionNotificationPeriod() {
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return native_get_pos_update_period();
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
689e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * Returns the playback head position expressed in frames.
690e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * Though the "int" type is signed 32-bits, the value should be reinterpreted as if it is
691e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * unsigned 32-bits.  That is, the next position after 0x7FFFFFFF is (int) 0x80000000.
692e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * This is a continuously advancing counter.  It will wrap (overflow) periodically,
693e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * for example approximately once every 27:03:11 hours:minutes:seconds at 44.1 kHz.
694e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * It is reset to zero by flush(), reload(), and stop().
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getPlaybackHeadPosition() {
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return native_get_position();
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
70161dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman     * Returns this track's estimated latency in milliseconds. This includes the latency due
70261dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman     * to AudioTrack buffer size, AudioMixer (if any) and audio hardware driver.
70361dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman     *
70461dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman     * DO NOT UNHIDE. The existing approach for doing A/V sync has too many problems. We need
70561dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman     * a better solution.
70661dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman     * @hide
70761dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman     */
70861dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman    public int getLatency() {
70961dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman        return native_get_latency();
71061dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman    }
71161dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman
71261dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman    /**
713e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     *  Returns the output sample rate in Hz for the specified stream type.
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static public int getNativeOutputSampleRate(int streamType) {
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return native_get_output_sample_rate(streamType);
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
718fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the minimum buffer size required for the successful creation of an AudioTrack
721ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * object to be created in the {@link #MODE_STREAM} mode. Note that this size doesn't
722ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * guarantee a smooth playback under load, and higher values should be chosen according to
723fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten     * the expected frequency at which the buffer will be refilled with additional data to play.
7248d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten     * For example, if you intend to dynamically set the source sample rate of an AudioTrack
7258d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten     * to a higher value than the initial source sample rate, be sure to configure the buffer size
7268d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten     * based on the highest planned sample rate.
7278d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten     * @param sampleRateInHz the source sample rate expressed in Hz.
728fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten     * @param channelConfig describes the configuration of the audio channels.
729a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent     *   See {@link AudioFormat#CHANNEL_OUT_MONO} and
730a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent     *   {@link AudioFormat#CHANNEL_OUT_STEREO}
731fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten     * @param audioFormat the format in which the audio data is represented.
732fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten     *   See {@link AudioFormat#ENCODING_PCM_16BIT} and
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   {@link AudioFormat#ENCODING_PCM_8BIT}
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return {@link #ERROR_BAD_VALUE} if an invalid parameter was passed,
735e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     *   or {@link #ERROR} if unable to query for output properties,
736ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     *   or the minimum buffer size expressed in bytes.
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
73854955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten    // add {@link AudioFormat#ENCODING_PCM_FLOAT} to audioFormat section above, when @hide removed
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static public int getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat) {
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int channelCount = 0;
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch(channelConfig) {
742a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent        case AudioFormat.CHANNEL_OUT_MONO:
7433026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent        case AudioFormat.CHANNEL_CONFIGURATION_MONO:
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            channelCount = 1;
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
746a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent        case AudioFormat.CHANNEL_OUT_STEREO:
7473026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent        case AudioFormat.CHANNEL_CONFIGURATION_STEREO:
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            channelCount = 2;
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        default:
7511b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi            if ((channelConfig & SUPPORTED_OUT_CHANNELS) != channelConfig) {
7521b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi                // input channel configuration features unsupported channels
7531b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi                loge("getMinBufferSize(): Invalid channel configuration.");
754df3cb5279857cac41909643c6703e8fc1621fad1Glenn Kasten                return ERROR_BAD_VALUE;
7551b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi            } else {
7561b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi                channelCount = Integer.bitCount(channelConfig);
7571b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi            }
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
759fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten
760fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten        if ((audioFormat != AudioFormat.ENCODING_PCM_16BIT)
76154955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten            && (audioFormat != AudioFormat.ENCODING_PCM_8BIT)
76254955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten            && (audioFormat != AudioFormat.ENCODING_PCM_FLOAT)) {
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            loge("getMinBufferSize(): Invalid audio format.");
764df3cb5279857cac41909643c6703e8fc1621fad1Glenn Kasten            return ERROR_BAD_VALUE;
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
766fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten
7675c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten        // sample rate, note these values are subject to change
768ad67c9546494a7c4d9336b57889a7c19a7dbb945Glenn Kasten        if ( (sampleRateInHz < SAMPLE_RATE_HZ_MIN) || (sampleRateInHz > SAMPLE_RATE_HZ_MAX) ) {
769ad67c9546494a7c4d9336b57889a7c19a7dbb945Glenn Kasten            loge("getMinBufferSize(): " + sampleRateInHz + " Hz is not a supported sample rate.");
770df3cb5279857cac41909643c6703e8fc1621fad1Glenn Kasten            return ERROR_BAD_VALUE;
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
772fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int size = native_get_min_buff_size(sampleRateInHz, channelCount, audioFormat);
774a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten        if (size <= 0) {
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            loge("getMinBufferSize(): error querying hardware");
776df3cb5279857cac41909643c6703e8fc1621fad1Glenn Kasten            return ERROR;
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        else {
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return size;
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
783619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent    /**
784619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     * Returns the audio session ID.
785619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     *
786619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     * @return the ID of the audio session this AudioTrack belongs to.
787619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent     */
788619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent    public int getAudioSessionId() {
789619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent        return mSessionId;
790619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent    }
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
792948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten   /**
793948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    * Poll for a timestamp on demand.
794948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    *
7955e8f278f083f6a75cb6d1b09671c335156f93d1bGlenn Kasten    * Use if you need to get the most recent timestamp outside of the event callback handler.
796948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    * Calling this method too often may be inefficient;
797948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    * if you need a high-resolution mapping between frame position and presentation time,
798948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    * consider implementing that at application level, based on low-resolution timestamps.
799948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    * The audio data at the returned position may either already have been
800948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    * presented, or may have not yet been presented but is committed to be presented.
801948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    * It is not possible to request the time corresponding to a particular position,
802948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    * or to request the (fractional) position corresponding to a particular time.
803948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    * If you need such features, consider implementing them at application level.
804948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    *
805948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    * @param timestamp a reference to a non-null AudioTimestamp instance allocated
806596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten    *        and owned by caller.
807596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten    * @return true if a timestamp is available, or false if no timestamp is available.
808596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten    *         If a timestamp if available,
809948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    *         the AudioTimestamp instance is filled in with a position in frame units, together
810948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    *         with the estimated time when that frame was presented or is committed to
811948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    *         be presented.
812948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    *         In the case that no timestamp is available, any supplied instance is left unaltered.
813948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    */
814596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten    public boolean getTimestamp(AudioTimestamp timestamp)
815948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    {
816596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten        if (timestamp == null) {
817596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten            throw new IllegalArgumentException();
818596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten        }
819948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten        // It's unfortunate, but we have to either create garbage every time or use synchronized
820948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten        long[] longArray = new long[2];
821948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten        int ret = native_get_timestamp(longArray);
822596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten        if (ret != SUCCESS) {
823596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten            return false;
824948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten        }
825596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten        timestamp.framePosition = longArray[0];
826596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten        timestamp.nanoTime = longArray[1];
827596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten        return true;
828948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    }
829948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten
830948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //--------------------------------------------------------------------------
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Initialization / configuration
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //--------------------
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8354df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     * Sets the listener the AudioTrack notifies when a previously set marker is reached or
8364df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     * for each periodic playback head position update.
837ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * Notifications will be received in the same thread as the one in which the AudioTrack
838ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * instance was created.
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param listener
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8414df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    public void setPlaybackPositionUpdateListener(OnPlaybackPositionUpdateListener listener) {
8424df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        setPlaybackPositionUpdateListener(listener, null);
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
844fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten
845ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi    /**
846ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * Sets the listener the AudioTrack notifies when a previously set marker is reached or
847ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * for each periodic playback head position update.
848ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * Use this method to receive AudioTrack events in the Handler associated with another
849ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * thread than the one in which you created the AudioTrack instance.
850ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * @param listener
851ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * @param handler the Handler that will receive the event notification messages.
852ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     */
853fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten    public void setPlaybackPositionUpdateListener(OnPlaybackPositionUpdateListener listener,
8544df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                                                    Handler handler) {
8554df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        if (listener != null) {
85695bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten            mEventHandlerDelegate = new NativeEventHandlerDelegate(this, listener, handler);
85795bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten        } else {
85895bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten            mEventHandlerDelegate = null;
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
86378cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten    private static float clampGainOrLevel(float gainOrLevel) {
86478cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten        if (Float.isNaN(gainOrLevel)) {
86578cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten            throw new IllegalArgumentException();
86678cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten        }
86778cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten        if (gainOrLevel < GAIN_MIN) {
86878cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten            gainOrLevel = GAIN_MIN;
86978cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten        } else if (gainOrLevel > GAIN_MAX) {
87078cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten            gainOrLevel = GAIN_MAX;
87178cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten        }
87278cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten        return gainOrLevel;
87378cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten    }
87478cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten
8754df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     /**
87778cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * Sets the specified left and right output gain values on the AudioTrack.
87878cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * <p>Gain values are clamped to the closed interval [0.0, max] where
87978cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * max is the value of {@link #getMaxVolume}.
88078cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * A value of 0.0 results in zero gain (silence), and
88178cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * a value of 1.0 means unity gain (signal unchanged).
88278cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * The default value is 1.0 meaning unity gain.
88378cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * <p>The word "volume" in the API name is historical; this is actually a linear gain.
88478cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * @param leftGain output gain for the left channel.
88578cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * @param rightGain output gain for the right channel
8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return error code or success, see {@link #SUCCESS},
8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *    {@link #ERROR_INVALID_OPERATION}
88878cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * @deprecated Applications should use {@link #setVolume} instead, as it
88978cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * more gracefully scales down to mono, and up to multi-channel content beyond stereo.
8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
89178cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten    public int setStereoVolume(float leftGain, float rightGain) {
8921af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock        if (isRestricted()) {
8931af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock            return SUCCESS;
8941af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock        }
8953b4df62704a6184878afd9272830cf3db7bd2d66Glenn Kasten        if (mState == STATE_UNINITIALIZED) {
8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ERROR_INVALID_OPERATION;
8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
89978cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten        leftGain = clampGainOrLevel(leftGain);
90078cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten        rightGain = clampGainOrLevel(rightGain);
9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
90278cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten        native_setVolume(leftGain, rightGain);
9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return SUCCESS;
9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
90978cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * Sets the specified output gain value on all channels of this track.
91078cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * <p>Gain values are clamped to the closed interval [0.0, max] where
91178cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * max is the value of {@link #getMaxVolume}.
91278cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * A value of 0.0 results in zero gain (silence), and
91378cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * a value of 1.0 means unity gain (signal unchanged).
91478cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * The default value is 1.0 meaning unity gain.
91578cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * <p>This API is preferred over {@link #setStereoVolume}, as it
91678cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * more gracefully scales down to mono, and up to multi-channel content beyond stereo.
91778cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * <p>The word "volume" in the API name is historical; this is actually a linear gain.
91878cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * @param gain output gain for all channels.
9193e21cc8140e42bdcd924590e5e12446b6c55ad2aGlenn Kasten     * @return error code or success, see {@link #SUCCESS},
9203e21cc8140e42bdcd924590e5e12446b6c55ad2aGlenn Kasten     *    {@link #ERROR_INVALID_OPERATION}
921068225de0197df07a0247b2877666ea91c22c992Glenn Kasten     */
92278cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten    public int setVolume(float gain) {
92378cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten        return setStereoVolume(gain, gain);
924068225de0197df07a0247b2877666ea91c22c992Glenn Kasten    }
925068225de0197df07a0247b2877666ea91c22c992Glenn Kasten
926068225de0197df07a0247b2877666ea91c22c992Glenn Kasten
927068225de0197df07a0247b2877666ea91c22c992Glenn Kasten    /**
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the playback sample rate for this track. This sets the sampling rate at which
9298d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten     * the audio data will be consumed and played back
9308d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten     * (as set by the sampleRateInHz parameter in the
9318d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten     * {@link #AudioTrack(int, int, int, int, int, int)} constructor),
9328d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten     * not the original sampling rate of the
933e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * content. For example, setting it to half the sample rate of the content will cause the
934e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * playback to last twice as long, but will also result in a pitch shift down by one octave.
935e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * The valid sample rate range is from 1 Hz to twice the value returned by
93688e209dcf8c2ebddda5c272f46d1bd5478bc639cEric Laurent     * {@link #getNativeOutputSampleRate(int)}.
937ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * @param sampleRateInHz the sample rate expressed in Hz
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE},
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *    {@link #ERROR_INVALID_OPERATION}
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int setPlaybackRate(int sampleRateInHz) {
942f19395db6343efdf80d064e0ba7c3b9aa4dbae75Glenn Kasten        if (mState != STATE_INITIALIZED) {
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ERROR_INVALID_OPERATION;
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (sampleRateInHz <= 0) {
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ERROR_BAD_VALUE;
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
94888e209dcf8c2ebddda5c272f46d1bd5478bc639cEric Laurent        return native_set_playback_rate(sampleRateInHz);
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
953e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * Sets the position of the notification marker.  At most one marker can be active.
954e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * @param markerInFrames marker position in wrapping frame units similar to
955e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * {@link #getPlaybackHeadPosition}, or zero to disable the marker.
956e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * To set a marker at a position which would appear as zero due to wraparound,
957e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * a workaround is to use a non-zero position near zero, such as -1 or 1.
9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE},
9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *  {@link #ERROR_INVALID_OPERATION}
9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int setNotificationMarkerPosition(int markerInFrames) {
9623b4df62704a6184878afd9272830cf3db7bd2d66Glenn Kasten        if (mState == STATE_UNINITIALIZED) {
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ERROR_INVALID_OPERATION;
9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return native_set_marker_pos(markerInFrames);
9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
970ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * Sets the period for the periodic notification event.
971ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * @param periodInFrames update period expressed in frames
9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_INVALID_OPERATION}
9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int setPositionNotificationPeriod(int periodInFrames) {
9753b4df62704a6184878afd9272830cf3db7bd2d66Glenn Kasten        if (mState == STATE_UNINITIALIZED) {
9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ERROR_INVALID_OPERATION;
9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return native_set_pos_update_period(periodInFrames);
9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
983a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten     * Sets the playback head position.
984a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten     * The track must be stopped or paused for the position to be changed,
985a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten     * and must use the {@link #MODE_STATIC} mode.
986ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * @param positionInFrames playback head position expressed in frames
987e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * Zero corresponds to start of buffer.
988e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * The position must not be greater than the buffer size in frames, or negative.
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE},
9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *    {@link #ERROR_INVALID_OPERATION}
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int setPlaybackHeadPosition(int positionInFrames) {
993a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten        if (mDataLoadMode == MODE_STREAM || mState != STATE_INITIALIZED ||
994a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten                getPlayState() == PLAYSTATE_PLAYING) {
995a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten            return ERROR_INVALID_OPERATION;
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
997e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten        if (!(0 <= positionInFrames && positionInFrames <= mNativeBufferSizeInFrames)) {
998e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten            return ERROR_BAD_VALUE;
999e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten        }
1000a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten        return native_set_position(positionInFrames);
10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the loop points and the loop count. The loop can be infinite.
1005a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten     * Similarly to setPlaybackHeadPosition,
1006e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * the track must be stopped or paused for the loop points to be changed,
1007a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten     * and must use the {@link #MODE_STATIC} mode.
1008ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * @param startInFrames loop start marker expressed in frames
1009e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * Zero corresponds to start of buffer.
1010e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * The start marker must not be greater than or equal to the buffer size in frames, or negative.
1011ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * @param endInFrames loop end marker expressed in frames
1012e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * The total buffer size in frames corresponds to end of buffer.
1013e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * The end marker must not be greater than the buffer size in frames.
1014e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * For looping, the end marker must not be less than or equal to the start marker,
1015e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * but to disable looping
1016e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * it is permitted for start marker, end marker, and loop count to all be 0.
10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param loopCount the number of times the loop is looped.
1018e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     *    A value of -1 means infinite looping, and 0 disables looping.
10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE},
10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *    {@link #ERROR_INVALID_OPERATION}
10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int setLoopPoints(int startInFrames, int endInFrames, int loopCount) {
1023a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten        if (mDataLoadMode == MODE_STREAM || mState != STATE_INITIALIZED ||
1024a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten                getPlayState() == PLAYSTATE_PLAYING) {
10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ERROR_INVALID_OPERATION;
10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1027e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten        if (loopCount == 0) {
1028e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten            ;   // explicitly allowed as an exception to the loop region range check
1029e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten        } else if (!(0 <= startInFrames && startInFrames < mNativeBufferSizeInFrames &&
1030e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten                startInFrames < endInFrames && endInFrames <= mNativeBufferSizeInFrames)) {
1031e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten            return ERROR_BAD_VALUE;
1032e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten        }
10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return native_set_loop(startInFrames, endInFrames, loopCount);
10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
103755a3218f242a611afb3569d88970c0c5dbf8ce54Glenn Kasten     * Sets the initialization state of the instance. This method was originally intended to be used
103855a3218f242a611afb3569d88970c0c5dbf8ce54Glenn Kasten     * in an AudioTrack subclass constructor to set a subclass-specific post-initialization state.
103955a3218f242a611afb3569d88970c0c5dbf8ce54Glenn Kasten     * However, subclasses of AudioTrack are no longer recommended, so this method is obsolete.
10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param state the state of the AudioTrack instance
104155a3218f242a611afb3569d88970c0c5dbf8ce54Glenn Kasten     * @deprecated Only accessible by subclasses, which are not recommended for AudioTrack.
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
104355a3218f242a611afb3569d88970c0c5dbf8ce54Glenn Kasten    @Deprecated
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void setState(int state) {
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mState = state;
10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //---------------------------------------------------------
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Transport control methods
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //--------------------
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Starts playing an AudioTrack.
1054e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * If track's creation mode is {@link #MODE_STATIC}, you must have called write() prior.
105588bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath     *
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalStateException
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void play()
10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    throws IllegalStateException {
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mState != STATE_INITIALIZED) {
1061f4e58051e22ad4e21c7cd436c37cc5665c194d1cGlenn Kasten            throw new IllegalStateException("play() called on uninitialized AudioTrack.");
10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10631af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock        if (isRestricted()) {
10641af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock            setVolume(0);
10651af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock        }
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized(mPlayStateLock) {
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            native_start();
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPlayState = PLAYSTATE_PLAYING;
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10721af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock    private boolean isRestricted() {
10731af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock        try {
10741af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock            final int mode = mAppOps.checkAudioOperation(AppOpsManager.OP_PLAY_AUDIO, mStreamType,
10751af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock                    Process.myUid(), ActivityThread.currentPackageName());
10761af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock            return mode != AppOpsManager.MODE_ALLOWED;
10771af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock        } catch (RemoteException e) {
10781af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock            return false;
10791af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock        }
10801af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock    }
10811af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Stops playing the audio data.
1084a701da8ebabb3d63ac57b7718055698abb21804aJean-Michel Trivi     * When used on an instance created in {@link #MODE_STREAM} mode, audio will stop playing
1085a701da8ebabb3d63ac57b7718055698abb21804aJean-Michel Trivi     * after the last buffer that was written has been played. For an immediate stop, use
1086a701da8ebabb3d63ac57b7718055698abb21804aJean-Michel Trivi     * {@link #pause()}, followed by {@link #flush()} to discard audio data that hasn't been played
1087a701da8ebabb3d63ac57b7718055698abb21804aJean-Michel Trivi     * back yet.
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalStateException
10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void stop()
10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    throws IllegalStateException {
10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mState != STATE_INITIALIZED) {
1093f4e58051e22ad4e21c7cd436c37cc5665c194d1cGlenn Kasten            throw new IllegalStateException("stop() called on uninitialized AudioTrack.");
10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // stop playing
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized(mPlayStateLock) {
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            native_stop();
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPlayState = PLAYSTATE_STOPPED;
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
110488bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath     * Pauses the playback of the audio data. Data that has not been played
110588bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath     * back will not be discarded. Subsequent calls to {@link #play} will play
1106a701da8ebabb3d63ac57b7718055698abb21804aJean-Michel Trivi     * this data back. See {@link #flush()} to discard this data.
110788bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath     *
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalStateException
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void pause()
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    throws IllegalStateException {
11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mState != STATE_INITIALIZED) {
1113f4e58051e22ad4e21c7cd436c37cc5665c194d1cGlenn Kasten            throw new IllegalStateException("pause() called on uninitialized AudioTrack.");
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //logd("pause()");
11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // pause playback
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized(mPlayStateLock) {
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            native_pause();
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPlayState = PLAYSTATE_PAUSED;
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //---------------------------------------------------------
11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Audio data supply
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //--------------------
11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
113088bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath     * Flushes the audio data currently queued for playback. Any data that has
1131e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * not been played back will be discarded.  No-op if not stopped or paused,
1132e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * or if the track's creation mode is not {@link #MODE_STREAM}.
11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void flush() {
11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mState == STATE_INITIALIZED) {
11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // flush the data in native layer
11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            native_flush();
11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1143e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * Writes the audio data to the audio sink for playback (streaming mode),
1144e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * or copies audio data for later playback (static buffer mode).
1145e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * In streaming mode, will block until all data has been written to the audio sink.
1146e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * In static buffer mode, copies the data to the buffer starting at offset 0.
114788bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath     * Note that the actual playback of this data might occur after this function
114888bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath     * returns. This function is thread safe with respect to {@link #stop} calls,
1149e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * in which case all of the specified data might not be written to the audio sink.
115088bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath     *
11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param audioData the array that holds the data to play.
115288bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath     * @param offsetInBytes the offset expressed in bytes in audioData where the data to play
1153ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     *    starts.
11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param sizeInBytes the number of bytes to read in audioData after the offset.
11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the number of bytes that were written or {@link #ERROR_INVALID_OPERATION}
11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *    if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *    the parameters don't resolve to valid data and indexes.
11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11605c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten    public int write(byte[] audioData, int offsetInBytes, int sizeInBytes) {
11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
116254955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten        if (mState == STATE_UNINITIALIZED || mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT) {
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ERROR_INVALID_OPERATION;
11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1166fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten        if ( (audioData == null) || (offsetInBytes < 0 ) || (sizeInBytes < 0)
1167a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten                || (offsetInBytes + sizeInBytes < 0)    // detect integer overflow
11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                || (offsetInBytes + sizeInBytes > audioData.length)) {
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ERROR_BAD_VALUE;
11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11727ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi        int ret = native_write_byte(audioData, offsetInBytes, sizeInBytes, mAudioFormat,
11737ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi                true /*isBlocking*/);
1174a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten
1175a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten        if ((mDataLoadMode == MODE_STATIC)
1176a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten                && (mState == STATE_NO_STATIC_DATA)
1177a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten                && (ret > 0)) {
1178a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten            // benign race with respect to other APIs that read mState
1179a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten            mState = STATE_INITIALIZED;
1180a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten        }
1181a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten
1182a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten        return ret;
11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1187e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * Writes the audio data to the audio sink for playback (streaming mode),
1188e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * or copies audio data for later playback (static buffer mode).
1189e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * In streaming mode, will block until all data has been written to the audio sink.
1190e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * In static buffer mode, copies the data to the buffer starting at offset 0.
119188bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath     * Note that the actual playback of this data might occur after this function
119288bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath     * returns. This function is thread safe with respect to {@link #stop} calls,
1193e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * in which case all of the specified data might not be written to the audio sink.
119488bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath     *
11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param audioData the array that holds the data to play.
1196ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     * @param offsetInShorts the offset expressed in shorts in audioData where the data to play
1197ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi     *     starts.
1198e8c82a37050e568f211d47951480b182a61d42b4Glenn Kasten     * @param sizeInShorts the number of shorts to read in audioData after the offset.
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the number of shorts that were written or {@link #ERROR_INVALID_OPERATION}
120054955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     *    if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
120154955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     *    the parameters don't resolve to valid data and indexes.
12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int write(short[] audioData, int offsetInShorts, int sizeInShorts) {
1205fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten
120654955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten        if (mState == STATE_UNINITIALIZED || mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT) {
12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ERROR_INVALID_OPERATION;
12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1210fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten        if ( (audioData == null) || (offsetInShorts < 0 ) || (sizeInShorts < 0)
1211a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten                || (offsetInShorts + sizeInShorts < 0)  // detect integer overflow
12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                || (offsetInShorts + sizeInShorts > audioData.length)) {
12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ERROR_BAD_VALUE;
12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1216a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten        int ret = native_write_short(audioData, offsetInShorts, sizeInShorts, mAudioFormat);
1217a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten
1218a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten        if ((mDataLoadMode == MODE_STATIC)
1219a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten                && (mState == STATE_NO_STATIC_DATA)
1220a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten                && (ret > 0)) {
1221a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten            // benign race with respect to other APIs that read mState
1222a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten            mState = STATE_INITIALIZED;
1223a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten        }
1224a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten
1225a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten        return ret;
12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12307ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi     * Writes the audio data to the audio sink for playback (streaming mode),
12317ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi     * or copies audio data for later playback (static buffer mode).
123254955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     * In static buffer mode, copies the data to the buffer starting at offset 0,
123354955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     * and the write mode is ignored.
123454955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     * In streaming mode, the blocking behavior will depend on the write mode.
123554955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     * <p>
123654955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     * Note that the actual playback of this data might occur after this function
123754955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     * returns. This function is thread safe with respect to {@link #stop} calls,
123854955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     * in which case all of the specified data might not be written to the audio sink.
123954955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     * <p>
124054955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     * @param audioData the array that holds the data to play.
124154955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     *     The implementation does not clip for sample values within the nominal range
124254955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     *     [-1.0f, 1.0f], provided that all gains in the audio pipeline are
124354955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     *     less than or equal to unity (1.0f), and in the absence of post-processing effects
124454955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     *     that could add energy, such as reverb.  For the convenience of applications
124554955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     *     that compute samples using filters with non-unity gain,
124654955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     *     sample values +3 dB beyond the nominal range are permitted.
124754955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     *     However such values may eventually be limited or clipped, depending on various gains
124854955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     *     and later processing in the audio path.  Therefore applications are encouraged
124954955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     *     to provide samples values within the nominal range.
125054955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     * @param offsetInFloats the offset, expressed as a number of floats,
125154955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     *     in audioData where the data to play starts.
125254955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     * @param sizeInFloats the number of floats to read in audioData after the offset.
125354955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     * @param writeMode one of {@link #WRITE_BLOCKING}, {@link #WRITE_NON_BLOCKING}. It has no
125454955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     *     effect in static mode.
125554955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     *     <BR>With {@link #WRITE_BLOCKING}, the write will block until all data has been written
125654955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     *         to the audio sink.
125754955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     *     <BR>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after
125854955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     *     queuing as much audio data for playback as possible without blocking.
125954955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     * @return the number of floats that were written, or {@link #ERROR_INVALID_OPERATION}
126054955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     *    if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
126154955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     *    the parameters don't resolve to valid data and indexes.
126254955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     * @hide candidate for public API
126354955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     */
126454955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten    public int write(float[] audioData, int offsetInFloats, int sizeInFloats,
126554955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten            @WriteMode int writeMode) {
126654955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten
126754955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten        if (mState == STATE_UNINITIALIZED) {
126854955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten            Log.e(TAG, "AudioTrack.write() called in invalid state STATE_UNINITIALIZED");
126954955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten            return ERROR_INVALID_OPERATION;
127054955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten        }
127154955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten
127254955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten        if (mAudioFormat != AudioFormat.ENCODING_PCM_FLOAT) {
127354955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten            Log.e(TAG, "AudioTrack.write(float[] ...) requires format ENCODING_PCM_FLOAT");
127454955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten            return ERROR_INVALID_OPERATION;
127554955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten        }
127654955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten
127754955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten        if ((writeMode != WRITE_BLOCKING) && (writeMode != WRITE_NON_BLOCKING)) {
127854955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten            Log.e(TAG, "AudioTrack.write() called with invalid blocking mode");
127954955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten            return ERROR_BAD_VALUE;
128054955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten        }
128154955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten
128254955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten        if ( (audioData == null) || (offsetInFloats < 0 ) || (sizeInFloats < 0)
128354955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten                || (offsetInFloats + sizeInFloats < 0)  // detect integer overflow
128454955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten                || (offsetInFloats + sizeInFloats > audioData.length)) {
128554955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten            Log.e(TAG, "AudioTrack.write() called with invalid array, offset, or size");
128654955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten            return ERROR_BAD_VALUE;
128754955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten        }
128854955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten
128954955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten        int ret = native_write_float(audioData, offsetInFloats, sizeInFloats, mAudioFormat,
129054955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten                writeMode == WRITE_BLOCKING);
129154955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten
129254955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten        if ((mDataLoadMode == MODE_STATIC)
129354955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten                && (mState == STATE_NO_STATIC_DATA)
129454955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten                && (ret > 0)) {
129554955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten            // benign race with respect to other APIs that read mState
129654955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten            mState = STATE_INITIALIZED;
129754955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten        }
129854955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten
129954955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten        return ret;
130054955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten    }
130154955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten
130254955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten
130354955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten    /**
130454955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     * Writes the audio data to the audio sink for playback (streaming mode),
130554955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten     * or copies audio data for later playback (static buffer mode).
13067ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi     * In static buffer mode, copies the data to the buffer starting at its 0 offset, and the write
13077ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi     * mode is ignored.
13087ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi     * In streaming mode, the blocking behavior will depend on the write mode.
13097ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi     * @param audioData the buffer that holds the data to play, starting at the position reported
13107ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi     *     by <code>audioData.position()</code>.
13115d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi     *     <BR>Note that upon return, the buffer position (<code>audioData.position()</code>) will
13125d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi     *     have been advanced to reflect the amount of data that was successfully written to
13135d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi     *     the AudioTrack.
13145d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi     * @param sizeInBytes number of bytes to write.
13155d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi     *     <BR>Note this may differ from <code>audioData.remaining()</code>, but cannot exceed it.
13167ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi     * @param writeMode one of {@link #WRITE_BLOCKING}, {@link #WRITE_NON_BLOCKING}. It has no
13177ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi     *     effect in static mode.
13187ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi     *     <BR>With {@link #WRITE_BLOCKING}, the write will block until all data has been written
13197ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi     *         to the audio sink.
13207ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi     *     <BR>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after
13217ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi     *     queuing as much audio data for playback as possible without blocking.
13227ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi     * @return 0 or a positive number of bytes that were written, or
13237ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi     *     {@link #ERROR_BAD_VALUE}, {@link #ERROR_INVALID_OPERATION}
13247ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi     */
13255d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi    public int write(ByteBuffer audioData, int sizeInBytes,
13267ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi            @WriteMode int writeMode) {
13277ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi
13287ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi        if (mState == STATE_UNINITIALIZED) {
13297ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi            Log.e(TAG, "AudioTrack.write() called in invalid state STATE_UNINITIALIZED");
13307ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi            return ERROR_INVALID_OPERATION;
13317ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi        }
13327ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi
133354955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten        if (mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT) {
133454955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten            Log.e(TAG, "AudioTrack.write(ByteBuffer ...) not yet supported for ENCODING_PCM_FLOAT");
133554955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten            return ERROR_INVALID_OPERATION;
133654955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten        }
133754955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten
13387ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi        if ((writeMode != WRITE_BLOCKING) && (writeMode != WRITE_NON_BLOCKING)) {
13397ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi            Log.e(TAG, "AudioTrack.write() called with invalid blocking mode");
13407ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi            return ERROR_BAD_VALUE;
13417ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi        }
13427ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi
13435d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi        if ( (audioData == null) || (sizeInBytes < 0) || (sizeInBytes > audioData.remaining())) {
13445d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi            Log.e(TAG, "AudioTrack.write() called with invalid size (" + sizeInBytes + ") value");
13457ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi            return ERROR_BAD_VALUE;
13467ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi        }
13477ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi
13487ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi        int ret = 0;
13497ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi        if (audioData.isDirect()) {
13507ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi            ret = native_write_native_bytes(audioData,
13515d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi                    audioData.position(), sizeInBytes, mAudioFormat,
13527ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi                    writeMode == WRITE_BLOCKING);
13537ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi        } else {
13547ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi            ret = native_write_byte(NioUtils.unsafeArray(audioData),
13555d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi                    NioUtils.unsafeArrayOffset(audioData) + audioData.position(),
13567ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi                    sizeInBytes, mAudioFormat,
13577ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi                    writeMode == WRITE_BLOCKING);
13587ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi        }
13597ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi
13607ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi        if ((mDataLoadMode == MODE_STATIC)
13617ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi                && (mState == STATE_NO_STATIC_DATA)
13627ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi                && (ret > 0)) {
13637ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi            // benign race with respect to other APIs that read mState
13647ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi            mState = STATE_INITIALIZED;
13657ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi        }
13667ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi
13675d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi        if (ret > 0) {
13685d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi            audioData.position(audioData.position() + ret);
13695d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi        }
13705d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi
13717ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi        return ret;
13727ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi    }
13737ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi
13747ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi    /**
13759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Notifies the native resource to reuse the audio data already loaded in the native
1376e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * layer, that is to rewind to start of buffer.
1377e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * The track's creation mode must be {@link #MODE_STATIC}.
13789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE},
13799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *  {@link #ERROR_INVALID_OPERATION}
13809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
13819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int reloadStaticData() {
1382a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten        if (mDataLoadMode == MODE_STREAM || mState != STATE_INITIALIZED) {
13839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ERROR_INVALID_OPERATION;
13849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return native_reload_static();
13869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13887070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent    //--------------------------------------------------------------------------
13897070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent    // Audio effects management
13907070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent    //--------------------
13917070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent
13927070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent    /**
13931a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent     * Attaches an auxiliary effect to the audio track. A typical auxiliary
13941a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent     * effect is a reverberation effect which can be applied on any sound source
13951a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent     * that directs a certain amount of its energy to this effect. This amount
13961a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent     * is defined by setAuxEffectSendLevel().
13977070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent     * {@see #setAuxEffectSendLevel(float)}.
13981a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent     * <p>After creating an auxiliary effect (e.g.
13991a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent     * {@link android.media.audiofx.EnvironmentalReverb}), retrieve its ID with
14001a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent     * {@link android.media.audiofx.AudioEffect#getId()} and use it when calling
14017070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent     * this method to attach the audio track to the effect.
14021a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent     * <p>To detach the effect from the audio track, call this method with a
14031a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent     * null effect id.
14047070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent     *
14057070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent     * @param effectId system wide unique id of the effect to attach
14067070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent     * @return error code or success, see {@link #SUCCESS},
14077070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent     *    {@link #ERROR_INVALID_OPERATION}, {@link #ERROR_BAD_VALUE}
14087070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent     */
14097070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent    public int attachAuxEffect(int effectId) {
14103b4df62704a6184878afd9272830cf3db7bd2d66Glenn Kasten        if (mState == STATE_UNINITIALIZED) {
14117070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent            return ERROR_INVALID_OPERATION;
14127070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent        }
14137070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent        return native_attachAuxEffect(effectId);
14147070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent    }
14157070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent
14167070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent    /**
14177070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent     * Sets the send level of the audio track to the attached auxiliary effect
141878cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * {@link #attachAuxEffect(int)}.  Effect levels
141978cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * are clamped to the closed interval [0.0, max] where
142078cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * max is the value of {@link #getMaxVolume}.
142178cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * A value of 0.0 results in no effect, and a value of 1.0 is full send.
1422e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten     * <p>By default the send level is 0.0f, so even if an effect is attached to the player
14237070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent     * this method must be called for the effect to be applied.
142478cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * <p>Note that the passed level value is a linear scalar. UI controls should be scaled
142578cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * logarithmically: the gain applied by audio framework ranges from -72dB to at least 0dB,
14267070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent     * so an appropriate conversion from linear UI input x to level is:
14275c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten     * x == 0 -&gt; level = 0
14285c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten     * 0 &lt; x &lt;= R -&gt; level = 10^(72*(x-R)/20/R)
14297070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent     *
143078cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten     * @param level linear send level
14317070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent     * @return error code or success, see {@link #SUCCESS},
14323009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten     *    {@link #ERROR_INVALID_OPERATION}, {@link #ERROR}
14337070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent     */
14347070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent    public int setAuxEffectSendLevel(float level) {
14351af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock        if (isRestricted()) {
14361af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock            return SUCCESS;
14371af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock        }
14383b4df62704a6184878afd9272830cf3db7bd2d66Glenn Kasten        if (mState == STATE_UNINITIALIZED) {
14397070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent            return ERROR_INVALID_OPERATION;
14407070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent        }
144178cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten        level = clampGainOrLevel(level);
14423009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten        int err = native_setAuxEffectSendLevel(level);
14433009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten        return err == 0 ? SUCCESS : ERROR;
14447070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent    }
14459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //---------------------------------------------------------
14479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Interface definitions
14489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //--------------------
14499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
14504df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     * Interface definition for a callback to be invoked when the playback head position of
14514df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     * an AudioTrack has reached a notification marker or has increased by a certain period.
14529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
14534df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    public interface OnPlaybackPositionUpdateListener  {
14549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
14559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Called on the listener to notify it that the previously set marker has been reached
14569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * by the playback head.
14579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
14589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void onMarkerReached(AudioTrack track);
1459fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten
14609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
14619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Called on the listener to periodically notify it that the playback head has reached
14629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * a multiple of the notification period.
14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
14649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void onPeriodicNotification(AudioTrack track);
14659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //---------------------------------------------------------
14699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Inner classes
14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //--------------------
14719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
14724df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     * Helper class to handle the forwarding of native events to the appropriate listener
14734df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project     * (potentially) handled in a different thread
14745c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten     */
14754df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    private class NativeEventHandlerDelegate {
14764df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        private final Handler mHandler;
1477fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten
147895bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten        NativeEventHandlerDelegate(final AudioTrack track,
147995bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten                                   final OnPlaybackPositionUpdateListener listener,
148095bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten                                   Handler handler) {
14814df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            // find the looper for our new event handler
14824df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            Looper looper;
14834df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            if (handler != null) {
14844df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                looper = handler.getLooper();
14854df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            } else {
1486105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                // no given handler, use the looper the AudioTrack was created in
1487105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                looper = mInitializationLooper;
14889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1489fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten
14904df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            // construct the event handler with this looper
14914df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            if (looper != null) {
14924df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                // implement the event handler delegate
14934df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                mHandler = new Handler(looper) {
14944df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                    @Override
14954df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                    public void handleMessage(Message msg) {
149695bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten                        if (track == null) {
14974df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            return;
14984df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        }
14994df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        switch(msg.what) {
15004df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        case NATIVE_EVENT_MARKER:
15014df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            if (listener != null) {
150295bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten                                listener.onMarkerReached(track);
15034df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            }
15044df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            break;
15054df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        case NATIVE_EVENT_NEW_POS:
15064df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            if (listener != null) {
150795bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten                                listener.onPeriodicNotification(track);
15084df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            }
15094df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            break;
15104df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        default:
15111f61d01508651b4475397414e1fe06af1ab8fadaGlenn Kasten                            loge("Unknown native event type: " + msg.what);
15124df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            break;
15134df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        }
15144df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                    }
15154df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                };
15164df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            } else {
15174df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                mHandler = null;
1518fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten            }
15194df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        }
1520fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten
15214df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        Handler getHandler() {
15224df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            return mHandler;
15239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //---------------------------------------------------------
15289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Java methods called from the native side
15299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //--------------------
15309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @SuppressWarnings("unused")
15319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static void postEventFromNative(Object audiotrack_ref,
15329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int what, int arg1, int arg2, Object obj) {
15339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //logd("Event posted from the native side: event="+ what + " args="+ arg1+" "+arg2);
15349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        AudioTrack track = (AudioTrack)((WeakReference)audiotrack_ref).get();
15359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (track == null) {
15369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
15379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
153995bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten        NativeEventHandlerDelegate delegate = track.mEventHandlerDelegate;
154095bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten        if (delegate != null) {
154195bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten            Handler handler = delegate.getHandler();
154295bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten            if (handler != null) {
154395bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten                Message m = handler.obtainMessage(what, arg1, arg2, obj);
154495bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten                handler.sendMessage(m);
154595bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten            }
15469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //---------------------------------------------------------
15529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Native methods called from the Java side
15539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //--------------------
15549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final int native_setup(Object audiotrack_this,
1556a4b06fd111185f4f245d816c09074107fef960bbGlenn Kasten            int streamType, int sampleRate, int channelMask, int audioFormat,
1557619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent            int buffSizeInBytes, int mode, int[] sessionId);
15589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final void native_finalize();
15609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final void native_release();
15629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final void native_start();
15649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final void native_stop();
15669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final void native_pause();
15689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final void native_flush();
15709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final int native_write_byte(byte[] audioData,
15727ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi                                               int offsetInBytes, int sizeInBytes, int format,
15737ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi                                               boolean isBlocking);
15749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final int native_write_short(short[] audioData,
15769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                int offsetInShorts, int sizeInShorts, int format);
15779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
157854955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten    private native final int native_write_float(float[] audioData,
157954955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten                                                int offsetInFloats, int sizeInFloats, int format,
158054955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten                                                boolean isBlocking);
158154955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten
15827ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi    private native final int native_write_native_bytes(Object audioData,
15835d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi            int positionInBytes, int sizeInBytes, int format, boolean blocking);
15847ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi
15859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final int native_reload_static();
15869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final int native_get_native_frame_count();
15889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final void native_setVolume(float leftVolume, float rightVolume);
15909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
159188e209dcf8c2ebddda5c272f46d1bd5478bc639cEric Laurent    private native final int native_set_playback_rate(int sampleRateInHz);
159288e209dcf8c2ebddda5c272f46d1bd5478bc639cEric Laurent    private native final int native_get_playback_rate();
15939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final int native_set_marker_pos(int marker);
15959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final int native_get_marker_pos();
15969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final int native_set_pos_update_period(int updatePeriod);
15989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final int native_get_pos_update_period();
15999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final int native_set_position(int position);
16019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final int native_get_position();
16029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
160361dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman    private native final int native_get_latency();
160461dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman
1605948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    // longArray must be a non-null array of length >= 2
1606948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    // [0] is assigned the frame position
1607948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    // [1] is assigned the time in CLOCK_MONOTONIC nanoseconds
1608948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten    private native final int native_get_timestamp(long[] longArray);
1609948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten
16109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final int native_set_loop(int start, int end, int loopCount);
16119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static private native final int native_get_output_sample_rate(int streamType);
16139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static private native final int native_get_min_buff_size(
16149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int sampleRateInHz, int channelConfig, int audioFormat);
16159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16167070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent    private native final int native_attachAuxEffect(int effectId);
16173009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten    private native final int native_setAuxEffectSendLevel(float level);
16187070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent
16199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //---------------------------------------------------------
16209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Utility methods
16219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //------------------
16229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static void logd(String msg) {
16241f61d01508651b4475397414e1fe06af1ab8fadaGlenn Kasten        Log.d(TAG, msg);
16259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static void loge(String msg) {
16281f61d01508651b4475397414e1fe06af1ab8fadaGlenn Kasten        Log.e(TAG, msg);
16299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1632