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 -> level = 0 14285c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten * 0 < x <= R -> 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