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