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; 301af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlockimport android.app.ActivityThread; 311af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlockimport android.content.Context; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler; 331af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlockimport android.os.IBinder; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Looper; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message; 361af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlockimport android.os.Process; 371af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlockimport android.os.RemoteException; 381af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlockimport android.os.ServiceManager; 39d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLeanimport android.util.ArrayMap; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 42ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkeyimport com.android.internal.annotations.GuardedBy; 431af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The AudioTrack class manages and plays a single audio resource for Java applications. 46e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * It allows streaming of PCM audio buffers to the audio sink for playback. This is 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * achieved by "pushing" the data to the AudioTrack object using one of the 487d60bcd2d950e3571c00ce9f1c492c6bd58334c9Glenn Kasten * {@link #write(byte[], int, int)}, {@link #write(short[], int, int)}, 497d60bcd2d950e3571c00ce9f1c492c6bd58334c9Glenn Kasten * and {@link #write(float[], int, int, int)} methods. 5088bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath * 51ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi * <p>An AudioTrack instance can operate under two modes: static or streaming.<br> 52ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi * In Streaming mode, the application writes a continuous stream of data to the AudioTrack, using 5388bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath * one of the {@code write()} methods. These are blocking and return when the data has been 5488bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath * transferred from the Java layer to the native layer and queued for playback. The streaming 5588bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath * mode is most useful when playing blocks of audio data that for instance are: 5688bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath * 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <ul> 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>too big to fit in memory because of the duration of the sound to play,</li> 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <li>too big to fit in memory because of the characteristics of the audio data 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (high sampling rate, bits per sample ...)</li> 61ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi * <li>received or generated while previously queued audio is playing.</li> 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </ul> 6388bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath * 645c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten * The static mode should be chosen when dealing with short sounds that fit in memory and 6588bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath * that need to be played with the smallest latency possible. The static mode will 6688bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath * therefore be preferred for UI and game sounds that are played often, and with the 6788bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath * smallest overhead possible. 6888bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath * 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Upon creation, an AudioTrack object initializes its associated audio buffer. 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The size of this buffer, specified during the construction, determines how long an AudioTrack 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * can play before running out of data.<br> 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * For an AudioTrack using the static mode, this size is the maximum size of the sound that can 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be played from it.<br> 74e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * For the streaming mode, data will be written to the audio sink in chunks of 755c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten * sizes less than or equal to the total buffer size. 7655a3218f242a611afb3569d88970c0c5dbf8ce54Glenn Kasten * 7755a3218f242a611afb3569d88970c0c5dbf8ce54Glenn Kasten * AudioTrack is not final and thus permits subclasses, but such use is not recommended. 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 793c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivipublic class AudioTrack extends PlayerBase 803c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi implements AudioRouting 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //--------------------------------------------------------- 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Constants 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //-------------------- 8578cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten /** Minimum value for a linear gain or auxiliary effect level. 8678cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * This value must be exactly equal to 0.0f; do not change it. 8778cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten */ 8878cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten private static final float GAIN_MIN = 0.0f; 8978cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten /** Maximum value for a linear gain or auxiliary effect level. 9078cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * This value must be greater than or equal to 1.0f. 9178cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten */ 9278cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten private static final float GAIN_MAX = 1.0f; 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 94bd2c3d65d6b62b5a359268246e7ebe96904bd851Glenn Kasten /** Maximum value for AudioTrack channel count 95bd2c3d65d6b62b5a359268246e7ebe96904bd851Glenn Kasten * @hide public for MediaCode only, do not un-hide or change to a numeric literal 96bd2c3d65d6b62b5a359268246e7ebe96904bd851Glenn Kasten */ 9725d3c7c49bafb22723138bfab2e315d2d0a926fbGlenn Kasten public static final int CHANNEL_COUNT_MAX = native_get_FCC_8(); 98ad720aeea741d9058a7b4d326c9ab1b3ebcd7c62Andy Hung 99ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi /** indicates AudioTrack state is stopped */ 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int PLAYSTATE_STOPPED = 1; // matches SL_PLAYSTATE_STOPPED 101ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi /** indicates AudioTrack state is paused */ 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int PLAYSTATE_PAUSED = 2; // matches SL_PLAYSTATE_PAUSED 103ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi /** indicates AudioTrack state is playing */ 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int PLAYSTATE_PLAYING = 3; // matches SL_PLAYSTATE_PLAYING 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1065c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten // keep these values in sync with android_media_AudioTrack.cpp 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Creation mode where audio data is transferred from Java to the native layer 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * only once before the audio starts playing. 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int MODE_STATIC = 0; 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Creation mode where audio data is streamed from Java to the native layer 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * as the audio is playing. 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int MODE_STREAM = 1; 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11835ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi /** @hide */ 11935ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi @IntDef({ 12035ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi MODE_STATIC, 12135ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi MODE_STREAM 12235ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi }) 12335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi @Retention(RetentionPolicy.SOURCE) 12435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi public @interface TransferMode {} 12535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 127ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi * State of an AudioTrack that was not successfully initialized upon creation. 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int STATE_UNINITIALIZED = 0; 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * State of an AudioTrack that is ready to be used. 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int STATE_INITIALIZED = 1; 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * State of a successfully initialized AudioTrack that uses static data, 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * but that hasn't received that data yet. 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int STATE_NO_STATIC_DATA = 2; 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Denotes a successful operation. 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 143bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent public static final int SUCCESS = AudioSystem.SUCCESS; 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Denotes a generic operation failure. 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 147bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent public static final int ERROR = AudioSystem.ERROR; 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Denotes a failure due to the use of an invalid value. 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 151bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent public static final int ERROR_BAD_VALUE = AudioSystem.BAD_VALUE; 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Denotes a failure due to the improper use of a method. 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 155bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent public static final int ERROR_INVALID_OPERATION = AudioSystem.INVALID_OPERATION; 1564e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent /** 1574e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent * An error code indicating that the object reporting it is no longer valid and needs to 1584e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent * be recreated. 1594e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent */ 1604e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent public static final int ERROR_DEAD_OBJECT = AudioSystem.DEAD_OBJECT; 1614e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent /** 1624e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent * {@link #getTimestampWithStatus(AudioTimestamp)} is called in STOPPED or FLUSHED state, 1634e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent * or immediately after start/ACTIVE. 1644e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent * @hide 1654e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent */ 1664e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent public static final int ERROR_WOULD_BLOCK = AudioSystem.WOULD_BLOCK; 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 168bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent // Error codes: 169bc11a696f6856624de532a6830d5db9dbbe2384cEric Laurent // to keep in sync with frameworks/base/core/jni/android_media_AudioTrack.cpp 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int ERROR_NATIVESETUP_AUDIOSYSTEM = -16; 171a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent private static final int ERROR_NATIVESETUP_INVALIDCHANNELMASK = -17; 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int ERROR_NATIVESETUP_INVALIDFORMAT = -18; 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int ERROR_NATIVESETUP_INVALIDSTREAMTYPE = -19; 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int ERROR_NATIVESETUP_NATIVEINITFAILED = -20; 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Events: 177e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten // to keep in sync with frameworks/av/include/media/AudioTrack.h 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 179ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi * Event id denotes when playback head has reached a previously set marker. 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int NATIVE_EVENT_MARKER = 3; 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 183ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi * Event id denotes when previously set update period has elapsed during playback. 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int NATIVE_EVENT_NEW_POS = 4; 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1871f61d01508651b4475397414e1fe06af1ab8fadaGlenn Kasten private final static String TAG = "android.media.AudioTrack"; 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1907ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi /** @hide */ 1917ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi @IntDef({ 1927ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi WRITE_BLOCKING, 1937ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi WRITE_NON_BLOCKING 1947ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi }) 1957ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi @Retention(RetentionPolicy.SOURCE) 1967ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi public @interface WriteMode {} 1977ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi 1987ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi /** 1997ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi * The write mode indicating the write operation will block until all data has been written, 200659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * to be used as the actual value of the writeMode parameter in 201659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * {@link #write(byte[], int, int, int)}, {@link #write(short[], int, int, int)}, 202659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * {@link #write(float[], int, int, int)}, {@link #write(ByteBuffer, int, int)}, and 203659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * {@link #write(ByteBuffer, int, int, long)}. 2047ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi */ 2057ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi public final static int WRITE_BLOCKING = 0; 206659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten 2077ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi /** 2087ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi * The write mode indicating the write operation will return immediately after 209659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * queuing as much audio data for playback as possible without blocking, 210659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * to be used as the actual value of the writeMode parameter in 211659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * {@link #write(ByteBuffer, int, int)}, {@link #write(short[], int, int, int)}, 212659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * {@link #write(float[], int, int, int)}, {@link #write(ByteBuffer, int, int)}, and 213659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * {@link #write(ByteBuffer, int, int, long)}. 2147ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi */ 2157ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi public final static int WRITE_NON_BLOCKING = 1; 2167ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //-------------------------------------------------------------------------- 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Member variables 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //-------------------- 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 221ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi * Indicates the state of the AudioTrack instance. 222340a6d09bdba7d4d99cef52a83a90fb96842c58aGlenn Kasten * One of STATE_UNINITIALIZED, STATE_INITIALIZED, or STATE_NO_STATIC_DATA. 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mState = STATE_UNINITIALIZED; 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 226ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi * Indicates the play state of the AudioTrack instance. 227340a6d09bdba7d4d99cef52a83a90fb96842c58aGlenn Kasten * One of PLAYSTATE_STOPPED, PLAYSTATE_PAUSED, or PLAYSTATE_PLAYING. 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mPlayState = PLAYSTATE_STOPPED; 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 231340a6d09bdba7d4d99cef52a83a90fb96842c58aGlenn Kasten * Lock to ensure mPlayState updates reflect the actual state of the object. 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Object mPlayStateLock = new Object(); 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2351d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * Sizes of the audio buffer. 2364bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung * These values are set during construction and can be stale. 2371d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * To obtain the current audio buffer frame count use {@link #getBufferSizeInFrames()}. 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mNativeBufferSizeInBytes = 0; 240e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten private int mNativeBufferSizeInFrames = 0; 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 24286fad47e68e344b19fabeab1156c5e6742d8dfadGlenn Kasten * Handler for events coming from the native code. 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 244d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean private NativePositionEventHandlerDelegate mEventHandlerDelegate; 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 246ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi * Looper associated with the thread that creates the AudioTrack instance. 247105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project */ 248b09707a041957f055cee3d290c85763cfef8d986Glenn Kasten private final Looper mInitializationLooper; 249105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project /** 2508d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten * The audio data source sampling rate in Hz. 2511cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten * Never {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED}. 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 253340a6d09bdba7d4d99cef52a83a90fb96842c58aGlenn Kasten private int mSampleRate; // initialized by all constructors via audioParamCheck() 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 255340a6d09bdba7d4d99cef52a83a90fb96842c58aGlenn Kasten * The number of audio output channels (1 is mono, 2 is stereo, etc.). 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mChannelCount = 1; 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 259a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung * The audio channel mask used for calling native AudioTrack 2603026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent */ 2619ea5e5564812bb88e62d0c4fae8f1d40d8a6e7e0Glenn Kasten private int mChannelMask = AudioFormat.CHANNEL_OUT_MONO; 2623026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent 2633026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent /** 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The type of the audio stream to play. See 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link AudioManager#STREAM_VOICE_CALL}, {@link AudioManager#STREAM_SYSTEM}, 2665c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten * {@link AudioManager#STREAM_RING}, {@link AudioManager#STREAM_MUSIC}, 267b282e08ab641d4fc74d0324b7a0ce30926638dd5Glenn Kasten * {@link AudioManager#STREAM_ALARM}, {@link AudioManager#STREAM_NOTIFICATION}, and 268b282e08ab641d4fc74d0324b7a0ce30926638dd5Glenn Kasten * {@link AudioManager#STREAM_DTMF}. 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mStreamType = AudioManager.STREAM_MUSIC; 271a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 273340a6d09bdba7d4d99cef52a83a90fb96842c58aGlenn Kasten * The way audio is consumed by the audio sink, one of MODE_STATIC or MODE_STREAM. 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mDataLoadMode = MODE_STREAM; 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 277a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung * The current channel position mask, as specified on AudioTrack creation. 278a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung * Can be set simultaneously with channel index mask {@link #mChannelIndexMask}. 279a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung * May be set to {@link AudioFormat#CHANNEL_INVALID} if a channel index mask is specified. 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 281a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent private int mChannelConfiguration = AudioFormat.CHANNEL_OUT_MONO; 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 283340a6d09bdba7d4d99cef52a83a90fb96842c58aGlenn Kasten * The channel index mask if specified, otherwise 0. 284a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung */ 285a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung private int mChannelIndexMask = 0; 286a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung /** 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The encoding of the audio samples. 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see AudioFormat#ENCODING_PCM_8BIT 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see AudioFormat#ENCODING_PCM_16BIT 2907d60bcd2d950e3571c00ce9f1c492c6bd58334c9Glenn Kasten * @see AudioFormat#ENCODING_PCM_FLOAT 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 292340a6d09bdba7d4d99cef52a83a90fb96842c58aGlenn Kasten private int mAudioFormat; // initialized by all constructors via audioParamCheck() 293619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent /** 294619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent * Audio session ID 295619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent */ 29633b840444f5a481dd31e129079d3c0cf3acdf80eGlenn Kasten private int mSessionId = AudioManager.AUDIO_SESSION_ID_GENERATE; 2971af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock /** 298cfe964a09ca05778e5dd84f2fd24119b89401696Rachad * HW_AV_SYNC track AV Sync Header 299cfe964a09ca05778e5dd84f2fd24119b89401696Rachad */ 300cfe964a09ca05778e5dd84f2fd24119b89401696Rachad private ByteBuffer mAvSyncHeader = null; 301cfe964a09ca05778e5dd84f2fd24119b89401696Rachad /** 302cfe964a09ca05778e5dd84f2fd24119b89401696Rachad * HW_AV_SYNC track audio data bytes remaining to write after current AV sync header 303cfe964a09ca05778e5dd84f2fd24119b89401696Rachad */ 304cfe964a09ca05778e5dd84f2fd24119b89401696Rachad private int mAvSyncBytesRemaining = 0; 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //-------------------------------- 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Used exclusively by native code 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //-------------------- 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 310ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean * @hide 311ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi * Accessed by native methods: provides access to C++ AudioTrack object. 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @SuppressWarnings("unused") 314ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean protected long mNativeTrackInJavaObj; 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Accessed by native methods: provides access to the JNI data (i.e. resources used by 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the native AudioTrack object, but not stored in it). 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @SuppressWarnings("unused") 320075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat private long mJniData; 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //-------------------------------------------------------------------------- 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Constructor, Finalize 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //-------------------- 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Class constructor. 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param streamType the type of the audio stream. See 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link AudioManager#STREAM_VOICE_CALL}, {@link AudioManager#STREAM_SYSTEM}, 3305c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten * {@link AudioManager#STREAM_RING}, {@link AudioManager#STREAM_MUSIC}, 3315c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten * {@link AudioManager#STREAM_ALARM}, and {@link AudioManager#STREAM_NOTIFICATION}. 3328d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten * @param sampleRateInHz the initial source sample rate expressed in Hz. 3331cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten * {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED} means to use a route-dependent value 3341cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten * which is usually the sample rate of the sink. 3351cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten * {@link #getSampleRate()} can be used to retrieve the actual sample rate chosen. 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param channelConfig describes the configuration of the audio channels. 337a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent * See {@link AudioFormat#CHANNEL_OUT_MONO} and 338a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent * {@link AudioFormat#CHANNEL_OUT_STEREO} 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param audioFormat the format in which the audio data is represented. 3407d60bcd2d950e3571c00ce9f1c492c6bd58334c9Glenn Kasten * See {@link AudioFormat#ENCODING_PCM_16BIT}, 3417d60bcd2d950e3571c00ce9f1c492c6bd58334c9Glenn Kasten * {@link AudioFormat#ENCODING_PCM_8BIT}, 3427d60bcd2d950e3571c00ce9f1c492c6bd58334c9Glenn Kasten * and {@link AudioFormat#ENCODING_PCM_FLOAT}. 343e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * @param bufferSizeInBytes the total size (in bytes) of the internal buffer where audio data is 3441d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * read from for playback. This should be a nonzero multiple of the frame size in bytes. 3454bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung * <p> If the track's creation mode is {@link #MODE_STATIC}, 346e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * this is the maximum length sample, or audio clip, that can be played by this instance. 3474bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung * <p> If the track's creation mode is {@link #MODE_STREAM}, 3484bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung * this should be the desired buffer size 3494bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung * for the <code>AudioTrack</code> to satisfy the application's 3501d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * latency requirements. 3514bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung * If <code>bufferSizeInBytes</code> is less than the 3521d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * minimum buffer size for the output sink, it is increased to the minimum 3534bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung * buffer size. 354e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung * The method {@link #getBufferSizeInFrames()} returns the 3551d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * actual size in frames of the buffer created, which 3561d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * determines the minimum frequency to write 3574bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung * to the streaming <code>AudioTrack</code> to avoid underrun. 3581d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * See {@link #getMinBufferSize(int, int, int)} to determine the estimated minimum buffer size 3591d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * for an AudioTrack instance in streaming mode. 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param mode streaming or static buffer. See {@link #MODE_STATIC} and {@link #MODE_STREAM} 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws java.lang.IllegalArgumentException 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat, 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int bufferSizeInBytes, int mode) 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws IllegalArgumentException { 366619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent this(streamType, sampleRateInHz, channelConfig, audioFormat, 36733b840444f5a481dd31e129079d3c0cf3acdf80eGlenn Kasten bufferSizeInBytes, mode, AudioManager.AUDIO_SESSION_ID_GENERATE); 368619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent } 369619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent 370619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent /** 371619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent * Class constructor with audio session. Use this constructor when the AudioTrack must be 372619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent * attached to a particular audio session. The primary use of the audio session ID is to 373619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent * associate audio effects to a particular instance of AudioTrack: if an audio session ID 374619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent * is provided when creating an AudioEffect, this effect will be applied only to audio tracks 375619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent * and media players in the same session and not to the output mix. 376619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent * When an AudioTrack is created without specifying a session, it will create its own session 3778d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten * which can be retrieved by calling the {@link #getAudioSessionId()} method. 3785c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten * If a non-zero session ID is provided, this AudioTrack will share effects attached to this 3795c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten * session 3805c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten * with all other media players or audio tracks in the same session, otherwise a new session 3815c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten * will be created for this track if none is supplied. 382619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent * @param streamType the type of the audio stream. See 383619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent * {@link AudioManager#STREAM_VOICE_CALL}, {@link AudioManager#STREAM_SYSTEM}, 3845c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten * {@link AudioManager#STREAM_RING}, {@link AudioManager#STREAM_MUSIC}, 3855c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten * {@link AudioManager#STREAM_ALARM}, and {@link AudioManager#STREAM_NOTIFICATION}. 3868d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten * @param sampleRateInHz the initial source sample rate expressed in Hz. 3871cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten * {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED} means to use a route-dependent value 3881cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten * which is usually the sample rate of the sink. 389619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent * @param channelConfig describes the configuration of the audio channels. 390619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent * See {@link AudioFormat#CHANNEL_OUT_MONO} and 391619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent * {@link AudioFormat#CHANNEL_OUT_STEREO} 392619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent * @param audioFormat the format in which the audio data is represented. 393619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent * See {@link AudioFormat#ENCODING_PCM_16BIT} and 3947d60bcd2d950e3571c00ce9f1c492c6bd58334c9Glenn Kasten * {@link AudioFormat#ENCODING_PCM_8BIT}, 3957d60bcd2d950e3571c00ce9f1c492c6bd58334c9Glenn Kasten * and {@link AudioFormat#ENCODING_PCM_FLOAT}. 3961d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * @param bufferSizeInBytes the total size (in bytes) of the internal buffer where audio data is 3971d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * read from for playback. This should be a nonzero multiple of the frame size in bytes. 3981d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * <p> If the track's creation mode is {@link #MODE_STATIC}, 3991d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * this is the maximum length sample, or audio clip, that can be played by this instance. 4001d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * <p> If the track's creation mode is {@link #MODE_STREAM}, 4011d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * this should be the desired buffer size 4021d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * for the <code>AudioTrack</code> to satisfy the application's 4031d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * latency requirements. 4041d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * If <code>bufferSizeInBytes</code> is less than the 4051d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * minimum buffer size for the output sink, it is increased to the minimum 4061d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * buffer size. 4071d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * The method {@link #getBufferSizeInFrames()} returns the 4081d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * actual size in frames of the buffer created, which 4091d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * determines the minimum frequency to write 4101d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * to the streaming <code>AudioTrack</code> to avoid underrun. 4111d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * You can write data into this buffer in smaller chunks than this size. 4121d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * See {@link #getMinBufferSize(int, int, int)} to determine the estimated minimum buffer size 4131d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * for an AudioTrack instance in streaming mode. 414619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent * @param mode streaming or static buffer. See {@link #MODE_STATIC} and {@link #MODE_STREAM} 415619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent * @param sessionId Id of audio session the AudioTrack must be attached to 416619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent * @throws java.lang.IllegalArgumentException 417619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent */ 418619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat, 419619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent int bufferSizeInBytes, int mode, int sessionId) 420619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent throws IllegalArgumentException { 421a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten // mState already == STATE_UNINITIALIZED 422a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi this((new AudioAttributes.Builder()) 423a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi .setLegacyStreamType(streamType) 424a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi .build(), 425a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi (new AudioFormat.Builder()) 426a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi .setChannelMask(channelConfig) 427a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi .setEncoding(audioFormat) 428a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi .setSampleRate(sampleRateInHz) 429a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi .build(), 430a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi bufferSizeInBytes, 431a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi mode, sessionId); 432a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi } 433a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi 434a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi /** 4357f6ee760b0aee76bdb9fe61ac7ed1465c0da3489Jean-Michel Trivi * Class constructor with {@link AudioAttributes} and {@link AudioFormat}. 4367f6ee760b0aee76bdb9fe61ac7ed1465c0da3489Jean-Michel Trivi * @param attributes a non-null {@link AudioAttributes} instance. 4377f6ee760b0aee76bdb9fe61ac7ed1465c0da3489Jean-Michel Trivi * @param format a non-null {@link AudioFormat} instance describing the format of the data 4387f6ee760b0aee76bdb9fe61ac7ed1465c0da3489Jean-Michel Trivi * that will be played through this AudioTrack. See {@link AudioFormat.Builder} for 4397f6ee760b0aee76bdb9fe61ac7ed1465c0da3489Jean-Michel Trivi * configuring the audio format parameters such as encoding, channel mask and sample rate. 4401d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * @param bufferSizeInBytes the total size (in bytes) of the internal buffer where audio data is 4411d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * read from for playback. This should be a nonzero multiple of the frame size in bytes. 4421d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * <p> If the track's creation mode is {@link #MODE_STATIC}, 4431d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * this is the maximum length sample, or audio clip, that can be played by this instance. 4441d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * <p> If the track's creation mode is {@link #MODE_STREAM}, 4451d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * this should be the desired buffer size 4461d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * for the <code>AudioTrack</code> to satisfy the application's 4471d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * latency requirements. 4481d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * If <code>bufferSizeInBytes</code> is less than the 4491d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * minimum buffer size for the output sink, it is increased to the minimum 4501d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * buffer size. 4511d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * The method {@link #getBufferSizeInFrames()} returns the 4521d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * actual size in frames of the buffer created, which 4531d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * determines the minimum frequency to write 4541d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * to the streaming <code>AudioTrack</code> to avoid underrun. 4551d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * See {@link #getMinBufferSize(int, int, int)} to determine the estimated minimum buffer size 4561d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * for an AudioTrack instance in streaming mode. 4577f6ee760b0aee76bdb9fe61ac7ed1465c0da3489Jean-Michel Trivi * @param mode streaming or static buffer. See {@link #MODE_STATIC} and {@link #MODE_STREAM}. 458289cc8e887f786f557faab226a1e01abb9a632a6Jean-Michel Trivi * @param sessionId ID of audio session the AudioTrack must be attached to, or 459289cc8e887f786f557faab226a1e01abb9a632a6Jean-Michel Trivi * {@link AudioManager#AUDIO_SESSION_ID_GENERATE} if the session isn't known at construction 460289cc8e887f786f557faab226a1e01abb9a632a6Jean-Michel Trivi * time. See also {@link AudioManager#generateAudioSessionId()} to obtain a session ID before 461289cc8e887f786f557faab226a1e01abb9a632a6Jean-Michel Trivi * construction. 4627f6ee760b0aee76bdb9fe61ac7ed1465c0da3489Jean-Michel Trivi * @throws IllegalArgumentException 463a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi */ 464a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi public AudioTrack(AudioAttributes attributes, AudioFormat format, int bufferSizeInBytes, 465a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi int mode, int sessionId) 466a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi throws IllegalArgumentException { 4673c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi super(attributes); 468a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi // mState already == STATE_UNINITIALIZED 4695c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten 4707f6ee760b0aee76bdb9fe61ac7ed1465c0da3489Jean-Michel Trivi if (format == null) { 4717f6ee760b0aee76bdb9fe61ac7ed1465c0da3489Jean-Michel Trivi throw new IllegalArgumentException("Illegal null AudioFormat"); 4727f6ee760b0aee76bdb9fe61ac7ed1465c0da3489Jean-Michel Trivi } 4737f6ee760b0aee76bdb9fe61ac7ed1465c0da3489Jean-Michel Trivi 4745c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten // remember which looper is associated with the AudioTrack instantiation 475b09707a041957f055cee3d290c85763cfef8d986Glenn Kasten Looper looper; 476b09707a041957f055cee3d290c85763cfef8d986Glenn Kasten if ((looper = Looper.myLooper()) == null) { 477b09707a041957f055cee3d290c85763cfef8d986Glenn Kasten looper = Looper.getMainLooper(); 478105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4801cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten int rate = format.getSampleRate(); 4811cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten if (rate == AudioFormat.SAMPLE_RATE_UNSPECIFIED) { 4821cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten rate = 0; 483a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi } 4841cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten 485a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung int channelIndexMask = 0; 486a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung if ((format.getPropertySetMask() 487a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung & AudioFormat.AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_INDEX_MASK) != 0) { 488a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung channelIndexMask = format.getChannelIndexMask(); 489a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung } 490a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung int channelMask = 0; 491a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung if ((format.getPropertySetMask() 492a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung & AudioFormat.AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_MASK) != 0) { 493a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi channelMask = format.getChannelMask(); 494a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung } else if (channelIndexMask == 0) { // if no masks at all, use stereo 495a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung channelMask = AudioFormat.CHANNEL_OUT_FRONT_LEFT 496a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung | AudioFormat.CHANNEL_OUT_FRONT_RIGHT; 497a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi } 498a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi int encoding = AudioFormat.ENCODING_DEFAULT; 499a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi if ((format.getPropertySetMask() & AudioFormat.AUDIO_FORMAT_HAS_PROPERTY_ENCODING) != 0) { 500a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi encoding = format.getEncoding(); 501a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi } 502a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung audioParamCheck(rate, channelMask, channelIndexMask, encoding, mode); 503a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi mStreamType = AudioSystem.STREAM_DEFAULT; 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project audioBuffSizeCheck(bufferSizeInBytes); 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 507a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi mInitializationLooper = looper; 508a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi 509619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent if (sessionId < 0) { 510f4e58051e22ad4e21c7cd436c37cc5665c194d1cGlenn Kasten throw new IllegalArgumentException("Invalid audio session ID: "+sessionId); 511619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent } 512619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent 5131cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten int[] sampleRate = new int[] {mSampleRate}; 514619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent int[] session = new int[1]; 515619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent session[0] = sessionId; 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // native initialization 517a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi int initResult = native_setup(new WeakReference<AudioTrack>(this), mAttributes, 5181cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten sampleRate, mChannelMask, mChannelIndexMask, mAudioFormat, 5199b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean mNativeBufferSizeInBytes, mDataLoadMode, session, 0 /*nativeTrackInJavaObj*/); 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (initResult != SUCCESS) { 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project loge("Error code "+initResult+" when initializing AudioTrack."); 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; // with mState == STATE_UNINITIALIZED 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5251cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten mSampleRate = sampleRate[0]; 526619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent mSessionId = session[0]; 527619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDataLoadMode == MODE_STATIC) { 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState = STATE_NO_STATIC_DATA; 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState = STATE_INITIALIZED; 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 53535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi /** 536ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean * A constructor which explicitly connects a Native (C++) AudioTrack. For use by 537ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean * the AudioTrackRoutingProxy subclass. 538ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean * @param nativeTrackInJavaObj a C/C++ pointer to a native AudioTrack 539ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean * (associated with an OpenSL ES player). 54014b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean * IMPORTANT: For "N", this method is ONLY called to setup a Java routing proxy, 54114b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean * i.e. IAndroidConfiguration::AcquireJavaProxy(). If we call with a 0 in nativeTrackInJavaObj 54214b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean * it means that the OpenSL player interface hasn't been realized, so there is no native 54314b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean * Audiotrack to connect to. In this case wait to call deferred_connect() until the 54414b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean * OpenSLES interface is realized. 545ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean */ 546ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean /*package*/ AudioTrack(long nativeTrackInJavaObj) { 5473c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi super(new AudioAttributes.Builder().build()); 548ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean // "final"s 54914b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean mNativeTrackInJavaObj = 0; 55014b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean mJniData = 0; 551ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean 552ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean // remember which looper is associated with the AudioTrack instantiation 553ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean Looper looper; 554ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean if ((looper = Looper.myLooper()) == null) { 555ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean looper = Looper.getMainLooper(); 556ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean } 557ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean mInitializationLooper = looper; 558ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean 559ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean // other initialization... 56014b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean if (nativeTrackInJavaObj != 0) { 56114b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean deferred_connect(nativeTrackInJavaObj); 56214b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean } else { 56314b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean mState = STATE_UNINITIALIZED; 5649b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean } 56514b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean } 5669b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean 56714b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean /** 56814b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean * @hide 56914b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean */ 57014b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean /* package */ void deferred_connect(long nativeTrackInJavaObj) { 57114b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean if (mState != STATE_INITIALIZED) { 57214b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean // Note that for this native_setup, we are providing an already created/initialized 57314b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean // *Native* AudioTrack, so the attributes parameters to native_setup() are ignored. 57414b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean int[] session = { 0 }; 57514b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean int[] rates = { 0 }; 57614b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean int initResult = native_setup(new WeakReference<AudioTrack>(this), 57714b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean null /*mAttributes - NA*/, 57814b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean rates /*sampleRate - NA*/, 57914b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean 0 /*mChannelMask - NA*/, 58014b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean 0 /*mChannelIndexMask - NA*/, 58114b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean 0 /*mAudioFormat - NA*/, 58214b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean 0 /*mNativeBufferSizeInBytes - NA*/, 58314b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean 0 /*mDataLoadMode - NA*/, 58414b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean session, 58514b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean nativeTrackInJavaObj); 58614b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean if (initResult != SUCCESS) { 58714b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean loge("Error code "+initResult+" when initializing AudioTrack."); 58814b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean return; // with mState == STATE_UNINITIALIZED 58914b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean } 59014b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean 59114b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean mSessionId = session[0]; 592ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean 59314b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean mState = STATE_INITIALIZED; 59414b4e65affca4eabe57c02d4968b0b585adff76fPaul McLean } 595ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean } 596ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean 597ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean /** 59835ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * Builder class for {@link AudioTrack} objects. 59935ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * Use this class to configure and create an <code>AudioTrack</code> instance. By setting audio 60035ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * attributes and audio format parameters, you indicate which of those vary from the default 60135ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * behavior on the device. 60235ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * <p> Here is an example where <code>Builder</code> is used to specify all {@link AudioFormat} 60335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * parameters, to be used by a new <code>AudioTrack</code> instance: 60435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * 60535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * <pre class="prettyprint"> 60635ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * AudioTrack player = new AudioTrack.Builder() 60735ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * .setAudioAttributes(new AudioAttributes.Builder() 60835ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * .setUsage(AudioAttributes.USAGE_ALARM) 609e27a75173f0eb43c1a5d52f35f543d50a859e144Jean-Michel Trivi * .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) 61035ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * .build()) 61135ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * .setAudioFormat(new AudioFormat.Builder() 61235ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * .setEncoding(AudioFormat.ENCODING_PCM_16BIT) 61349962261b3c05eea70fe66076d27c8c0b80ba280Jean-Michel Trivi * .setSampleRate(44100) 61435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * .setChannelMask(AudioFormat.CHANNEL_OUT_STEREO) 61535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * .build()) 616e27a75173f0eb43c1a5d52f35f543d50a859e144Jean-Michel Trivi * .setBufferSizeInBytes(minBuffSize) 61735ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * .build(); 61835ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * </pre> 61935ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * <p> 62035ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * If the audio attributes are not set with {@link #setAudioAttributes(AudioAttributes)}, 62135ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * attributes comprising {@link AudioAttributes#USAGE_MEDIA} will be used. 6220f0da49fce053eec4f95ce6a8e553d77f9df62a4Eric Laurent * <br>If the audio format is not specified or is incomplete, its channel configuration will be 62335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * {@link AudioFormat#CHANNEL_OUT_STEREO} and the encoding will be 62435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * {@link AudioFormat#ENCODING_PCM_16BIT}. 6250f0da49fce053eec4f95ce6a8e553d77f9df62a4Eric Laurent * The sample rate will depend on the device actually selected for playback and can be queried 6260f0da49fce053eec4f95ce6a8e553d77f9df62a4Eric Laurent * with {@link #getSampleRate()} method. 6274bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung * <br>If the buffer size is not specified with {@link #setBufferSizeInBytes(int)}, 6284bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung * and the mode is {@link AudioTrack#MODE_STREAM}, the minimum buffer size is used. 62935ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * <br>If the transfer mode is not specified with {@link #setTransferMode(int)}, 6304bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung * <code>MODE_STREAM</code> will be used. 63135ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * <br>If the session ID is not specified with {@link #setSessionId(int)}, a new one will 63235ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * be generated. 63335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi */ 63435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi public static class Builder { 63535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi private AudioAttributes mAttributes; 63635ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi private AudioFormat mFormat; 63735ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi private int mBufferSizeInBytes; 63835ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi private int mSessionId = AudioManager.AUDIO_SESSION_ID_GENERATE; 63935ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi private int mMode = MODE_STREAM; 64035ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi 64135ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi /** 64235ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * Constructs a new Builder with the default values as described above. 64335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi */ 64435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi public Builder() { 64535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi } 64635ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi 64735ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi /** 64835ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * Sets the {@link AudioAttributes}. 64935ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * @param attributes a non-null {@link AudioAttributes} instance that describes the audio 65035ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * data to be played. 65135ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * @return the same Builder instance. 65235ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * @throws IllegalArgumentException 65335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi */ 65435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi public @NonNull Builder setAudioAttributes(@NonNull AudioAttributes attributes) 65535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi throws IllegalArgumentException { 65635ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi if (attributes == null) { 65735ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi throw new IllegalArgumentException("Illegal null AudioAttributes argument"); 65835ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi } 65935ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi // keep reference, we only copy the data when building 66035ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi mAttributes = attributes; 66135ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi return this; 66235ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi } 66335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi 66435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi /** 66535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * Sets the format of the audio data to be played by the {@link AudioTrack}. 66635ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * See {@link AudioFormat.Builder} for configuring the audio format parameters such 66735ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * as encoding, channel mask and sample rate. 66835ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * @param format a non-null {@link AudioFormat} instance. 66935ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * @return the same Builder instance. 67035ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * @throws IllegalArgumentException 67135ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi */ 67235ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi public @NonNull Builder setAudioFormat(@NonNull AudioFormat format) 67335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi throws IllegalArgumentException { 67435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi if (format == null) { 67535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi throw new IllegalArgumentException("Illegal null AudioFormat argument"); 67635ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi } 67735ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi // keep reference, we only copy the data when building 67835ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi mFormat = format; 67935ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi return this; 68035ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi } 68135ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi 68235ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi /** 68335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * Sets the total size (in bytes) of the buffer where audio data is read from for playback. 68435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * If using the {@link AudioTrack} in streaming mode 68535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * (see {@link AudioTrack#MODE_STREAM}, you can write data into this buffer in smaller 68635ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * chunks than this size. See {@link #getMinBufferSize(int, int, int)} to determine 6871d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * the estimated minimum buffer size for the creation of an AudioTrack instance 6881d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * in streaming mode. 68935ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * <br>If using the <code>AudioTrack</code> in static mode (see 69035ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * {@link AudioTrack#MODE_STATIC}), this is the maximum size of the sound that will be 69135ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * played by this instance. 69235ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * @param bufferSizeInBytes 69335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * @return the same Builder instance. 69435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * @throws IllegalArgumentException 69535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi */ 69635ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi public @NonNull Builder setBufferSizeInBytes(int bufferSizeInBytes) 69735ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi throws IllegalArgumentException { 69835ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi if (bufferSizeInBytes <= 0) { 69935ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi throw new IllegalArgumentException("Invalid buffer size " + bufferSizeInBytes); 70035ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi } 70135ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi mBufferSizeInBytes = bufferSizeInBytes; 70235ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi return this; 70335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi } 70435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi 70535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi /** 70635ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * Sets the mode under which buffers of audio data are transferred from the 70735ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * {@link AudioTrack} to the framework. 70835ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * @param mode one of {@link AudioTrack#MODE_STREAM}, {@link AudioTrack#MODE_STATIC}. 70935ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * @return the same Builder instance. 71035ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * @throws IllegalArgumentException 71135ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi */ 71235ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi public @NonNull Builder setTransferMode(@TransferMode int mode) 71335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi throws IllegalArgumentException { 71435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi switch(mode) { 71535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi case MODE_STREAM: 71635ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi case MODE_STATIC: 71735ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi mMode = mode; 71835ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi break; 71935ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi default: 72035ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi throw new IllegalArgumentException("Invalid transfer mode " + mode); 72135ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi } 72235ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi return this; 72335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi } 72435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi 72535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi /** 72635ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * Sets the session ID the {@link AudioTrack} will be attached to. 72735ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * @param sessionId a strictly positive ID number retrieved from another 72835ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * <code>AudioTrack</code> via {@link AudioTrack#getAudioSessionId()} or allocated by 72935ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * {@link AudioManager} via {@link AudioManager#generateAudioSessionId()}, or 73035ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * {@link AudioManager#AUDIO_SESSION_ID_GENERATE}. 73135ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * @return the same Builder instance. 73235ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * @throws IllegalArgumentException 73335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi */ 73435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi public @NonNull Builder setSessionId(int sessionId) 73535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi throws IllegalArgumentException { 73635ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi if ((sessionId != AudioManager.AUDIO_SESSION_ID_GENERATE) && (sessionId < 1)) { 73735ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi throw new IllegalArgumentException("Invalid audio session ID " + sessionId); 73835ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi } 73935ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi mSessionId = sessionId; 74035ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi return this; 74135ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi } 74235ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi 74335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi /** 74435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * Builds an {@link AudioTrack} instance initialized with all the parameters set 74535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * on this <code>Builder</code>. 7462d2d89363f0b794cbb63f389584fa4c5557ff51aAndy Hung * @return a new successfully initialized {@link AudioTrack} instance. 74735ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi * @throws UnsupportedOperationException if the parameters set on the <code>Builder</code> 7482d2d89363f0b794cbb63f389584fa4c5557ff51aAndy Hung * were incompatible, or if they are not supported by the device, 7492d2d89363f0b794cbb63f389584fa4c5557ff51aAndy Hung * or if the device was not available. 75035ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi */ 75135ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi public @NonNull AudioTrack build() throws UnsupportedOperationException { 75235ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi if (mAttributes == null) { 75335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi mAttributes = new AudioAttributes.Builder() 75435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi .setUsage(AudioAttributes.USAGE_MEDIA) 75535ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi .build(); 75635ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi } 75735ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi if (mFormat == null) { 75835ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi mFormat = new AudioFormat.Builder() 75935ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi .setChannelMask(AudioFormat.CHANNEL_OUT_STEREO) 7601cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten //.setSampleRate(AudioFormat.SAMPLE_RATE_UNSPECIFIED) 76135ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi .setEncoding(AudioFormat.ENCODING_DEFAULT) 76235ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi .build(); 76335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi } 76435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi try { 7654bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung // If the buffer size is not specified in streaming mode, 7664bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung // use a single frame for the buffer size and let the 7674bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung // native code figure out the minimum buffer size. 7684bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung if (mMode == MODE_STREAM && mBufferSizeInBytes == 0) { 7694bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung mBufferSizeInBytes = mFormat.getChannelCount() 7704bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung * mFormat.getBytesPerSample(mFormat.getEncoding()); 7714bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung } 7722d2d89363f0b794cbb63f389584fa4c5557ff51aAndy Hung final AudioTrack track = new AudioTrack( 7732d2d89363f0b794cbb63f389584fa4c5557ff51aAndy Hung mAttributes, mFormat, mBufferSizeInBytes, mMode, mSessionId); 7742d2d89363f0b794cbb63f389584fa4c5557ff51aAndy Hung if (track.getState() == STATE_UNINITIALIZED) { 7752d2d89363f0b794cbb63f389584fa4c5557ff51aAndy Hung // release is not necessary 7762d2d89363f0b794cbb63f389584fa4c5557ff51aAndy Hung throw new UnsupportedOperationException("Cannot create AudioTrack"); 7772d2d89363f0b794cbb63f389584fa4c5557ff51aAndy Hung } 7782d2d89363f0b794cbb63f389584fa4c5557ff51aAndy Hung return track; 77935ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi } catch (IllegalArgumentException e) { 78035ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi throw new UnsupportedOperationException(e.getMessage()); 78135ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi } 78235ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi } 78335ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi } 78435ba5ab4503f4818f0dd131ad1d2bf91f7397cadJean-Michel Trivi 785340a6d09bdba7d4d99cef52a83a90fb96842c58aGlenn Kasten // mask of all the positional channels supported, however the allowed combinations 786340a6d09bdba7d4d99cef52a83a90fb96842c58aGlenn Kasten // are further restricted by the matching left/right rule and CHANNEL_COUNT_MAX 7871b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi private static final int SUPPORTED_OUT_CHANNELS = 7881b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi AudioFormat.CHANNEL_OUT_FRONT_LEFT | 7891b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi AudioFormat.CHANNEL_OUT_FRONT_RIGHT | 7901b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi AudioFormat.CHANNEL_OUT_FRONT_CENTER | 7911b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi AudioFormat.CHANNEL_OUT_LOW_FREQUENCY | 7921b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi AudioFormat.CHANNEL_OUT_BACK_LEFT | 7931b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi AudioFormat.CHANNEL_OUT_BACK_RIGHT | 794ad720aeea741d9058a7b4d326c9ab1b3ebcd7c62Andy Hung AudioFormat.CHANNEL_OUT_BACK_CENTER | 795ad720aeea741d9058a7b4d326c9ab1b3ebcd7c62Andy Hung AudioFormat.CHANNEL_OUT_SIDE_LEFT | 796ad720aeea741d9058a7b4d326c9ab1b3ebcd7c62Andy Hung AudioFormat.CHANNEL_OUT_SIDE_RIGHT; 7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Convenience method for the constructor's parameter checks. 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This is where constructor IllegalArgumentException-s are thrown 8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // postconditions: 8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // mChannelCount is valid 8029ea5e5564812bb88e62d0c4fae8f1d40d8a6e7e0Glenn Kasten // mChannelMask is valid 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // mAudioFormat is valid 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // mSampleRate is valid 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // mDataLoadMode is valid 806a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung private void audioParamCheck(int sampleRateInHz, int channelConfig, int channelIndexMask, 807a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung int audioFormat, int mode) { 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //-------------- 8095c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten // sample rate, note these values are subject to change 8101cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten if ((sampleRateInHz < AudioFormat.SAMPLE_RATE_HZ_MIN || 8111cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten sampleRateInHz > AudioFormat.SAMPLE_RATE_HZ_MAX) && 8121cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten sampleRateInHz != AudioFormat.SAMPLE_RATE_UNSPECIFIED) { 813f4e58051e22ad4e21c7cd436c37cc5665c194d1cGlenn Kasten throw new IllegalArgumentException(sampleRateInHz 814f4e58051e22ad4e21c7cd436c37cc5665c194d1cGlenn Kasten + "Hz is not a supported sample rate."); 8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 816896a7f5fee46c24d31e9403abdf5813e4bb84ca5Glenn Kasten mSampleRate = sampleRateInHz; 8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 818621dbc874047b7f8c227f12fe15f977618f1f2f8Phil Burk // IEC61937 is based on stereo. We could coerce it to stereo. 819621dbc874047b7f8c227f12fe15f977618f1f2f8Phil Burk // But the application needs to know the stream is stereo so that 820621dbc874047b7f8c227f12fe15f977618f1f2f8Phil Burk // it is encoded and played correctly. So better to just reject it. 821621dbc874047b7f8c227f12fe15f977618f1f2f8Phil Burk if (audioFormat == AudioFormat.ENCODING_IEC61937 822621dbc874047b7f8c227f12fe15f977618f1f2f8Phil Burk && channelConfig != AudioFormat.CHANNEL_OUT_STEREO) { 823621dbc874047b7f8c227f12fe15f977618f1f2f8Phil Burk throw new IllegalArgumentException( 824621dbc874047b7f8c227f12fe15f977618f1f2f8Phil Burk "ENCODING_IEC61937 must be configured as CHANNEL_OUT_STEREO"); 825621dbc874047b7f8c227f12fe15f977618f1f2f8Phil Burk } 826621dbc874047b7f8c227f12fe15f977618f1f2f8Phil Burk 8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //-------------- 8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // channel config 8293026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent mChannelConfiguration = channelConfig; 8303026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent 8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (channelConfig) { 8323026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent case AudioFormat.CHANNEL_OUT_DEFAULT: //AudioFormat.CHANNEL_CONFIGURATION_DEFAULT 833a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent case AudioFormat.CHANNEL_OUT_MONO: 8343026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent case AudioFormat.CHANNEL_CONFIGURATION_MONO: 8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChannelCount = 1; 8369ea5e5564812bb88e62d0c4fae8f1d40d8a6e7e0Glenn Kasten mChannelMask = AudioFormat.CHANNEL_OUT_MONO; 8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 838a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent case AudioFormat.CHANNEL_OUT_STEREO: 8393026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent case AudioFormat.CHANNEL_CONFIGURATION_STEREO: 8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChannelCount = 2; 8419ea5e5564812bb88e62d0c4fae8f1d40d8a6e7e0Glenn Kasten mChannelMask = AudioFormat.CHANNEL_OUT_STEREO; 8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 844a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung if (channelConfig == AudioFormat.CHANNEL_INVALID && channelIndexMask != 0) { 845a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung mChannelCount = 0; 846a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung break; // channel index configuration only 847a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung } 848d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi if (!isMultichannelConfigSupported(channelConfig)) { 8491b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi // input channel configuration features unsupported channels 850f4e58051e22ad4e21c7cd436c37cc5665c194d1cGlenn Kasten throw new IllegalArgumentException("Unsupported channel configuration."); 8511b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi } 8529ea5e5564812bb88e62d0c4fae8f1d40d8a6e7e0Glenn Kasten mChannelMask = channelConfig; 8538528ed43b41ff02535675c5da7425bef5195e73bAndy Hung mChannelCount = AudioFormat.channelCountFromOutChannelMask(channelConfig); 8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 855a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung // check the channel index configuration (if present) 856a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung mChannelIndexMask = channelIndexMask; 857a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung if (mChannelIndexMask != 0) { 858a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung // restrictive: indexMask could allow up to AUDIO_CHANNEL_BITS_LOG2 859a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung final int indexMask = (1 << CHANNEL_COUNT_MAX) - 1; 860a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung if ((channelIndexMask & ~indexMask) != 0) { 861a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung throw new IllegalArgumentException("Unsupported channel index configuration " 862a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung + channelIndexMask); 863a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung } 864a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung int channelIndexCount = Integer.bitCount(channelIndexMask); 865a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung if (mChannelCount == 0) { 866a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung mChannelCount = channelIndexCount; 867a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung } else if (mChannelCount != channelIndexCount) { 868a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung throw new IllegalArgumentException("Channel count must match"); 869a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung } 870a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung } 8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //-------------- 8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // audio format 874ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent if (audioFormat == AudioFormat.ENCODING_DEFAULT) { 875ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent audioFormat = AudioFormat.ENCODING_PCM_16BIT; 876ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent } 877ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent 878cae346633321e237f824f3ca10d7e6fff2307b2fEric Laurent if (!AudioFormat.isPublicEncoding(audioFormat)) { 879ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent throw new IllegalArgumentException("Unsupported audio encoding."); 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 881ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent mAudioFormat = audioFormat; 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //-------------- 8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // audio load mode 885ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent if (((mode != MODE_STREAM) && (mode != MODE_STATIC)) || 886ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent ((mode != MODE_STREAM) && !AudioFormat.isEncodingLinearPcm(mAudioFormat))) { 887f4e58051e22ad4e21c7cd436c37cc5665c194d1cGlenn Kasten throw new IllegalArgumentException("Invalid mode."); 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 889896a7f5fee46c24d31e9403abdf5813e4bb84ca5Glenn Kasten mDataLoadMode = mode; 8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 892d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi /** 893d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi * Convenience method to check that the channel configuration (a.k.a channel mask) is supported 894d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi * @param channelConfig the mask to validate 895d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi * @return false if the AudioTrack can't be used with such a mask 896d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi */ 897d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi private static boolean isMultichannelConfigSupported(int channelConfig) { 898d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi // check for unsupported channels 899d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi if ((channelConfig & SUPPORTED_OUT_CHANNELS) != channelConfig) { 9001f61d01508651b4475397414e1fe06af1ab8fadaGlenn Kasten loge("Channel configuration features unsupported channels"); 901d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi return false; 902d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi } 9038528ed43b41ff02535675c5da7425bef5195e73bAndy Hung final int channelCount = AudioFormat.channelCountFromOutChannelMask(channelConfig); 904ad720aeea741d9058a7b4d326c9ab1b3ebcd7c62Andy Hung if (channelCount > CHANNEL_COUNT_MAX) { 905ad720aeea741d9058a7b4d326c9ab1b3ebcd7c62Andy Hung loge("Channel configuration contains too many channels " + 906ad720aeea741d9058a7b4d326c9ab1b3ebcd7c62Andy Hung channelCount + ">" + CHANNEL_COUNT_MAX); 907ad720aeea741d9058a7b4d326c9ab1b3ebcd7c62Andy Hung return false; 908ad720aeea741d9058a7b4d326c9ab1b3ebcd7c62Andy Hung } 909d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi // check for unsupported multichannel combinations: 910d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi // - FL/FR must be present 911d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi // - L/R channels must be paired (e.g. no single L channel) 912d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi final int frontPair = 913d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi AudioFormat.CHANNEL_OUT_FRONT_LEFT | AudioFormat.CHANNEL_OUT_FRONT_RIGHT; 914d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi if ((channelConfig & frontPair) != frontPair) { 9151f61d01508651b4475397414e1fe06af1ab8fadaGlenn Kasten loge("Front channels must be present in multichannel configurations"); 916d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi return false; 917d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi } 918d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi final int backPair = 919d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi AudioFormat.CHANNEL_OUT_BACK_LEFT | AudioFormat.CHANNEL_OUT_BACK_RIGHT; 920d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi if ((channelConfig & backPair) != 0) { 921d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi if ((channelConfig & backPair) != backPair) { 9221f61d01508651b4475397414e1fe06af1ab8fadaGlenn Kasten loge("Rear channels can't be used independently"); 923d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi return false; 924d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi } 925d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi } 926ad720aeea741d9058a7b4d326c9ab1b3ebcd7c62Andy Hung final int sidePair = 927ad720aeea741d9058a7b4d326c9ab1b3ebcd7c62Andy Hung AudioFormat.CHANNEL_OUT_SIDE_LEFT | AudioFormat.CHANNEL_OUT_SIDE_RIGHT; 928ad720aeea741d9058a7b4d326c9ab1b3ebcd7c62Andy Hung if ((channelConfig & sidePair) != 0 929ad720aeea741d9058a7b4d326c9ab1b3ebcd7c62Andy Hung && (channelConfig & sidePair) != sidePair) { 930ad720aeea741d9058a7b4d326c9ab1b3ebcd7c62Andy Hung loge("Side channels can't be used independently"); 931ad720aeea741d9058a7b4d326c9ab1b3ebcd7c62Andy Hung return false; 932ad720aeea741d9058a7b4d326c9ab1b3ebcd7c62Andy Hung } 933d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi return true; 934d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi } 935d9e587137b926a56e6e339f11da6a91624df515aJean-Michel Trivi 9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 937e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten // Convenience method for the constructor's audio buffer size check. 9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // preconditions: 9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // mChannelCount is valid 9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // mAudioFormat is valid 9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // postcondition: 9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // mNativeBufferSizeInBytes is valid (multiple of frame size, positive) 9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void audioBuffSizeCheck(int audioBufferSize) { 94443f4b276a56e6fb5a3c9637c0e3a6865657e3be7Phil Burk // NB: this section is only valid with PCM or IEC61937 data. 9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // To update when supporting compressed formats 946ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent int frameSizeInBytes; 94743f4b276a56e6fb5a3c9637c0e3a6865657e3be7Phil Burk if (AudioFormat.isEncodingLinearFrames(mAudioFormat)) { 948340a6d09bdba7d4d99cef52a83a90fb96842c58aGlenn Kasten frameSizeInBytes = mChannelCount * AudioFormat.getBytesPerSample(mAudioFormat); 949ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent } else { 950ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent frameSizeInBytes = 1; 951ff0d9f098e51c54e1a030ed21fd980680cb7b405Eric Laurent } 9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((audioBufferSize % frameSizeInBytes != 0) || (audioBufferSize < 1)) { 953f4e58051e22ad4e21c7cd436c37cc5665c194d1cGlenn Kasten throw new IllegalArgumentException("Invalid audio buffer size."); 9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNativeBufferSizeInBytes = audioBufferSize; 957e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten mNativeBufferSizeInFrames = audioBufferSize / frameSizeInBytes; 9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Releases the native AudioTrack resources. 9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void release() { 9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // even though native_release() stops the native AudioTrack, we need to stop 9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // AudioTrack subclasses too. 9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stop(); 969fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten } catch(IllegalStateException ise) { 9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // don't raise an exception, we're releasing the resources. 9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9723c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi baseRelease(); 9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project native_release(); 9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState = STATE_UNINITIALIZED; 9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void finalize() { 9793c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi baseRelease(); 9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project native_finalize(); 9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //-------------------------------------------------------------------------- 9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Getters 9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //-------------------- 9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 98778cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * Returns the minimum gain value, which is the constant 0.0. 98878cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * Gain values less than 0.0 will be clamped to 0.0. 98978cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * <p>The word "volume" in the API name is historical; this is actually a linear gain. 99078cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * @return the minimum value, which is the constant 0.0. 9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static public float getMinVolume() { 99378cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten return GAIN_MIN; 9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 99778cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * Returns the maximum gain value, which is greater than or equal to 1.0. 99878cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * Gain values greater than the maximum will be clamped to the maximum. 99978cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * <p>The word "volume" in the API name is historical; this is actually a gain. 100078cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * expressed as a linear multiplier on sample values, where a maximum value of 1.0 100178cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * corresponds to a gain of 0 dB (sample values left unmodified). 100278cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * @return the maximum value, which is greater than or equal to 1.0. 10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static public float getMaxVolume() { 100578cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten return GAIN_MAX; 10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10091cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten * Returns the configured audio source sample rate in Hz. 10101cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten * The initial source sample rate depends on the constructor parameters, 10111cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten * but the source sample rate may change if {@link #setPlaybackRate(int)} is called. 10121cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten * If the constructor had a specific sample rate, then the initial sink sample rate is that 10131cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten * value. 10141cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten * If the constructor had {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED}, 10151cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten * then the initial sink sample rate is a route-dependent default value based on the source [sic]. 10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getSampleRate() { 10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mSampleRate; 10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1020fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten 10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1022263b4c97823295c41900210515d0c769a236190cAndy Hung * Returns the current playback sample rate rate in Hz. 10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getPlaybackRate() { 10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return native_get_playback_rate(); 10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10295f68c7a3f8400bcef233bf02d9a722f6d21f5c34Glenn Kasten * Returns the current playback parameters. 10305f68c7a3f8400bcef233bf02d9a722f6d21f5c34Glenn Kasten * See {@link #setPlaybackParams(PlaybackParams)} to set playback parameters 10312d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia * @return current {@link PlaybackParams}. 1032263b4c97823295c41900210515d0c769a236190cAndy Hung * @throws IllegalStateException if track is not initialized. 1033263b4c97823295c41900210515d0c769a236190cAndy Hung */ 10342d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia public @NonNull PlaybackParams getPlaybackParams() { 10352d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia return native_get_playback_params(); 1036263b4c97823295c41900210515d0c769a236190cAndy Hung } 1037263b4c97823295c41900210515d0c769a236190cAndy Hung 1038263b4c97823295c41900210515d0c769a236190cAndy Hung /** 1039463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung * Returns the configured audio data encoding. See {@link AudioFormat#ENCODING_PCM_8BIT}, 1040463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung * {@link AudioFormat#ENCODING_PCM_16BIT}, and {@link AudioFormat#ENCODING_PCM_FLOAT}. 10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getAudioFormat() { 10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mAudioFormat; 10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the type of audio stream this AudioTrack is configured for. 10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Compare the result against {@link AudioManager#STREAM_VOICE_CALL}, 10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link AudioManager#STREAM_SYSTEM}, {@link AudioManager#STREAM_RING}, 10505c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten * {@link AudioManager#STREAM_MUSIC}, {@link AudioManager#STREAM_ALARM}, 1051b282e08ab641d4fc74d0324b7a0ce30926638dd5Glenn Kasten * {@link AudioManager#STREAM_NOTIFICATION}, or {@link AudioManager#STREAM_DTMF}. 10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getStreamType() { 10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mStreamType; 10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1058a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung * Returns the configured channel position mask. 1059463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung * <p> For example, refer to {@link AudioFormat#CHANNEL_OUT_MONO}, 1060a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung * {@link AudioFormat#CHANNEL_OUT_STEREO}, {@link AudioFormat#CHANNEL_OUT_5POINT1}. 1061463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung * This method may return {@link AudioFormat#CHANNEL_INVALID} if 1062340a6d09bdba7d4d99cef52a83a90fb96842c58aGlenn Kasten * a channel index mask was used. Consider 1063463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung * {@link #getFormat()} instead, to obtain an {@link AudioFormat}, 1064463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung * which contains both the channel position mask and the channel index mask. 10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getChannelConfiguration() { 10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mChannelConfiguration; 10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1071463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung * Returns the configured <code>AudioTrack</code> format. 1072463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung * @return an {@link AudioFormat} containing the 1073463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung * <code>AudioTrack</code> parameters at the time of configuration. 1074463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung */ 1075463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung public @NonNull AudioFormat getFormat() { 1076463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung AudioFormat.Builder builder = new AudioFormat.Builder() 1077463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung .setSampleRate(mSampleRate) 1078463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung .setEncoding(mAudioFormat); 1079463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung if (mChannelConfiguration != AudioFormat.CHANNEL_INVALID) { 1080463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung builder.setChannelMask(mChannelConfiguration); 1081463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung } 1082463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung if (mChannelIndexMask != AudioFormat.CHANNEL_INVALID /* 0 */) { 1083463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung builder.setChannelIndexMask(mChannelIndexMask); 1084463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung } 1085463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung return builder.build(); 1086463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung } 1087463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung 1088463a8c7743c5187827a8ac56b7767b50ab491ca8Andy Hung /** 10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the configured number of channels. 10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getChannelCount() { 10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mChannelCount; 10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the state of the AudioTrack instance. This is useful after the 10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * AudioTrack instance has been created to check if it was initialized 1098e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * properly. This ensures that the appropriate resources have been acquired. 1099340a6d09bdba7d4d99cef52a83a90fb96842c58aGlenn Kasten * @see #STATE_UNINITIALIZED 1100ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi * @see #STATE_INITIALIZED 1101ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi * @see #STATE_NO_STATIC_DATA 11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getState() { 11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mState; 11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the playback state of the AudioTrack instance. 11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #PLAYSTATE_STOPPED 11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #PLAYSTATE_PAUSED 11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #PLAYSTATE_PLAYING 11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getPlayState() { 111406e0333c7eb50533cc6e0f7b61812d2840844296Narayan Kamath synchronized (mPlayStateLock) { 111506e0333c7eb50533cc6e0f7b61812d2840844296Narayan Kamath return mPlayState; 111606e0333c7eb50533cc6e0f7b61812d2840844296Narayan Kamath } 11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1119cd0e210651da3d0f35f3ae164379c7ab71eb58ccPhil Burk 112010a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk /** 1121cd0e210651da3d0f35f3ae164379c7ab71eb58ccPhil Burk * Returns the effective size of the <code>AudioTrack</code> buffer 112210a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk * that the application writes to. 1123cd0e210651da3d0f35f3ae164379c7ab71eb58ccPhil Burk * <p> This will be less than or equal to the result of 1124cd0e210651da3d0f35f3ae164379c7ab71eb58ccPhil Burk * {@link #getBufferCapacityInFrames()}. 1125cd0e210651da3d0f35f3ae164379c7ab71eb58ccPhil Burk * It will be equal if {@link #setBufferSizeInFrames(int)} has never been called. 1126cd0e210651da3d0f35f3ae164379c7ab71eb58ccPhil Burk * <p> If the track is subsequently routed to a different output sink, the buffer 1127cd0e210651da3d0f35f3ae164379c7ab71eb58ccPhil Burk * size and capacity may enlarge to accommodate. 1128cd0e210651da3d0f35f3ae164379c7ab71eb58ccPhil Burk * <p> If the <code>AudioTrack</code> encoding indicates compressed data, 1129cd0e210651da3d0f35f3ae164379c7ab71eb58ccPhil Burk * e.g. {@link AudioFormat#ENCODING_AC3}, then the frame count returned is 11301d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * the size of the <code>AudioTrack</code> buffer in bytes. 1131cd0e210651da3d0f35f3ae164379c7ab71eb58ccPhil Burk * <p> See also {@link AudioManager#getProperty(String)} for key 1132cd0e210651da3d0f35f3ae164379c7ab71eb58ccPhil Burk * {@link AudioManager#PROPERTY_OUTPUT_FRAMES_PER_BUFFER}. 1133cd0e210651da3d0f35f3ae164379c7ab71eb58ccPhil Burk * @return current size in frames of the <code>AudioTrack</code> buffer. 1134eeecfa44010321952a2f156bb883ca8a1331a451Phil Burk * @throws IllegalStateException if track is not initialized. 113510a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk */ 113610a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk public int getBufferSizeInFrames() { 113710a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk return native_get_buffer_size_frames(); 113810a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk } 113910a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk 114010a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk /** 114110a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk * Limits the effective size of the <code>AudioTrack</code> buffer 114210a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk * that the application writes to. 114310a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk * <p> A write to this AudioTrack will not fill the buffer beyond this limit. 11441d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * If a blocking write is used then the write will block until the data 114510a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk * can fit within this limit. 114610a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk * <p>Changing this limit modifies the latency associated with 114710a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk * the buffer for this track. A smaller size will give lower latency 114810a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk * but there may be more glitches due to buffer underruns. 1149cd0e210651da3d0f35f3ae164379c7ab71eb58ccPhil Burk * <p>The actual size used may not be equal to this requested size. 115010a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk * It will be limited to a valid range with a maximum of 1151cd0e210651da3d0f35f3ae164379c7ab71eb58ccPhil Burk * {@link #getBufferCapacityInFrames()}. 115210a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk * It may also be adjusted slightly for internal reasons. 115310a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk * If bufferSizeInFrames is less than zero then {@link #ERROR_BAD_VALUE} 115410a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk * will be returned. 115510a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk * <p>This method is only supported for PCM audio. 115610a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk * It is not supported for compressed audio tracks. 115710a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk * 11581d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * @param bufferSizeInFrames requested buffer size in frames 1159cd0e210651da3d0f35f3ae164379c7ab71eb58ccPhil Burk * @return the actual buffer size in frames or an error code, 1160cd0e210651da3d0f35f3ae164379c7ab71eb58ccPhil Burk * {@link #ERROR_BAD_VALUE}, {@link #ERROR_INVALID_OPERATION} 1161eeecfa44010321952a2f156bb883ca8a1331a451Phil Burk * @throws IllegalStateException if track is not initialized. 116210a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk */ 116310a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk public int setBufferSizeInFrames(int bufferSizeInFrames) { 116410a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk if (mDataLoadMode == MODE_STATIC || mState == STATE_UNINITIALIZED) { 116510a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk return ERROR_INVALID_OPERATION; 116610a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk } 116710a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk if (bufferSizeInFrames < 0) { 116810a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk return ERROR_BAD_VALUE; 116910a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk } 117010a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk return native_set_buffer_size_frames(bufferSizeInFrames); 117110a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk } 117210a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk 11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 11741d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * Returns the maximum size of the <code>AudioTrack</code> buffer in frames. 11754bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung * <p> If the track's creation mode is {@link #MODE_STATIC}, 11764bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung * it is equal to the specified bufferSizeInBytes on construction, converted to frame units. 11771d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * A static track's frame count will not change. 11784bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung * <p> If the track's creation mode is {@link #MODE_STREAM}, 11794bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung * it is greater than or equal to the specified bufferSizeInBytes converted to frame units. 11804bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung * For streaming tracks, this value may be rounded up to a larger value if needed by 11814bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung * the target output sink, and 11821d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * if the track is subsequently routed to a different output sink, the 11834bd513e6ed168811c97dbc83cd5a7c7cc43caffeAndy Hung * frame count may enlarge to accommodate. 1184e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung * <p> If the <code>AudioTrack</code> encoding indicates compressed data, 1185e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung * e.g. {@link AudioFormat#ENCODING_AC3}, then the frame count returned is 11861d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * the size of the <code>AudioTrack</code> buffer in bytes. 1187e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung * <p> See also {@link AudioManager#getProperty(String)} for key 118855a3218f242a611afb3569d88970c0c5dbf8ce54Glenn Kasten * {@link AudioManager#PROPERTY_OUTPUT_FRAMES_PER_BUFFER}. 118910a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk * @return maximum size in frames of the <code>AudioTrack</code> buffer. 1190eeecfa44010321952a2f156bb883ca8a1331a451Phil Burk * @throws IllegalStateException if track is not initialized. 11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 119210a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk public int getBufferCapacityInFrames() { 119310a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk return native_get_buffer_capacity_frames(); 1194e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung } 1195e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung 1196e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung /** 1197e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung * Returns the frame count of the native <code>AudioTrack</code> buffer. 1198e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung * @return current size in frames of the <code>AudioTrack</code> buffer. 1199e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung * @throws IllegalStateException 1200e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung * @deprecated Use the identical public method {@link #getBufferSizeInFrames()} instead. 1201e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung */ 1202e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung @Deprecated 1203e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung protected int getNativeFrameCount() { 120410a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk return native_get_buffer_capacity_frames(); 12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1208ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi * Returns marker position expressed in frames. 1209e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * @return marker position in wrapping frame units similar to {@link #getPlaybackHeadPosition}, 1210e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * or zero if marker is disabled. 12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getNotificationMarkerPosition() { 12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return native_get_marker_pos(); 12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1217ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi * Returns the notification update period expressed in frames. 1218e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * Zero means that no position update notifications are being delivered. 12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getPositionNotificationPeriod() { 12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return native_get_pos_update_period(); 12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1225e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * Returns the playback head position expressed in frames. 1226e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * Though the "int" type is signed 32-bits, the value should be reinterpreted as if it is 1227e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * unsigned 32-bits. That is, the next position after 0x7FFFFFFF is (int) 0x80000000. 1228e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * This is a continuously advancing counter. It will wrap (overflow) periodically, 1229e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * for example approximately once every 27:03:11 hours:minutes:seconds at 44.1 kHz. 1230ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * It is reset to zero by {@link #flush()}, {@link #reloadStaticData()}, and {@link #stop()}. 1231ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * If the track's creation mode is {@link #MODE_STATIC}, the return value indicates 1232ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * the total number of frames played since reset, 1233ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * <i>not</i> the current offset within the buffer. 12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getPlaybackHeadPosition() { 12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return native_get_position(); 12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 124061dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman * Returns this track's estimated latency in milliseconds. This includes the latency due 124161dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman * to AudioTrack buffer size, AudioMixer (if any) and audio hardware driver. 124261dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman * 124361dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman * DO NOT UNHIDE. The existing approach for doing A/V sync has too many problems. We need 124461dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman * a better solution. 124561dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman * @hide 124661dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman */ 124761dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman public int getLatency() { 124861dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman return native_get_latency(); 124961dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman } 125061dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman 125161dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman /** 125203f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk * Returns the number of underrun occurrences in the application-level write buffer 125303f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk * since the AudioTrack was created. 125403f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk * An underrun occurs if the application does not write audio 125503f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk * data quickly enough, causing the buffer to underflow 125603f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk * and a potential audio glitch or pop. 12572bf39d8e9f9bdcbe548f8bd8acb89def382b467dPhil Burk * <p> 125803f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk * Underruns are less likely when buffer sizes are large. 12592bf39d8e9f9bdcbe548f8bd8acb89def382b467dPhil Burk * It may be possible to eliminate underruns by recreating the AudioTrack with 12602bf39d8e9f9bdcbe548f8bd8acb89def382b467dPhil Burk * a larger buffer. 12612bf39d8e9f9bdcbe548f8bd8acb89def382b467dPhil Burk * Or by using {@link #setBufferSizeInFrames(int)} to dynamically increase the 12622bf39d8e9f9bdcbe548f8bd8acb89def382b467dPhil Burk * effective size of the buffer. 126303f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk */ 126403f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk public int getUnderrunCount() { 126503f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk return native_get_underrun_count(); 126603f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk } 126703f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk 126803f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk /** 1269e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * Returns the output sample rate in Hz for the specified stream type. 12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static public int getNativeOutputSampleRate(int streamType) { 12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return native_get_output_sample_rate(streamType); 12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1274fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten 12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 12761d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * Returns the estimated minimum buffer size required for an AudioTrack 12771d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * object to be created in the {@link #MODE_STREAM} mode. 12781d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * The size is an estimate because it does not consider either the route or the sink, 12791d46276a6240224b096208fc37b45e8926bb89a8Glenn Kasten * since neither is known yet. Note that this size doesn't 1280ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi * guarantee a smooth playback under load, and higher values should be chosen according to 1281fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten * the expected frequency at which the buffer will be refilled with additional data to play. 12828d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten * For example, if you intend to dynamically set the source sample rate of an AudioTrack 12838d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten * to a higher value than the initial source sample rate, be sure to configure the buffer size 12848d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten * based on the highest planned sample rate. 12858d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten * @param sampleRateInHz the source sample rate expressed in Hz. 12861cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten * {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED} is not permitted. 1287fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten * @param channelConfig describes the configuration of the audio channels. 1288a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent * See {@link AudioFormat#CHANNEL_OUT_MONO} and 1289a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent * {@link AudioFormat#CHANNEL_OUT_STEREO} 1290fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten * @param audioFormat the format in which the audio data is represented. 1291fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten * See {@link AudioFormat#ENCODING_PCM_16BIT} and 12927d60bcd2d950e3571c00ce9f1c492c6bd58334c9Glenn Kasten * {@link AudioFormat#ENCODING_PCM_8BIT}, 12937d60bcd2d950e3571c00ce9f1c492c6bd58334c9Glenn Kasten * and {@link AudioFormat#ENCODING_PCM_FLOAT}. 12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return {@link #ERROR_BAD_VALUE} if an invalid parameter was passed, 1295e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * or {@link #ERROR} if unable to query for output properties, 1296ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi * or the minimum buffer size expressed in bytes. 12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static public int getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat) { 12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int channelCount = 0; 13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch(channelConfig) { 1301a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent case AudioFormat.CHANNEL_OUT_MONO: 13023026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent case AudioFormat.CHANNEL_CONFIGURATION_MONO: 13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project channelCount = 1; 13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 1305a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent case AudioFormat.CHANNEL_OUT_STEREO: 13063026a023b8979b7ddcb3fe97bbc45531c89fda92Eric Laurent case AudioFormat.CHANNEL_CONFIGURATION_STEREO: 13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project channelCount = 2; 13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 1310a9470c19a9dfe362a201c569f14b669b7aa69ee4Andy Hung if (!isMultichannelConfigSupported(channelConfig)) { 13111b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi loge("getMinBufferSize(): Invalid channel configuration."); 1312df3cb5279857cac41909643c6703e8fc1621fad1Glenn Kasten return ERROR_BAD_VALUE; 13131b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi } else { 13148528ed43b41ff02535675c5da7425bef5195e73bAndy Hung channelCount = AudioFormat.channelCountFromOutChannelMask(channelConfig); 13151b8f499a14a4340d3422d95c7f6fdc8c0c72b3a4Jean-Michel Trivi } 13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1317fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten 1318cae346633321e237f824f3ca10d7e6fff2307b2fEric Laurent if (!AudioFormat.isPublicEncoding(audioFormat)) { 13199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project loge("getMinBufferSize(): Invalid audio format."); 1320df3cb5279857cac41909643c6703e8fc1621fad1Glenn Kasten return ERROR_BAD_VALUE; 13219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1322fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten 13235c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten // sample rate, note these values are subject to change 13241cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten // Note: AudioFormat.SAMPLE_RATE_UNSPECIFIED is not allowed 13251cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten if ( (sampleRateInHz < AudioFormat.SAMPLE_RATE_HZ_MIN) || 13261cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten (sampleRateInHz > AudioFormat.SAMPLE_RATE_HZ_MAX) ) { 1327ad67c9546494a7c4d9336b57889a7c19a7dbb945Glenn Kasten loge("getMinBufferSize(): " + sampleRateInHz + " Hz is not a supported sample rate."); 1328df3cb5279857cac41909643c6703e8fc1621fad1Glenn Kasten return ERROR_BAD_VALUE; 13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1330fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten 13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int size = native_get_min_buff_size(sampleRateInHz, channelCount, audioFormat); 1332a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten if (size <= 0) { 13339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project loge("getMinBufferSize(): error querying hardware"); 1334df3cb5279857cac41909643c6703e8fc1621fad1Glenn Kasten return ERROR; 13359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else { 13379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return size; 13389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1341619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent /** 1342619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent * Returns the audio session ID. 1343619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent * 1344619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent * @return the ID of the audio session this AudioTrack belongs to. 1345619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent */ 1346619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent public int getAudioSessionId() { 1347619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent return mSessionId; 1348619346f902241736d933657a4fe10f10c50a1ba8Eric Laurent } 13499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1350948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten /** 1351948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten * Poll for a timestamp on demand. 1352486918b41584cd2589c46c5217b3fba1e7d18874Glenn Kasten * <p> 1353486918b41584cd2589c46c5217b3fba1e7d18874Glenn Kasten * If you need to track timestamps during initial warmup or after a routing or mode change, 135400908b6c6964346af4d2512ba161a109912d97b8Glenn Kasten * you should request a new timestamp periodically until the reported timestamps 135500908b6c6964346af4d2512ba161a109912d97b8Glenn Kasten * show that the frame position is advancing, or until it becomes clear that 135600908b6c6964346af4d2512ba161a109912d97b8Glenn Kasten * timestamps are unavailable for this route. 135700908b6c6964346af4d2512ba161a109912d97b8Glenn Kasten * <p> 135800908b6c6964346af4d2512ba161a109912d97b8Glenn Kasten * After the clock is advancing at a stable rate, 135900908b6c6964346af4d2512ba161a109912d97b8Glenn Kasten * query for a new timestamp approximately once every 10 seconds to once per minute. 1360486918b41584cd2589c46c5217b3fba1e7d18874Glenn Kasten * Calling this method more often is inefficient. 1361486918b41584cd2589c46c5217b3fba1e7d18874Glenn Kasten * It is also counter-productive to call this method more often than recommended, 1362486918b41584cd2589c46c5217b3fba1e7d18874Glenn Kasten * because the short-term differences between successive timestamp reports are not meaningful. 1363486918b41584cd2589c46c5217b3fba1e7d18874Glenn Kasten * If you need a high-resolution mapping between frame position and presentation time, 1364948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten * consider implementing that at application level, based on low-resolution timestamps. 1365486918b41584cd2589c46c5217b3fba1e7d18874Glenn Kasten * <p> 1366948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten * The audio data at the returned position may either already have been 1367948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten * presented, or may have not yet been presented but is committed to be presented. 1368948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten * It is not possible to request the time corresponding to a particular position, 1369948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten * or to request the (fractional) position corresponding to a particular time. 1370948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten * If you need such features, consider implementing them at application level. 1371948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten * 1372948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten * @param timestamp a reference to a non-null AudioTimestamp instance allocated 1373596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten * and owned by caller. 1374596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten * @return true if a timestamp is available, or false if no timestamp is available. 1375596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten * If a timestamp if available, 1376948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten * the AudioTimestamp instance is filled in with a position in frame units, together 1377948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten * with the estimated time when that frame was presented or is committed to 1378948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten * be presented. 1379948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten * In the case that no timestamp is available, any supplied instance is left unaltered. 1380c52f4e25e21719d5d637a588e3200be941b9fe4dGlenn Kasten * A timestamp may be temporarily unavailable while the audio clock is stabilizing, 1381c52f4e25e21719d5d637a588e3200be941b9fe4dGlenn Kasten * or during and immediately after a route change. 138200908b6c6964346af4d2512ba161a109912d97b8Glenn Kasten * A timestamp is permanently unavailable for a given route if the route does not support 138300908b6c6964346af4d2512ba161a109912d97b8Glenn Kasten * timestamps. In this case, the approximate frame position can be obtained 138400908b6c6964346af4d2512ba161a109912d97b8Glenn Kasten * using {@link #getPlaybackHeadPosition}. 138500908b6c6964346af4d2512ba161a109912d97b8Glenn Kasten * However, it may be useful to continue to query for 138600908b6c6964346af4d2512ba161a109912d97b8Glenn Kasten * timestamps occasionally, to recover after a route change. 1387948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten */ 1388486918b41584cd2589c46c5217b3fba1e7d18874Glenn Kasten // Add this text when the "on new timestamp" API is added: 1389486918b41584cd2589c46c5217b3fba1e7d18874Glenn Kasten // Use if you need to get the most recent timestamp outside of the event callback handler. 1390596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten public boolean getTimestamp(AudioTimestamp timestamp) 1391948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten { 1392596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten if (timestamp == null) { 1393596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten throw new IllegalArgumentException(); 1394596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten } 1395948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten // It's unfortunate, but we have to either create garbage every time or use synchronized 1396948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten long[] longArray = new long[2]; 1397948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten int ret = native_get_timestamp(longArray); 1398596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten if (ret != SUCCESS) { 1399596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten return false; 1400948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten } 1401596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten timestamp.framePosition = longArray[0]; 1402596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten timestamp.nanoTime = longArray[1]; 1403596fb8e7969cafdf7f25dfdc97372be4c0950cc3Glenn Kasten return true; 1404948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten } 1405948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten 14064e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent /** 14074e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent * Poll for a timestamp on demand. 14084e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent * <p> 14094e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent * Same as {@link #getTimestamp(AudioTimestamp)} but with a more useful return code. 14104e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent * 14114e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent * @param timestamp a reference to a non-null AudioTimestamp instance allocated 14124e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent * and owned by caller. 14134e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent * @return {@link #SUCCESS} if a timestamp is available 14144e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent * {@link #ERROR_WOULD_BLOCK} if called in STOPPED or FLUSHED state, or if called 14154e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent * immediately after start/ACTIVE, when the number of frames consumed is less than the 14164e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent * overall hardware latency to physical output. In WOULD_BLOCK cases, one might poll 14174e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent * again, or use {@link #getPlaybackHeadPosition}, or use 0 position and current time 14184e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent * for the timestamp. 14194e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent * {@link #ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and 14204e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent * needs to be recreated. 14214e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent * {@link #ERROR_INVALID_OPERATION} if current route does not support 14224e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent * timestamps. In this case, the approximate frame position can be obtained 14234e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent * using {@link #getPlaybackHeadPosition}. 14244e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent * 14254e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent * The AudioTimestamp instance is filled in with a position in frame units, together 14264e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent * with the estimated time when that frame was presented or is committed to 14274e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent * be presented. 14284e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent * @hide 14294e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent */ 14304e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent // Add this text when the "on new timestamp" API is added: 14314e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent // Use if you need to get the most recent timestamp outside of the event callback handler. 14324e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent public int getTimestampWithStatus(AudioTimestamp timestamp) 14334e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent { 14344e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent if (timestamp == null) { 14354e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent throw new IllegalArgumentException(); 14364e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent } 14374e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent // It's unfortunate, but we have to either create garbage every time or use synchronized 14384e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent long[] longArray = new long[2]; 14394e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent int ret = native_get_timestamp(longArray); 14404e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent timestamp.framePosition = longArray[0]; 14414e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent timestamp.nanoTime = longArray[1]; 14424e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent return ret; 14434e1ccd370fc268f3207c5baee08ac8c943c3fdf9Eric Laurent } 1444948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten 14459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //-------------------------------------------------------------------------- 14469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Initialization / configuration 14479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //-------------------- 14489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 14494df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project * Sets the listener the AudioTrack notifies when a previously set marker is reached or 14504df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project * for each periodic playback head position update. 1451ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi * Notifications will be received in the same thread as the one in which the AudioTrack 1452ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi * instance was created. 14539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param listener 14549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 14554df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project public void setPlaybackPositionUpdateListener(OnPlaybackPositionUpdateListener listener) { 14564df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project setPlaybackPositionUpdateListener(listener, null); 14579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1458fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten 1459ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi /** 1460ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi * Sets the listener the AudioTrack notifies when a previously set marker is reached or 1461ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi * for each periodic playback head position update. 1462ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi * Use this method to receive AudioTrack events in the Handler associated with another 1463ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi * thread than the one in which you created the AudioTrack instance. 1464ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi * @param listener 1465ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi * @param handler the Handler that will receive the event notification messages. 1466ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi */ 1467fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten public void setPlaybackPositionUpdateListener(OnPlaybackPositionUpdateListener listener, 14684df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project Handler handler) { 14694df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project if (listener != null) { 1470d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean mEventHandlerDelegate = new NativePositionEventHandlerDelegate(this, listener, handler); 147195bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten } else { 147295bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten mEventHandlerDelegate = null; 14739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 147778cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten private static float clampGainOrLevel(float gainOrLevel) { 147878cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten if (Float.isNaN(gainOrLevel)) { 147978cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten throw new IllegalArgumentException(); 148078cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten } 148178cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten if (gainOrLevel < GAIN_MIN) { 148278cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten gainOrLevel = GAIN_MIN; 148378cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten } else if (gainOrLevel > GAIN_MAX) { 148478cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten gainOrLevel = GAIN_MAX; 148578cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten } 148678cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten return gainOrLevel; 148778cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten } 148878cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten 14894df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project 14909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 149178cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * Sets the specified left and right output gain values on the AudioTrack. 149278cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * <p>Gain values are clamped to the closed interval [0.0, max] where 149378cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * max is the value of {@link #getMaxVolume}. 149478cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * A value of 0.0 results in zero gain (silence), and 149578cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * a value of 1.0 means unity gain (signal unchanged). 149678cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * The default value is 1.0 meaning unity gain. 149778cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * <p>The word "volume" in the API name is historical; this is actually a linear gain. 149878cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * @param leftGain output gain for the left channel. 149978cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * @param rightGain output gain for the right channel 15009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return error code or success, see {@link #SUCCESS}, 15019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #ERROR_INVALID_OPERATION} 150278cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * @deprecated Applications should use {@link #setVolume} instead, as it 150378cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * more gracefully scales down to mono, and up to multi-channel content beyond stereo. 15049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1505ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey @Deprecated 150678cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten public int setStereoVolume(float leftGain, float rightGain) { 15073b4df62704a6184878afd9272830cf3db7bd2d66Glenn Kasten if (mState == STATE_UNINITIALIZED) { 15089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ERROR_INVALID_OPERATION; 15099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15113c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi baseSetVolume(leftGain, rightGain); 15123c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi return SUCCESS; 15133c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi } 15149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15153c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi @Override 15163c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi void playerSetVolume(float leftVolume, float rightVolume) { 15173c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi leftVolume = clampGainOrLevel(leftVolume); 15183c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi rightVolume = clampGainOrLevel(rightVolume); 15199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15203c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi native_setVolume(leftVolume, rightVolume); 15219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 152578cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * Sets the specified output gain value on all channels of this track. 152678cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * <p>Gain values are clamped to the closed interval [0.0, max] where 152778cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * max is the value of {@link #getMaxVolume}. 152878cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * A value of 0.0 results in zero gain (silence), and 152978cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * a value of 1.0 means unity gain (signal unchanged). 153078cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * The default value is 1.0 meaning unity gain. 153178cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * <p>This API is preferred over {@link #setStereoVolume}, as it 153278cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * more gracefully scales down to mono, and up to multi-channel content beyond stereo. 153378cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * <p>The word "volume" in the API name is historical; this is actually a linear gain. 153478cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * @param gain output gain for all channels. 15353e21cc8140e42bdcd924590e5e12446b6c55ad2aGlenn Kasten * @return error code or success, see {@link #SUCCESS}, 15363e21cc8140e42bdcd924590e5e12446b6c55ad2aGlenn Kasten * {@link #ERROR_INVALID_OPERATION} 1537068225de0197df07a0247b2877666ea91c22c992Glenn Kasten */ 153878cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten public int setVolume(float gain) { 153978cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten return setStereoVolume(gain, gain); 1540068225de0197df07a0247b2877666ea91c22c992Glenn Kasten } 1541068225de0197df07a0247b2877666ea91c22c992Glenn Kasten 1542068225de0197df07a0247b2877666ea91c22c992Glenn Kasten 1543068225de0197df07a0247b2877666ea91c22c992Glenn Kasten /** 15449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the playback sample rate for this track. This sets the sampling rate at which 15458d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten * the audio data will be consumed and played back 15468d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten * (as set by the sampleRateInHz parameter in the 15478d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten * {@link #AudioTrack(int, int, int, int, int, int)} constructor), 15488d7fa137466c833ed422053204fb4c506b7bb209Glenn Kasten * not the original sampling rate of the 1549e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * content. For example, setting it to half the sample rate of the content will cause the 1550e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * playback to last twice as long, but will also result in a pitch shift down by one octave. 1551e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * The valid sample rate range is from 1 Hz to twice the value returned by 155288e209dcf8c2ebddda5c272f46d1bd5478bc639cEric Laurent * {@link #getNativeOutputSampleRate(int)}. 15532d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia * Use {@link #setPlaybackParams(PlaybackParams)} for speed control. 1554e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung * <p> This method may also be used to repurpose an existing <code>AudioTrack</code> 1555e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung * for playback of content of differing sample rate, 1556e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung * but with identical encoding and channel mask. 1557ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi * @param sampleRateInHz the sample rate expressed in Hz 15589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE}, 15599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #ERROR_INVALID_OPERATION} 15609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 15619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int setPlaybackRate(int sampleRateInHz) { 1562f19395db6343efdf80d064e0ba7c3b9aa4dbae75Glenn Kasten if (mState != STATE_INITIALIZED) { 15639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ERROR_INVALID_OPERATION; 15649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sampleRateInHz <= 0) { 15669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ERROR_BAD_VALUE; 15679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 156888e209dcf8c2ebddda5c272f46d1bd5478bc639cEric Laurent return native_set_playback_rate(sampleRateInHz); 15699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 15735f68c7a3f8400bcef233bf02d9a722f6d21f5c34Glenn Kasten * Sets the playback parameters. 15745f68c7a3f8400bcef233bf02d9a722f6d21f5c34Glenn Kasten * This method returns failure if it cannot apply the playback parameters. 1575263b4c97823295c41900210515d0c769a236190cAndy Hung * One possible cause is that the parameters for speed or pitch are out of range. 1576263b4c97823295c41900210515d0c769a236190cAndy Hung * Another possible cause is that the <code>AudioTrack</code> is streaming 1577263b4c97823295c41900210515d0c769a236190cAndy Hung * (see {@link #MODE_STREAM}) and the 1578263b4c97823295c41900210515d0c769a236190cAndy Hung * buffer size is too small. For speeds greater than 1.0f, the <code>AudioTrack</code> buffer 1579263b4c97823295c41900210515d0c769a236190cAndy Hung * on configuration must be larger than the speed multiplied by the minimum size 1580263b4c97823295c41900210515d0c769a236190cAndy Hung * {@link #getMinBufferSize(int, int, int)}) to allow proper playback. 15812d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia * @param params see {@link PlaybackParams}. In particular, 1582263b4c97823295c41900210515d0c769a236190cAndy Hung * speed, pitch, and audio mode should be set. 15835f68c7a3f8400bcef233bf02d9a722f6d21f5c34Glenn Kasten * @throws IllegalArgumentException if the parameters are invalid or not accepted. 1584263b4c97823295c41900210515d0c769a236190cAndy Hung * @throws IllegalStateException if track is not initialized. 1585263b4c97823295c41900210515d0c769a236190cAndy Hung */ 15862d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia public void setPlaybackParams(@NonNull PlaybackParams params) { 15872d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia if (params == null) { 15882d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia throw new IllegalArgumentException("params is null"); 1589263b4c97823295c41900210515d0c769a236190cAndy Hung } 15902d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia native_set_playback_params(params); 1591263b4c97823295c41900210515d0c769a236190cAndy Hung } 1592263b4c97823295c41900210515d0c769a236190cAndy Hung 1593263b4c97823295c41900210515d0c769a236190cAndy Hung 1594263b4c97823295c41900210515d0c769a236190cAndy Hung /** 1595e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * Sets the position of the notification marker. At most one marker can be active. 1596e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * @param markerInFrames marker position in wrapping frame units similar to 1597e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * {@link #getPlaybackHeadPosition}, or zero to disable the marker. 1598e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * To set a marker at a position which would appear as zero due to wraparound, 1599e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * a workaround is to use a non-zero position near zero, such as -1 or 1. 16009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE}, 16019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #ERROR_INVALID_OPERATION} 16029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 16039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int setNotificationMarkerPosition(int markerInFrames) { 16043b4df62704a6184878afd9272830cf3db7bd2d66Glenn Kasten if (mState == STATE_UNINITIALIZED) { 16059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ERROR_INVALID_OPERATION; 16069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return native_set_marker_pos(markerInFrames); 16089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1612ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi * Sets the period for the periodic notification event. 1613ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * @param periodInFrames update period expressed in frames. 1614ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * Zero period means no position updates. A negative period is not allowed. 16159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_INVALID_OPERATION} 16169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 16179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int setPositionNotificationPeriod(int periodInFrames) { 16183b4df62704a6184878afd9272830cf3db7bd2d66Glenn Kasten if (mState == STATE_UNINITIALIZED) { 16199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ERROR_INVALID_OPERATION; 16209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return native_set_pos_update_period(periodInFrames); 16229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1626ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * Sets the playback head position within the static buffer. 1627a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten * The track must be stopped or paused for the position to be changed, 1628a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten * and must use the {@link #MODE_STATIC} mode. 1629ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * @param positionInFrames playback head position within buffer, expressed in frames. 1630e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * Zero corresponds to start of buffer. 1631e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * The position must not be greater than the buffer size in frames, or negative. 1632ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * Though this method and {@link #getPlaybackHeadPosition()} have similar names, 1633ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * the position values have different meanings. 1634ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * <br> 1635ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * If looping is currently enabled and the new position is greater than or equal to the 163635e576e79292122fad462ebccd8520822552a6d7Andy Hung * loop end marker, the behavior varies by API level: 16370e3de6cacaffcfeda4d6353be61e2f1f9ed80705Dianne Hackborn * as of {@link android.os.Build.VERSION_CODES#M}, 1638ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * the looping is first disabled and then the position is set. 1639ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * For earlier API levels, the behavior is unspecified. 16409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE}, 16419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #ERROR_INVALID_OPERATION} 16429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 16439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int setPlaybackHeadPosition(int positionInFrames) { 164478bfa6322bf34e49d5e4426296c701a64f705e49Andy Hung if (mDataLoadMode == MODE_STREAM || mState == STATE_UNINITIALIZED || 1645a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten getPlayState() == PLAYSTATE_PLAYING) { 1646a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten return ERROR_INVALID_OPERATION; 16479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1648e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten if (!(0 <= positionInFrames && positionInFrames <= mNativeBufferSizeInFrames)) { 1649e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten return ERROR_BAD_VALUE; 1650e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten } 1651a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten return native_set_position(positionInFrames); 16529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 16559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the loop points and the loop count. The loop can be infinite. 1656a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten * Similarly to setPlaybackHeadPosition, 1657e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * the track must be stopped or paused for the loop points to be changed, 1658a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten * and must use the {@link #MODE_STATIC} mode. 1659ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * @param startInFrames loop start marker expressed in frames. 1660e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * Zero corresponds to start of buffer. 1661e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * The start marker must not be greater than or equal to the buffer size in frames, or negative. 1662ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * @param endInFrames loop end marker expressed in frames. 1663e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * The total buffer size in frames corresponds to end of buffer. 1664e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * The end marker must not be greater than the buffer size in frames. 1665e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * For looping, the end marker must not be less than or equal to the start marker, 1666e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * but to disable looping 1667e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * it is permitted for start marker, end marker, and loop count to all be 0. 1668ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * If any input parameters are out of range, this method returns {@link #ERROR_BAD_VALUE}. 1669ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * If the loop period (endInFrames - startInFrames) is too small for the implementation to 1670ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * support, 1671ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * {@link #ERROR_BAD_VALUE} is returned. 1672ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * The loop range is the interval [startInFrames, endInFrames). 1673ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * <br> 16740e3de6cacaffcfeda4d6353be61e2f1f9ed80705Dianne Hackborn * As of {@link android.os.Build.VERSION_CODES#M}, the position is left unchanged, 1675ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * unless it is greater than or equal to the loop end marker, in which case 1676ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * it is forced to the loop start marker. 1677ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * For earlier API levels, the effect on position is unspecified. 1678ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * @param loopCount the number of times the loop is looped; must be greater than or equal to -1. 1679e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * A value of -1 means infinite looping, and 0 disables looping. 1680ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * A value of positive N means to "loop" (go back) N times. For example, 1681ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * a value of one means to play the region two times in total. 16829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE}, 16839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #ERROR_INVALID_OPERATION} 16849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 16859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int setLoopPoints(int startInFrames, int endInFrames, int loopCount) { 168678bfa6322bf34e49d5e4426296c701a64f705e49Andy Hung if (mDataLoadMode == MODE_STREAM || mState == STATE_UNINITIALIZED || 1687a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten getPlayState() == PLAYSTATE_PLAYING) { 16889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ERROR_INVALID_OPERATION; 16899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1690e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten if (loopCount == 0) { 1691e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten ; // explicitly allowed as an exception to the loop region range check 1692e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten } else if (!(0 <= startInFrames && startInFrames < mNativeBufferSizeInFrames && 1693e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten startInFrames < endInFrames && endInFrames <= mNativeBufferSizeInFrames)) { 1694e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten return ERROR_BAD_VALUE; 1695e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten } 16969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return native_set_loop(startInFrames, endInFrames, loopCount); 16979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 170055a3218f242a611afb3569d88970c0c5dbf8ce54Glenn Kasten * Sets the initialization state of the instance. This method was originally intended to be used 170155a3218f242a611afb3569d88970c0c5dbf8ce54Glenn Kasten * in an AudioTrack subclass constructor to set a subclass-specific post-initialization state. 170255a3218f242a611afb3569d88970c0c5dbf8ce54Glenn Kasten * However, subclasses of AudioTrack are no longer recommended, so this method is obsolete. 17039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param state the state of the AudioTrack instance 170455a3218f242a611afb3569d88970c0c5dbf8ce54Glenn Kasten * @deprecated Only accessible by subclasses, which are not recommended for AudioTrack. 17059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 170655a3218f242a611afb3569d88970c0c5dbf8ce54Glenn Kasten @Deprecated 17079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void setState(int state) { 17089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mState = state; 17099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //--------------------------------------------------------- 17139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Transport control methods 17149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //-------------------- 17159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 17169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Starts playing an AudioTrack. 1717659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * <p> 1718ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * If track's creation mode is {@link #MODE_STATIC}, you must have called one of 1719659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * the write methods ({@link #write(byte[], int, int)}, {@link #write(byte[], int, int, int)}, 1720659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * {@link #write(short[], int, int)}, {@link #write(short[], int, int, int)}, 1721659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * {@link #write(float[], int, int, int)}, or {@link #write(ByteBuffer, int, int)}) prior to 1722659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * play(). 1723659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * <p> 1724659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * If the mode is {@link #MODE_STREAM}, you can optionally prime the data path prior to 1725659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * calling play(), by writing up to <code>bufferSizeInBytes</code> (from constructor). 1726e90a0a88f4eabdc27c3ef033f38c91ea23362a1eAndy Hung * If you don't call write() first, or if you call write() but with an insufficient amount of 1727659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * data, then the track will be in underrun state at play(). In this case, 1728659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * playback will not actually start playing until the data path is filled to a 1729659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * device-specific minimum level. This requirement for the path to be filled 1730659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * to a minimum level is also true when resuming audio playback after calling stop(). 1731659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * Similarly the buffer will need to be filled up again after 1732659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * the track underruns due to failure to call write() in a timely manner with sufficient data. 1733659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * For portability, an application should prime the data path to the maximum allowed 1734659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * by writing data until the write() method returns a short transfer count. 1735659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * This allows play() to start immediately, and reduces the chance of underrun. 173688bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath * 1737659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * @throws IllegalStateException if the track isn't properly initialized 17389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 17399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void play() 17409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws IllegalStateException { 17419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState != STATE_INITIALIZED) { 1742f4e58051e22ad4e21c7cd436c37cc5665c194d1cGlenn Kasten throw new IllegalStateException("play() called on uninitialized AudioTrack."); 17439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17443c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi baseStart(); 17459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized(mPlayStateLock) { 17469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project native_start(); 17479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPlayState = PLAYSTATE_PLAYING; 17489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 17529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Stops playing the audio data. 1753a701da8ebabb3d63ac57b7718055698abb21804aJean-Michel Trivi * When used on an instance created in {@link #MODE_STREAM} mode, audio will stop playing 1754a701da8ebabb3d63ac57b7718055698abb21804aJean-Michel Trivi * after the last buffer that was written has been played. For an immediate stop, use 1755a701da8ebabb3d63ac57b7718055698abb21804aJean-Michel Trivi * {@link #pause()}, followed by {@link #flush()} to discard audio data that hasn't been played 1756a701da8ebabb3d63ac57b7718055698abb21804aJean-Michel Trivi * back yet. 17579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws IllegalStateException 17589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 17599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void stop() 17609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws IllegalStateException { 17619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState != STATE_INITIALIZED) { 1762f4e58051e22ad4e21c7cd436c37cc5665c194d1cGlenn Kasten throw new IllegalStateException("stop() called on uninitialized AudioTrack."); 17639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // stop playing 17669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized(mPlayStateLock) { 17679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project native_stop(); 17689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPlayState = PLAYSTATE_STOPPED; 1769cfe964a09ca05778e5dd84f2fd24119b89401696Rachad mAvSyncHeader = null; 1770cfe964a09ca05778e5dd84f2fd24119b89401696Rachad mAvSyncBytesRemaining = 0; 17719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 177588bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath * Pauses the playback of the audio data. Data that has not been played 177688bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath * back will not be discarded. Subsequent calls to {@link #play} will play 1777a701da8ebabb3d63ac57b7718055698abb21804aJean-Michel Trivi * this data back. See {@link #flush()} to discard this data. 177888bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath * 17799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throws IllegalStateException 17809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 17819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void pause() 17829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws IllegalStateException { 17839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState != STATE_INITIALIZED) { 1784f4e58051e22ad4e21c7cd436c37cc5665c194d1cGlenn Kasten throw new IllegalStateException("pause() called on uninitialized AudioTrack."); 17859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //logd("pause()"); 17879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // pause playback 17899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized(mPlayStateLock) { 17909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project native_pause(); 17919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPlayState = PLAYSTATE_PAUSED; 17929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //--------------------------------------------------------- 17979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Audio data supply 17989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //-------------------- 17999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 180188bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath * Flushes the audio data currently queued for playback. Any data that has 18027a121563d5c94ca0b88539afd8a7e86cc9118b60Glenn Kasten * been written but not yet presented will be discarded. No-op if not stopped or paused, 1803e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * or if the track's creation mode is not {@link #MODE_STREAM}. 18047a121563d5c94ca0b88539afd8a7e86cc9118b60Glenn Kasten * <BR> Note that although data written but not yet presented is discarded, there is no 18057a121563d5c94ca0b88539afd8a7e86cc9118b60Glenn Kasten * guarantee that all of the buffer space formerly used by that data 18067a121563d5c94ca0b88539afd8a7e86cc9118b60Glenn Kasten * is available for a subsequent write. 18077a121563d5c94ca0b88539afd8a7e86cc9118b60Glenn Kasten * For example, a call to {@link #write(byte[], int, int)} with <code>sizeInBytes</code> 18087a121563d5c94ca0b88539afd8a7e86cc9118b60Glenn Kasten * less than or equal to the total buffer size 18097a121563d5c94ca0b88539afd8a7e86cc9118b60Glenn Kasten * may return a short actual transfer count. 18109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 18119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void flush() { 18129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mState == STATE_INITIALIZED) { 18139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // flush the data in native layer 18149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project native_flush(); 1815cfe964a09ca05778e5dd84f2fd24119b89401696Rachad mAvSyncHeader = null; 1816cfe964a09ca05778e5dd84f2fd24119b89401696Rachad mAvSyncBytesRemaining = 0; 18179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1822e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * Writes the audio data to the audio sink for playback (streaming mode), 1823e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * or copies audio data for later playback (static buffer mode). 18244aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung * The format specified in the AudioTrack constructor should be 18254aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung * {@link AudioFormat#ENCODING_PCM_8BIT} to correspond to the data in the array. 1826518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten * The format can be {@link AudioFormat#ENCODING_PCM_16BIT}, but this is deprecated. 1827659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * <p> 1828659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * In streaming mode, the write will normally block until all the data has been enqueued for 1829659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * playback, and will return a full transfer count. However, if the track is stopped or paused 1830659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * on entry, or another thread interrupts the write by calling stop or pause, or an I/O error 1831659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * occurs during the write, then the write may return a short transfer count. 1832659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * <p> 1833e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * In static buffer mode, copies the data to the buffer starting at offset 0. 1834659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * Note that the actual playback of this data might occur after this function returns. 183588bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath * 18369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param audioData the array that holds the data to play. 1837679f1e26d03ebb5574ed389187f2ebc619832d52Glenn Kasten * @param offsetInBytes the offset expressed in bytes in audioData where the data to write 1838ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi * starts. 1839518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten * Must not be negative, or cause the data access to go out of bounds of the array. 1840679f1e26d03ebb5574ed389187f2ebc619832d52Glenn Kasten * @param sizeInBytes the number of bytes to write in audioData after the offset. 1841518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten * Must not be negative, or cause the data access to go out of bounds of the array. 1842219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * @return zero or the positive number of bytes that were written, or one of the following 1843219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * error codes. The number of bytes will be a multiple of the frame size in bytes 1844518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten * not to exceed sizeInBytes. 1845219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * <ul> 1846219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * <li>{@link #ERROR_INVALID_OPERATION} if the track isn't properly initialized</li> 1847219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li> 1848219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * <li>{@link #ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and 1849219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * needs to be recreated. The dead object error code is not returned if some data was 1850219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * successfully transferred. In this case, the error is returned at the next write()</li> 1851219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * <li>{@link #ERROR} in case of other error</li> 1852219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * </ul> 1853659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * This is equivalent to {@link #write(byte[], int, int, int)} with <code>writeMode</code> 1854659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * set to {@link #WRITE_BLOCKING}. 18559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 18564aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung public int write(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes) { 18574aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung return write(audioData, offsetInBytes, sizeInBytes, WRITE_BLOCKING); 18584aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung } 18599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18604aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung /** 18614aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung * Writes the audio data to the audio sink for playback (streaming mode), 18624aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung * or copies audio data for later playback (static buffer mode). 18634aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung * The format specified in the AudioTrack constructor should be 18644aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung * {@link AudioFormat#ENCODING_PCM_8BIT} to correspond to the data in the array. 1865518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten * The format can be {@link AudioFormat#ENCODING_PCM_16BIT}, but this is deprecated. 1866659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * <p> 1867659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * In streaming mode, the blocking behavior depends on the write mode. If the write mode is 1868659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * {@link #WRITE_BLOCKING}, the write will normally block until all the data has been enqueued 1869659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * for playback, and will return a full transfer count. However, if the write mode is 1870659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * {@link #WRITE_NON_BLOCKING}, or the track is stopped or paused on entry, or another thread 1871659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * interrupts the write by calling stop or pause, or an I/O error 1872659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * occurs during the write, then the write may return a short transfer count. 1873659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * <p> 1874659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * In static buffer mode, copies the data to the buffer starting at offset 0, 1875659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * and the write mode is ignored. 1876659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * Note that the actual playback of this data might occur after this function returns. 18774aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung * 18784aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung * @param audioData the array that holds the data to play. 1879679f1e26d03ebb5574ed389187f2ebc619832d52Glenn Kasten * @param offsetInBytes the offset expressed in bytes in audioData where the data to write 18804aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung * starts. 1881518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten * Must not be negative, or cause the data access to go out of bounds of the array. 1882679f1e26d03ebb5574ed389187f2ebc619832d52Glenn Kasten * @param sizeInBytes the number of bytes to write in audioData after the offset. 1883518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten * Must not be negative, or cause the data access to go out of bounds of the array. 18844aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung * @param writeMode one of {@link #WRITE_BLOCKING}, {@link #WRITE_NON_BLOCKING}. It has no 18854aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung * effect in static mode. 18864aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung * <br>With {@link #WRITE_BLOCKING}, the write will block until all data has been written 18874aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung * to the audio sink. 18884aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung * <br>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after 18894aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung * queuing as much audio data for playback as possible without blocking. 1890219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * @return zero or the positive number of bytes that were written, or one of the following 1891219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * error codes. The number of bytes will be a multiple of the frame size in bytes 1892518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten * not to exceed sizeInBytes. 1893219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * <ul> 1894219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * <li>{@link #ERROR_INVALID_OPERATION} if the track isn't properly initialized</li> 1895219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li> 1896219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * <li>{@link #ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and 1897219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * needs to be recreated. The dead object error code is not returned if some data was 1898219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * successfully transferred. In this case, the error is returned at the next write()</li> 1899219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * <li>{@link #ERROR} in case of other error</li> 1900219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * </ul> 19014aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung */ 19024aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung public int write(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes, 19034aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung @WriteMode int writeMode) { 19049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 190554955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten if (mState == STATE_UNINITIALIZED || mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT) { 19069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ERROR_INVALID_OPERATION; 19079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19094aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung if ((writeMode != WRITE_BLOCKING) && (writeMode != WRITE_NON_BLOCKING)) { 19104aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung Log.e(TAG, "AudioTrack.write() called with invalid blocking mode"); 19114aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung return ERROR_BAD_VALUE; 19124aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung } 19134aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung 1914fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten if ( (audioData == null) || (offsetInBytes < 0 ) || (sizeInBytes < 0) 1915a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten || (offsetInBytes + sizeInBytes < 0) // detect integer overflow 19169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project || (offsetInBytes + sizeInBytes > audioData.length)) { 19179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ERROR_BAD_VALUE; 19189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19207ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi int ret = native_write_byte(audioData, offsetInBytes, sizeInBytes, mAudioFormat, 19214aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung writeMode == WRITE_BLOCKING); 1922a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten 1923a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten if ((mDataLoadMode == MODE_STATIC) 1924a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten && (mState == STATE_NO_STATIC_DATA) 1925a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten && (ret > 0)) { 1926a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten // benign race with respect to other APIs that read mState 1927a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten mState = STATE_INITIALIZED; 1928a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten } 1929a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten 1930a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten return ret; 19319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1934e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * Writes the audio data to the audio sink for playback (streaming mode), 1935e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * or copies audio data for later playback (static buffer mode). 19364aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung * The format specified in the AudioTrack constructor should be 19374aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung * {@link AudioFormat#ENCODING_PCM_16BIT} to correspond to the data in the array. 1938659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * <p> 1939659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * In streaming mode, the write will normally block until all the data has been enqueued for 1940659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * playback, and will return a full transfer count. However, if the track is stopped or paused 1941659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * on entry, or another thread interrupts the write by calling stop or pause, or an I/O error 1942659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * occurs during the write, then the write may return a short transfer count. 1943659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * <p> 1944e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * In static buffer mode, copies the data to the buffer starting at offset 0. 1945659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * Note that the actual playback of this data might occur after this function returns. 194688bde0ce3799c47530ea42ae3665bfa12ae38d11Narayan Kamath * 19479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param audioData the array that holds the data to play. 1948ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi * @param offsetInShorts the offset expressed in shorts in audioData where the data to play 1949ff14c25339da3f6cd86edd66ef42640e6d0c0787Jean-Michel Trivi * starts. 1950518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten * Must not be negative, or cause the data access to go out of bounds of the array. 1951e8c82a37050e568f211d47951480b182a61d42b4Glenn Kasten * @param sizeInShorts the number of shorts to read in audioData after the offset. 1952518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten * Must not be negative, or cause the data access to go out of bounds of the array. 1953219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * @return zero or the positive number of shorts that were written, or one of the following 1954219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * error codes. The number of shorts will be a multiple of the channel count not to 1955219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * exceed sizeInShorts. 1956219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * <ul> 1957219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * <li>{@link #ERROR_INVALID_OPERATION} if the track isn't properly initialized</li> 1958219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li> 1959219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * <li>{@link #ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and 1960219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * needs to be recreated. The dead object error code is not returned if some data was 1961219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * successfully transferred. In this case, the error is returned at the next write()</li> 1962219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * <li>{@link #ERROR} in case of other error</li> 1963219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * </ul> 1964659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * This is equivalent to {@link #write(short[], int, int, int)} with <code>writeMode</code> 1965659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * set to {@link #WRITE_BLOCKING}. 19669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 19674aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung public int write(@NonNull short[] audioData, int offsetInShorts, int sizeInShorts) { 19684aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung return write(audioData, offsetInShorts, sizeInShorts, WRITE_BLOCKING); 19694aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung } 19709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19714aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung /** 19724aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung * Writes the audio data to the audio sink for playback (streaming mode), 19734aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung * or copies audio data for later playback (static buffer mode). 19744aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung * The format specified in the AudioTrack constructor should be 19754aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung * {@link AudioFormat#ENCODING_PCM_16BIT} to correspond to the data in the array. 1976659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * <p> 1977659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * In streaming mode, the blocking behavior depends on the write mode. If the write mode is 1978659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * {@link #WRITE_BLOCKING}, the write will normally block until all the data has been enqueued 1979659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * for playback, and will return a full transfer count. However, if the write mode is 1980659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * {@link #WRITE_NON_BLOCKING}, or the track is stopped or paused on entry, or another thread 1981659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * interrupts the write by calling stop or pause, or an I/O error 1982659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * occurs during the write, then the write may return a short transfer count. 1983659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * <p> 19844aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung * In static buffer mode, copies the data to the buffer starting at offset 0. 1985659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * Note that the actual playback of this data might occur after this function returns. 19864aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung * 1987679f1e26d03ebb5574ed389187f2ebc619832d52Glenn Kasten * @param audioData the array that holds the data to write. 1988679f1e26d03ebb5574ed389187f2ebc619832d52Glenn Kasten * @param offsetInShorts the offset expressed in shorts in audioData where the data to write 19894aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung * starts. 1990518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten * Must not be negative, or cause the data access to go out of bounds of the array. 19914aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung * @param sizeInShorts the number of shorts to read in audioData after the offset. 1992518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten * Must not be negative, or cause the data access to go out of bounds of the array. 19934aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung * @param writeMode one of {@link #WRITE_BLOCKING}, {@link #WRITE_NON_BLOCKING}. It has no 19944aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung * effect in static mode. 19954aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung * <br>With {@link #WRITE_BLOCKING}, the write will block until all data has been written 19964aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung * to the audio sink. 19974aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung * <br>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after 19984aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung * queuing as much audio data for playback as possible without blocking. 1999219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * @return zero or the positive number of shorts that were written, or one of the following 2000219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * error codes. The number of shorts will be a multiple of the channel count not to 2001219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * exceed sizeInShorts. 2002219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * <ul> 2003219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * <li>{@link #ERROR_INVALID_OPERATION} if the track isn't properly initialized</li> 2004219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li> 2005219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * <li>{@link #ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and 2006219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * needs to be recreated. The dead object error code is not returned if some data was 2007219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * successfully transferred. In this case, the error is returned at the next write()</li> 2008219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * <li>{@link #ERROR} in case of other error</li> 2009219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * </ul> 20104aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung */ 20114aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung public int write(@NonNull short[] audioData, int offsetInShorts, int sizeInShorts, 20124aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung @WriteMode int writeMode) { 2013fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten 2014c56b8085919771b6f027dc64ed6a44915e392464Glenn Kasten if (mState == STATE_UNINITIALIZED || mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT) { 20159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ERROR_INVALID_OPERATION; 20169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 20179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20184aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung if ((writeMode != WRITE_BLOCKING) && (writeMode != WRITE_NON_BLOCKING)) { 20194aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung Log.e(TAG, "AudioTrack.write() called with invalid blocking mode"); 20204aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung return ERROR_BAD_VALUE; 20214aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung } 20224aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung 2023fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten if ( (audioData == null) || (offsetInShorts < 0 ) || (sizeInShorts < 0) 2024a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten || (offsetInShorts + sizeInShorts < 0) // detect integer overflow 20259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project || (offsetInShorts + sizeInShorts > audioData.length)) { 20269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ERROR_BAD_VALUE; 20279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 20289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20294aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung int ret = native_write_short(audioData, offsetInShorts, sizeInShorts, mAudioFormat, 20304aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung writeMode == WRITE_BLOCKING); 2031a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten 2032a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten if ((mDataLoadMode == MODE_STATIC) 2033a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten && (mState == STATE_NO_STATIC_DATA) 2034a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten && (ret > 0)) { 2035a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten // benign race with respect to other APIs that read mState 2036a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten mState = STATE_INITIALIZED; 2037a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten } 2038a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten 2039a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten return ret; 20409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 20419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 20437ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi * Writes the audio data to the audio sink for playback (streaming mode), 20447ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi * or copies audio data for later playback (static buffer mode). 20454aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung * The format specified in the AudioTrack constructor should be 20464aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung * {@link AudioFormat#ENCODING_PCM_FLOAT} to correspond to the data in the array. 204754955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten * <p> 2048659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * In streaming mode, the blocking behavior depends on the write mode. If the write mode is 2049659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * {@link #WRITE_BLOCKING}, the write will normally block until all the data has been enqueued 2050659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * for playback, and will return a full transfer count. However, if the write mode is 2051659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * {@link #WRITE_NON_BLOCKING}, or the track is stopped or paused on entry, or another thread 2052659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * interrupts the write by calling stop or pause, or an I/O error 2053659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * occurs during the write, then the write may return a short transfer count. 205454955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten * <p> 2055659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * In static buffer mode, copies the data to the buffer starting at offset 0, 2056659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * and the write mode is ignored. 2057659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * Note that the actual playback of this data might occur after this function returns. 2058659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * 2059679f1e26d03ebb5574ed389187f2ebc619832d52Glenn Kasten * @param audioData the array that holds the data to write. 206054955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten * The implementation does not clip for sample values within the nominal range 206154955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten * [-1.0f, 1.0f], provided that all gains in the audio pipeline are 206254955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten * less than or equal to unity (1.0f), and in the absence of post-processing effects 206354955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten * that could add energy, such as reverb. For the convenience of applications 206454955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten * that compute samples using filters with non-unity gain, 206554955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten * sample values +3 dB beyond the nominal range are permitted. 206654955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten * However such values may eventually be limited or clipped, depending on various gains 206754955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten * and later processing in the audio path. Therefore applications are encouraged 206854955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten * to provide samples values within the nominal range. 206954955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten * @param offsetInFloats the offset, expressed as a number of floats, 2070679f1e26d03ebb5574ed389187f2ebc619832d52Glenn Kasten * in audioData where the data to write starts. 2071518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten * Must not be negative, or cause the data access to go out of bounds of the array. 2072679f1e26d03ebb5574ed389187f2ebc619832d52Glenn Kasten * @param sizeInFloats the number of floats to write in audioData after the offset. 2073518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten * Must not be negative, or cause the data access to go out of bounds of the array. 207454955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten * @param writeMode one of {@link #WRITE_BLOCKING}, {@link #WRITE_NON_BLOCKING}. It has no 207554955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten * effect in static mode. 20764aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung * <br>With {@link #WRITE_BLOCKING}, the write will block until all data has been written 207754955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten * to the audio sink. 20784aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung * <br>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after 207954955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten * queuing as much audio data for playback as possible without blocking. 2080219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * @return zero or the positive number of floats that were written, or one of the following 2081219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * error codes. The number of floats will be a multiple of the channel count not to 2082219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * exceed sizeInFloats. 2083219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * <ul> 2084219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * <li>{@link #ERROR_INVALID_OPERATION} if the track isn't properly initialized</li> 2085219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li> 2086219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * <li>{@link #ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and 2087219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * needs to be recreated. The dead object error code is not returned if some data was 2088219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * successfully transferred. In this case, the error is returned at the next write()</li> 2089219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * <li>{@link #ERROR} in case of other error</li> 2090219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * </ul> 209154955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten */ 20924aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung public int write(@NonNull float[] audioData, int offsetInFloats, int sizeInFloats, 209354955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten @WriteMode int writeMode) { 209454955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten 209554955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten if (mState == STATE_UNINITIALIZED) { 209654955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten Log.e(TAG, "AudioTrack.write() called in invalid state STATE_UNINITIALIZED"); 209754955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten return ERROR_INVALID_OPERATION; 209854955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten } 209954955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten 210054955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten if (mAudioFormat != AudioFormat.ENCODING_PCM_FLOAT) { 210154955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten Log.e(TAG, "AudioTrack.write(float[] ...) requires format ENCODING_PCM_FLOAT"); 210254955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten return ERROR_INVALID_OPERATION; 210354955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten } 210454955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten 210554955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten if ((writeMode != WRITE_BLOCKING) && (writeMode != WRITE_NON_BLOCKING)) { 210654955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten Log.e(TAG, "AudioTrack.write() called with invalid blocking mode"); 210754955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten return ERROR_BAD_VALUE; 210854955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten } 210954955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten 211054955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten if ( (audioData == null) || (offsetInFloats < 0 ) || (sizeInFloats < 0) 211154955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten || (offsetInFloats + sizeInFloats < 0) // detect integer overflow 211254955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten || (offsetInFloats + sizeInFloats > audioData.length)) { 211354955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten Log.e(TAG, "AudioTrack.write() called with invalid array, offset, or size"); 211454955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten return ERROR_BAD_VALUE; 211554955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten } 211654955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten 211754955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten int ret = native_write_float(audioData, offsetInFloats, sizeInFloats, mAudioFormat, 211854955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten writeMode == WRITE_BLOCKING); 211954955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten 212054955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten if ((mDataLoadMode == MODE_STATIC) 212154955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten && (mState == STATE_NO_STATIC_DATA) 212254955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten && (ret > 0)) { 212354955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten // benign race with respect to other APIs that read mState 212454955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten mState = STATE_INITIALIZED; 212554955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten } 212654955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten 212754955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten return ret; 212854955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten } 212954955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten 213054955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten 213154955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten /** 213254955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten * Writes the audio data to the audio sink for playback (streaming mode), 213354955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten * or copies audio data for later playback (static buffer mode). 2134659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * The audioData in ByteBuffer should match the format specified in the AudioTrack constructor. 2135659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * <p> 2136659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * In streaming mode, the blocking behavior depends on the write mode. If the write mode is 2137659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * {@link #WRITE_BLOCKING}, the write will normally block until all the data has been enqueued 2138659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * for playback, and will return a full transfer count. However, if the write mode is 2139659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * {@link #WRITE_NON_BLOCKING}, or the track is stopped or paused on entry, or another thread 2140659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * interrupts the write by calling stop or pause, or an I/O error 2141659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * occurs during the write, then the write may return a short transfer count. 2142659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * <p> 2143659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * In static buffer mode, copies the data to the buffer starting at offset 0, 2144659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * and the write mode is ignored. 2145659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * Note that the actual playback of this data might occur after this function returns. 2146659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * 2147679f1e26d03ebb5574ed389187f2ebc619832d52Glenn Kasten * @param audioData the buffer that holds the data to write, starting at the position reported 21487ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi * by <code>audioData.position()</code>. 21495d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi * <BR>Note that upon return, the buffer position (<code>audioData.position()</code>) will 21505d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi * have been advanced to reflect the amount of data that was successfully written to 21515d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi * the AudioTrack. 2152518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten * @param sizeInBytes number of bytes to write. It is recommended but not enforced 2153518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten * that the number of bytes requested be a multiple of the frame size (sample size in 2154518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten * bytes multiplied by the channel count). 21555d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi * <BR>Note this may differ from <code>audioData.remaining()</code>, but cannot exceed it. 21567ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi * @param writeMode one of {@link #WRITE_BLOCKING}, {@link #WRITE_NON_BLOCKING}. It has no 21577ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi * effect in static mode. 21587ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi * <BR>With {@link #WRITE_BLOCKING}, the write will block until all data has been written 21597ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi * to the audio sink. 21607ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi * <BR>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after 21617ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi * queuing as much audio data for playback as possible without blocking. 2162219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * @return zero or the positive number of bytes that were written, or one of the following 2163219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * error codes. 2164219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * <ul> 2165219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * <li>{@link #ERROR_INVALID_OPERATION} if the track isn't properly initialized</li> 2166219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li> 2167219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * <li>{@link #ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and 2168219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * needs to be recreated. The dead object error code is not returned if some data was 2169219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * successfully transferred. In this case, the error is returned at the next write()</li> 2170219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * <li>{@link #ERROR} in case of other error</li> 2171219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * </ul> 21727ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi */ 21734aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung public int write(@NonNull ByteBuffer audioData, int sizeInBytes, 21747ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi @WriteMode int writeMode) { 21757ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi 21767ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi if (mState == STATE_UNINITIALIZED) { 21777ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi Log.e(TAG, "AudioTrack.write() called in invalid state STATE_UNINITIALIZED"); 21787ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi return ERROR_INVALID_OPERATION; 21797ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi } 21807ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi 21817ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi if ((writeMode != WRITE_BLOCKING) && (writeMode != WRITE_NON_BLOCKING)) { 21827ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi Log.e(TAG, "AudioTrack.write() called with invalid blocking mode"); 21837ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi return ERROR_BAD_VALUE; 21847ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi } 21857ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi 21865d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi if ( (audioData == null) || (sizeInBytes < 0) || (sizeInBytes > audioData.remaining())) { 21875d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi Log.e(TAG, "AudioTrack.write() called with invalid size (" + sizeInBytes + ") value"); 21887ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi return ERROR_BAD_VALUE; 21897ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi } 21907ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi 21917ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi int ret = 0; 21927ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi if (audioData.isDirect()) { 21937ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi ret = native_write_native_bytes(audioData, 21945d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi audioData.position(), sizeInBytes, mAudioFormat, 21957ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi writeMode == WRITE_BLOCKING); 21967ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi } else { 21977ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi ret = native_write_byte(NioUtils.unsafeArray(audioData), 21985d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi NioUtils.unsafeArrayOffset(audioData) + audioData.position(), 21997ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi sizeInBytes, mAudioFormat, 22007ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi writeMode == WRITE_BLOCKING); 22017ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi } 22027ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi 22037ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi if ((mDataLoadMode == MODE_STATIC) 22047ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi && (mState == STATE_NO_STATIC_DATA) 22057ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi && (ret > 0)) { 22067ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi // benign race with respect to other APIs that read mState 22077ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi mState = STATE_INITIALIZED; 22087ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi } 22097ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi 22105d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi if (ret > 0) { 22115d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi audioData.position(audioData.position() + ret); 22125d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi } 22135d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi 22147ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi return ret; 22157ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi } 22167ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi 22177ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi /** 2218659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * Writes the audio data to the audio sink for playback in streaming mode on a HW_AV_SYNC track. 2219659e31fb2933f16eefa6fb2d48da2622ea40b14aGlenn Kasten * The blocking behavior will depend on the write mode. 2220679f1e26d03ebb5574ed389187f2ebc619832d52Glenn Kasten * @param audioData the buffer that holds the data to write, starting at the position reported 2221cfe964a09ca05778e5dd84f2fd24119b89401696Rachad * by <code>audioData.position()</code>. 2222cfe964a09ca05778e5dd84f2fd24119b89401696Rachad * <BR>Note that upon return, the buffer position (<code>audioData.position()</code>) will 2223cfe964a09ca05778e5dd84f2fd24119b89401696Rachad * have been advanced to reflect the amount of data that was successfully written to 2224cfe964a09ca05778e5dd84f2fd24119b89401696Rachad * the AudioTrack. 2225518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten * @param sizeInBytes number of bytes to write. It is recommended but not enforced 2226518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten * that the number of bytes requested be a multiple of the frame size (sample size in 2227518432e36610ad6a14f00fdd8123efa295c7eaedGlenn Kasten * bytes multiplied by the channel count). 2228cfe964a09ca05778e5dd84f2fd24119b89401696Rachad * <BR>Note this may differ from <code>audioData.remaining()</code>, but cannot exceed it. 2229cfe964a09ca05778e5dd84f2fd24119b89401696Rachad * @param writeMode one of {@link #WRITE_BLOCKING}, {@link #WRITE_NON_BLOCKING}. 2230cfe964a09ca05778e5dd84f2fd24119b89401696Rachad * <BR>With {@link #WRITE_BLOCKING}, the write will block until all data has been written 2231cfe964a09ca05778e5dd84f2fd24119b89401696Rachad * to the audio sink. 2232cfe964a09ca05778e5dd84f2fd24119b89401696Rachad * <BR>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after 2233cfe964a09ca05778e5dd84f2fd24119b89401696Rachad * queuing as much audio data for playback as possible without blocking. 2234cfe964a09ca05778e5dd84f2fd24119b89401696Rachad * @param timestamp The timestamp of the first decodable audio frame in the provided audioData. 2235219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * @return zero or the positive number of bytes that were written, or one of the following 2236219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * error codes. 2237219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * <ul> 2238219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * <li>{@link #ERROR_INVALID_OPERATION} if the track isn't properly initialized</li> 2239219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li> 2240219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * <li>{@link #ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and 2241219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * needs to be recreated. The dead object error code is not returned if some data was 2242219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * successfully transferred. In this case, the error is returned at the next write()</li> 2243219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * <li>{@link #ERROR} in case of other error</li> 2244219de73da2a986ddcbfbc593c4e4e01c858ce245Eric Laurent * </ul> 2245cfe964a09ca05778e5dd84f2fd24119b89401696Rachad */ 224668d5ebd1da6bd4744314749d4fdbaf216414ea94Glenn Kasten public int write(@NonNull ByteBuffer audioData, int sizeInBytes, 2247cfe964a09ca05778e5dd84f2fd24119b89401696Rachad @WriteMode int writeMode, long timestamp) { 2248cfe964a09ca05778e5dd84f2fd24119b89401696Rachad 224968d5ebd1da6bd4744314749d4fdbaf216414ea94Glenn Kasten if (mState == STATE_UNINITIALIZED) { 225068d5ebd1da6bd4744314749d4fdbaf216414ea94Glenn Kasten Log.e(TAG, "AudioTrack.write() called in invalid state STATE_UNINITIALIZED"); 225168d5ebd1da6bd4744314749d4fdbaf216414ea94Glenn Kasten return ERROR_INVALID_OPERATION; 225268d5ebd1da6bd4744314749d4fdbaf216414ea94Glenn Kasten } 225368d5ebd1da6bd4744314749d4fdbaf216414ea94Glenn Kasten 225468d5ebd1da6bd4744314749d4fdbaf216414ea94Glenn Kasten if ((writeMode != WRITE_BLOCKING) && (writeMode != WRITE_NON_BLOCKING)) { 225568d5ebd1da6bd4744314749d4fdbaf216414ea94Glenn Kasten Log.e(TAG, "AudioTrack.write() called with invalid blocking mode"); 225668d5ebd1da6bd4744314749d4fdbaf216414ea94Glenn Kasten return ERROR_BAD_VALUE; 225768d5ebd1da6bd4744314749d4fdbaf216414ea94Glenn Kasten } 225868d5ebd1da6bd4744314749d4fdbaf216414ea94Glenn Kasten 225968d5ebd1da6bd4744314749d4fdbaf216414ea94Glenn Kasten if (mDataLoadMode != MODE_STREAM) { 226068d5ebd1da6bd4744314749d4fdbaf216414ea94Glenn Kasten Log.e(TAG, "AudioTrack.write() with timestamp called for non-streaming mode track"); 226168d5ebd1da6bd4744314749d4fdbaf216414ea94Glenn Kasten return ERROR_INVALID_OPERATION; 226268d5ebd1da6bd4744314749d4fdbaf216414ea94Glenn Kasten } 226368d5ebd1da6bd4744314749d4fdbaf216414ea94Glenn Kasten 2264cfe964a09ca05778e5dd84f2fd24119b89401696Rachad if ((mAttributes.getFlags() & AudioAttributes.FLAG_HW_AV_SYNC) == 0) { 2265cfe964a09ca05778e5dd84f2fd24119b89401696Rachad Log.d(TAG, "AudioTrack.write() called on a regular AudioTrack. Ignoring pts..."); 2266cfe964a09ca05778e5dd84f2fd24119b89401696Rachad return write(audioData, sizeInBytes, writeMode); 2267cfe964a09ca05778e5dd84f2fd24119b89401696Rachad } 2268cfe964a09ca05778e5dd84f2fd24119b89401696Rachad 2269cfe964a09ca05778e5dd84f2fd24119b89401696Rachad if ((audioData == null) || (sizeInBytes < 0) || (sizeInBytes > audioData.remaining())) { 2270cfe964a09ca05778e5dd84f2fd24119b89401696Rachad Log.e(TAG, "AudioTrack.write() called with invalid size (" + sizeInBytes + ") value"); 2271cfe964a09ca05778e5dd84f2fd24119b89401696Rachad return ERROR_BAD_VALUE; 2272cfe964a09ca05778e5dd84f2fd24119b89401696Rachad } 2273cfe964a09ca05778e5dd84f2fd24119b89401696Rachad 2274cfe964a09ca05778e5dd84f2fd24119b89401696Rachad // create timestamp header if none exists 2275cfe964a09ca05778e5dd84f2fd24119b89401696Rachad if (mAvSyncHeader == null) { 2276cfe964a09ca05778e5dd84f2fd24119b89401696Rachad mAvSyncHeader = ByteBuffer.allocate(16); 2277cfe964a09ca05778e5dd84f2fd24119b89401696Rachad mAvSyncHeader.order(ByteOrder.BIG_ENDIAN); 2278cfe964a09ca05778e5dd84f2fd24119b89401696Rachad mAvSyncHeader.putInt(0x55550001); 2279cfe964a09ca05778e5dd84f2fd24119b89401696Rachad mAvSyncHeader.putInt(sizeInBytes); 2280cfe964a09ca05778e5dd84f2fd24119b89401696Rachad mAvSyncHeader.putLong(timestamp); 2281cfe964a09ca05778e5dd84f2fd24119b89401696Rachad mAvSyncHeader.position(0); 2282cfe964a09ca05778e5dd84f2fd24119b89401696Rachad mAvSyncBytesRemaining = sizeInBytes; 2283cfe964a09ca05778e5dd84f2fd24119b89401696Rachad } 2284cfe964a09ca05778e5dd84f2fd24119b89401696Rachad 2285cfe964a09ca05778e5dd84f2fd24119b89401696Rachad // write timestamp header if not completely written already 2286cfe964a09ca05778e5dd84f2fd24119b89401696Rachad int ret = 0; 2287cfe964a09ca05778e5dd84f2fd24119b89401696Rachad if (mAvSyncHeader.remaining() != 0) { 2288cfe964a09ca05778e5dd84f2fd24119b89401696Rachad ret = write(mAvSyncHeader, mAvSyncHeader.remaining(), writeMode); 2289cfe964a09ca05778e5dd84f2fd24119b89401696Rachad if (ret < 0) { 2290cfe964a09ca05778e5dd84f2fd24119b89401696Rachad Log.e(TAG, "AudioTrack.write() could not write timestamp header!"); 2291cfe964a09ca05778e5dd84f2fd24119b89401696Rachad mAvSyncHeader = null; 2292cfe964a09ca05778e5dd84f2fd24119b89401696Rachad mAvSyncBytesRemaining = 0; 2293cfe964a09ca05778e5dd84f2fd24119b89401696Rachad return ret; 2294cfe964a09ca05778e5dd84f2fd24119b89401696Rachad } 2295cfe964a09ca05778e5dd84f2fd24119b89401696Rachad if (mAvSyncHeader.remaining() > 0) { 2296cfe964a09ca05778e5dd84f2fd24119b89401696Rachad Log.v(TAG, "AudioTrack.write() partial timestamp header written."); 2297cfe964a09ca05778e5dd84f2fd24119b89401696Rachad return 0; 2298cfe964a09ca05778e5dd84f2fd24119b89401696Rachad } 2299cfe964a09ca05778e5dd84f2fd24119b89401696Rachad } 2300cfe964a09ca05778e5dd84f2fd24119b89401696Rachad 2301cfe964a09ca05778e5dd84f2fd24119b89401696Rachad // write audio data 2302cfe964a09ca05778e5dd84f2fd24119b89401696Rachad int sizeToWrite = Math.min(mAvSyncBytesRemaining, sizeInBytes); 2303cfe964a09ca05778e5dd84f2fd24119b89401696Rachad ret = write(audioData, sizeToWrite, writeMode); 2304cfe964a09ca05778e5dd84f2fd24119b89401696Rachad if (ret < 0) { 2305cfe964a09ca05778e5dd84f2fd24119b89401696Rachad Log.e(TAG, "AudioTrack.write() could not write audio data!"); 2306cfe964a09ca05778e5dd84f2fd24119b89401696Rachad mAvSyncHeader = null; 2307cfe964a09ca05778e5dd84f2fd24119b89401696Rachad mAvSyncBytesRemaining = 0; 2308cfe964a09ca05778e5dd84f2fd24119b89401696Rachad return ret; 2309cfe964a09ca05778e5dd84f2fd24119b89401696Rachad } 2310cfe964a09ca05778e5dd84f2fd24119b89401696Rachad 2311cfe964a09ca05778e5dd84f2fd24119b89401696Rachad mAvSyncBytesRemaining -= ret; 2312cfe964a09ca05778e5dd84f2fd24119b89401696Rachad if (mAvSyncBytesRemaining == 0) { 2313cfe964a09ca05778e5dd84f2fd24119b89401696Rachad mAvSyncHeader = null; 2314cfe964a09ca05778e5dd84f2fd24119b89401696Rachad } 2315cfe964a09ca05778e5dd84f2fd24119b89401696Rachad 2316cfe964a09ca05778e5dd84f2fd24119b89401696Rachad return ret; 2317cfe964a09ca05778e5dd84f2fd24119b89401696Rachad } 2318cfe964a09ca05778e5dd84f2fd24119b89401696Rachad 2319cfe964a09ca05778e5dd84f2fd24119b89401696Rachad 2320cfe964a09ca05778e5dd84f2fd24119b89401696Rachad /** 2321ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * Sets the playback head position within the static buffer to zero, 2322ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * that is it rewinds to start of static buffer. 2323ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * The track must be stopped or paused, and 2324ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * the track's creation mode must be {@link #MODE_STATIC}. 2325ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * <p> 23260e3de6cacaffcfeda4d6353be61e2f1f9ed80705Dianne Hackborn * As of {@link android.os.Build.VERSION_CODES#M}, also resets the value returned by 2327ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * {@link #getPlaybackHeadPosition()} to zero. 2328ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * For earlier API levels, the reset behavior is unspecified. 2329ac322096d8c7b6198193d6140fc37073f7ccb2feGlenn Kasten * <p> 233035e576e79292122fad462ebccd8520822552a6d7Andy Hung * Use {@link #setPlaybackHeadPosition(int)} with a zero position 233135e576e79292122fad462ebccd8520822552a6d7Andy Hung * if the reset of <code>getPlaybackHeadPosition()</code> is not needed. 23329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE}, 23339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #ERROR_INVALID_OPERATION} 23349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 23359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int reloadStaticData() { 2336a501b5b8d5ec0ccc975adbcf302f01a6979e81e1Glenn Kasten if (mDataLoadMode == MODE_STREAM || mState != STATE_INITIALIZED) { 23379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ERROR_INVALID_OPERATION; 23389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return native_reload_static(); 23409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 23427070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent //-------------------------------------------------------------------------- 23437070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent // Audio effects management 23447070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent //-------------------- 23457070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent 23467070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent /** 23471a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent * Attaches an auxiliary effect to the audio track. A typical auxiliary 23481a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent * effect is a reverberation effect which can be applied on any sound source 23491a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent * that directs a certain amount of its energy to this effect. This amount 23501a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent * is defined by setAuxEffectSendLevel(). 23517070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent * {@see #setAuxEffectSendLevel(float)}. 23521a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent * <p>After creating an auxiliary effect (e.g. 23531a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent * {@link android.media.audiofx.EnvironmentalReverb}), retrieve its ID with 23541a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent * {@link android.media.audiofx.AudioEffect#getId()} and use it when calling 23557070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent * this method to attach the audio track to the effect. 23561a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent * <p>To detach the effect from the audio track, call this method with a 23571a5149e5d7f2dddc8b324f7695e69fd89af73c52Eric Laurent * null effect id. 23587070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent * 23597070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent * @param effectId system wide unique id of the effect to attach 23607070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent * @return error code or success, see {@link #SUCCESS}, 23617070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent * {@link #ERROR_INVALID_OPERATION}, {@link #ERROR_BAD_VALUE} 23627070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent */ 23637070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent public int attachAuxEffect(int effectId) { 23643b4df62704a6184878afd9272830cf3db7bd2d66Glenn Kasten if (mState == STATE_UNINITIALIZED) { 23657070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent return ERROR_INVALID_OPERATION; 23667070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent } 23677070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent return native_attachAuxEffect(effectId); 23687070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent } 23697070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent 23707070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent /** 23717070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent * Sets the send level of the audio track to the attached auxiliary effect 237278cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * {@link #attachAuxEffect(int)}. Effect levels 237378cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * are clamped to the closed interval [0.0, max] where 237478cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * max is the value of {@link #getMaxVolume}. 237578cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * A value of 0.0 results in no effect, and a value of 1.0 is full send. 2376e2a4b42c5b7f3475c1587f30d19afc12a190f009Glenn Kasten * <p>By default the send level is 0.0f, so even if an effect is attached to the player 23777070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent * this method must be called for the effect to be applied. 237878cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * <p>Note that the passed level value is a linear scalar. UI controls should be scaled 237978cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * logarithmically: the gain applied by audio framework ranges from -72dB to at least 0dB, 23807070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent * so an appropriate conversion from linear UI input x to level is: 23815c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten * x == 0 -> level = 0 23825c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten * 0 < x <= R -> level = 10^(72*(x-R)/20/R) 23837070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent * 238478cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten * @param level linear send level 23857070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent * @return error code or success, see {@link #SUCCESS}, 23863009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten * {@link #ERROR_INVALID_OPERATION}, {@link #ERROR} 23877070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent */ 23887070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent public int setAuxEffectSendLevel(float level) { 23893b4df62704a6184878afd9272830cf3db7bd2d66Glenn Kasten if (mState == STATE_UNINITIALIZED) { 23907070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent return ERROR_INVALID_OPERATION; 23917070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent } 23923c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi return baseSetAuxEffectSendLevel(level); 23933c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi } 23943c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi 23953c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi @Override 23963c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi int playerSetAuxEffectSendLevel(float level) { 239778cbd451fd568e8fcc6fcc7c4f875428189aa8b8Glenn Kasten level = clampGainOrLevel(level); 23983009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten int err = native_setAuxEffectSendLevel(level); 23993009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten return err == 0 ? SUCCESS : ERROR; 24007070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent } 24019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 240288e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean //-------------------------------------------------------------------------- 240388e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean // Explicit Routing 240488e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean //-------------------- 240588e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean private AudioDeviceInfo mPreferredDevice = null; 240688e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean 240788e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean /** 24082d6de4c38c899707e0596b7fa4dad9bbb3eb6b60Paul McLean * Specifies an audio device (via an {@link AudioDeviceInfo} object) to route 240988e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean * the output from this AudioTrack. 24109e29086d5df800532e736d8f31e2b9159b102524Glenn Kasten * @param deviceInfo The {@link AudioDeviceInfo} specifying the audio sink. 24119e29086d5df800532e736d8f31e2b9159b102524Glenn Kasten * If deviceInfo is null, default routing is restored. 241288e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean * @return true if succesful, false if the specified {@link AudioDeviceInfo} is non-null and 241388e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean * does not correspond to a valid audio output device. 241488e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean */ 2415ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey @Override 2416e3383cc4539921756232ae4f3f54e99b95fb20ccPaul McLean public boolean setPreferredDevice(AudioDeviceInfo deviceInfo) { 241788e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean // Do some validation.... 24182d6de4c38c899707e0596b7fa4dad9bbb3eb6b60Paul McLean if (deviceInfo != null && !deviceInfo.isSink()) { 241988e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean return false; 242088e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean } 24214bcdba848449b33d7022de527c526943aff1f5fdEric Laurent int preferredDeviceId = deviceInfo != null ? deviceInfo.getId() : 0; 24224bcdba848449b33d7022de527c526943aff1f5fdEric Laurent boolean status = native_setOutputDevice(preferredDeviceId); 24234bcdba848449b33d7022de527c526943aff1f5fdEric Laurent if (status == true) { 24244bcdba848449b33d7022de527c526943aff1f5fdEric Laurent synchronized (this) { 24254bcdba848449b33d7022de527c526943aff1f5fdEric Laurent mPreferredDevice = deviceInfo; 24264bcdba848449b33d7022de527c526943aff1f5fdEric Laurent } 24274bcdba848449b33d7022de527c526943aff1f5fdEric Laurent } 24284bcdba848449b33d7022de527c526943aff1f5fdEric Laurent return status; 242988e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean } 243088e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean 243188e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean /** 2432e3383cc4539921756232ae4f3f54e99b95fb20ccPaul McLean * Returns the selected output specified by {@link #setPreferredDevice}. Note that this 24332d6de4c38c899707e0596b7fa4dad9bbb3eb6b60Paul McLean * is not guaranteed to correspond to the actual device being used for playback. 243488e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean */ 2435ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey @Override 2436e3383cc4539921756232ae4f3f54e99b95fb20ccPaul McLean public AudioDeviceInfo getPreferredDevice() { 24374bcdba848449b33d7022de527c526943aff1f5fdEric Laurent synchronized (this) { 24384bcdba848449b33d7022de527c526943aff1f5fdEric Laurent return mPreferredDevice; 24394bcdba848449b33d7022de527c526943aff1f5fdEric Laurent } 244088e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean } 244188e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean 2442d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean /** 2443d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean * Returns an {@link AudioDeviceInfo} identifying the current routing of this AudioTrack. 24448e6c9f46172458624349755c9b1bc051f420d36dPaul McLean * Note: The query is only valid if the AudioTrack is currently playing. If it is not, 24458e6c9f46172458624349755c9b1bc051f420d36dPaul McLean * <code>getRoutedDevice()</code> will return null. 2446d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean */ 2447ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey @Override 2448d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean public AudioDeviceInfo getRoutedDevice() { 24494bcdba848449b33d7022de527c526943aff1f5fdEric Laurent int deviceId = native_getRoutedDeviceId(); 24504bcdba848449b33d7022de527c526943aff1f5fdEric Laurent if (deviceId == 0) { 24514bcdba848449b33d7022de527c526943aff1f5fdEric Laurent return null; 24524bcdba848449b33d7022de527c526943aff1f5fdEric Laurent } 24534bcdba848449b33d7022de527c526943aff1f5fdEric Laurent AudioDeviceInfo[] devices = 2454e3383cc4539921756232ae4f3f54e99b95fb20ccPaul McLean AudioManager.getDevicesStatic(AudioManager.GET_DEVICES_OUTPUTS); 24554bcdba848449b33d7022de527c526943aff1f5fdEric Laurent for (int i = 0; i < devices.length; i++) { 24564bcdba848449b33d7022de527c526943aff1f5fdEric Laurent if (devices[i].getId() == deviceId) { 24574bcdba848449b33d7022de527c526943aff1f5fdEric Laurent return devices[i]; 24584bcdba848449b33d7022de527c526943aff1f5fdEric Laurent } 24594bcdba848449b33d7022de527c526943aff1f5fdEric Laurent } 2460d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean return null; 2461d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean } 2462d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean 2463ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean /* 2464ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean * Call BEFORE adding a routing callback handler. 2465ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean */ 2466ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey private void testEnableNativeRoutingCallbacksLocked() { 2467ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey if (mRoutingChangeListeners.size() == 0) { 2468ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean native_enableDeviceCallback(); 2469ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean } 2470ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean } 2471ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean 2472ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean /* 2473ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean * Call AFTER removing a routing callback handler. 2474ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean */ 2475ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey private void testDisableNativeRoutingCallbacksLocked() { 2476ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey if (mRoutingChangeListeners.size() == 0) { 2477ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean native_disableDeviceCallback(); 2478ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean } 2479ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean } 2480ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean 2481ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean //-------------------------------------------------------------------------- 2482ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey // (Re)Routing Info 2483ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean //-------------------- 2484ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean /** 2485ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean * The list of AudioRouting.OnRoutingChangedListener interfaces added (with 2486ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey * {@link AudioRecord#addOnRoutingChangedListener} by an app to receive 2487ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey * (re)routing notifications. 2488ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean */ 2489ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey @GuardedBy("mRoutingChangeListeners") 2490ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey private ArrayMap<AudioRouting.OnRoutingChangedListener, 2491ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey NativeRoutingEventHandlerDelegate> mRoutingChangeListeners = new ArrayMap<>(); 2492ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean 2493ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean /** 2494ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean * Adds an {@link AudioRouting.OnRoutingChangedListener} to receive notifications of routing 2495ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean * changes on this AudioTrack. 2496ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean * @param listener The {@link AudioRouting.OnRoutingChangedListener} interface to receive 2497ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean * notifications of rerouting events. 2498ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean * @param handler Specifies the {@link Handler} object for the thread on which to execute 2499ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean * the callback. If <code>null</code>, the {@link Handler} associated with the main 2500ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean * {@link Looper} will be used. 2501ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean */ 2502ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey @Override 2503ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey public void addOnRoutingChangedListener(AudioRouting.OnRoutingChangedListener listener, 2504ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean Handler handler) { 2505ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey synchronized (mRoutingChangeListeners) { 2506ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey if (listener != null && !mRoutingChangeListeners.containsKey(listener)) { 2507ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey testEnableNativeRoutingCallbacksLocked(); 2508ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey mRoutingChangeListeners.put( 2509ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey listener, new NativeRoutingEventHandlerDelegate(this, listener, 2510ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey handler != null ? handler : new Handler(mInitializationLooper))); 2511ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean } 2512ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean } 2513ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean } 2514ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean 2515ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean /** 2516ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean * Removes an {@link AudioRouting.OnRoutingChangedListener} which has been previously added 2517ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean * to receive rerouting notifications. 2518ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean * @param listener The previously added {@link AudioRouting.OnRoutingChangedListener} interface 2519ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean * to remove. 2520ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean */ 2521ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey @Override 2522ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey public void removeOnRoutingChangedListener(AudioRouting.OnRoutingChangedListener listener) { 2523ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey synchronized (mRoutingChangeListeners) { 2524ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey if (mRoutingChangeListeners.containsKey(listener)) { 2525ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey mRoutingChangeListeners.remove(listener); 2526ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey } 2527ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey testDisableNativeRoutingCallbacksLocked(); 2528ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean } 2529ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean } 2530ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean 2531ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean //-------------------------------------------------------------------------- 2532ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey // (Re)Routing Info 2533ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean //-------------------- 2534ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean /** 2535ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey * Defines the interface by which applications can receive notifications of 2536ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey * routing changes for the associated {@link AudioTrack}. 2537ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey * 2538ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey * @deprecated users should switch to the general purpose 2539ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey * {@link AudioRouting.OnRoutingChangedListener} class instead. 2540ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean */ 2541ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean @Deprecated 2542ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey public interface OnRoutingChangedListener extends AudioRouting.OnRoutingChangedListener { 2543ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean /** 2544ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey * Called when the routing of an AudioTrack changes from either and 2545ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey * explicit or policy rerouting. Use {@link #getRoutedDevice()} to 2546ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey * retrieve the newly routed-to device. 2547ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean */ 2548ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean public void onRoutingChanged(AudioTrack audioTrack); 2549ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean 2550ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey @Override 2551ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey default public void onRoutingChanged(AudioRouting router) { 2552ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey if (router instanceof AudioTrack) { 2553ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey onRoutingChanged((AudioTrack) router); 2554ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey } 2555ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey } 2556ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey } 2557d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean 2558d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean /** 2559e3383cc4539921756232ae4f3f54e99b95fb20ccPaul McLean * Adds an {@link OnRoutingChangedListener} to receive notifications of routing changes 2560d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean * on this AudioTrack. 25618e6c9f46172458624349755c9b1bc051f420d36dPaul McLean * @param listener The {@link OnRoutingChangedListener} interface to receive notifications 25628e6c9f46172458624349755c9b1bc051f420d36dPaul McLean * of rerouting events. 25638e6c9f46172458624349755c9b1bc051f420d36dPaul McLean * @param handler Specifies the {@link Handler} object for the thread on which to execute 25648e6c9f46172458624349755c9b1bc051f420d36dPaul McLean * the callback. If <code>null</code>, the {@link Handler} associated with the main 25658e6c9f46172458624349755c9b1bc051f420d36dPaul McLean * {@link Looper} will be used. 2566ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey * @deprecated users should switch to the general purpose 2567ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey * {@link AudioRouting.OnRoutingChangedListener} class instead. 2568d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean */ 2569ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean @Deprecated 2570e3383cc4539921756232ae4f3f54e99b95fb20ccPaul McLean public void addOnRoutingChangedListener(OnRoutingChangedListener listener, 2571d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean android.os.Handler handler) { 2572ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey addOnRoutingChangedListener((AudioRouting.OnRoutingChangedListener) listener, handler); 2573d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean } 2574d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean 2575d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean /** 2576e3383cc4539921756232ae4f3f54e99b95fb20ccPaul McLean * Removes an {@link OnRoutingChangedListener} which has been previously added 25778e6c9f46172458624349755c9b1bc051f420d36dPaul McLean * to receive rerouting notifications. 25788e6c9f46172458624349755c9b1bc051f420d36dPaul McLean * @param listener The previously added {@link OnRoutingChangedListener} interface to remove. 2579ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey * @deprecated users should switch to the general purpose 2580ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey * {@link AudioRouting.OnRoutingChangedListener} class instead. 2581d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean */ 2582ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean @Deprecated 2583e3383cc4539921756232ae4f3f54e99b95fb20ccPaul McLean public void removeOnRoutingChangedListener(OnRoutingChangedListener listener) { 2584ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey removeOnRoutingChangedListener((AudioRouting.OnRoutingChangedListener) listener); 2585d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean } 2586d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean 2587d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean /** 2588d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean * Sends device list change notification to all listeners. 2589d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean */ 2590d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean private void broadcastRoutingChange() { 2591ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean AudioManager.resetAudioPortGeneration(); 2592d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean synchronized (mRoutingChangeListeners) { 2593ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey for (NativeRoutingEventHandlerDelegate delegate : mRoutingChangeListeners.values()) { 2594ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey Handler handler = delegate.getHandler(); 2595ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey if (handler != null) { 2596ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey handler.sendEmptyMessage(AudioSystem.NATIVE_EVENT_ROUTING_CHANGE); 2597ed2edc7a8e044e31a6c9db638c97f9c21fb1d946Jeff Sharkey } 2598ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean } 2599ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean } 2600d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean } 2601d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean 26029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //--------------------------------------------------------- 26039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Interface definitions 26049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //-------------------- 26059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 26064df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project * Interface definition for a callback to be invoked when the playback head position of 26074df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project * an AudioTrack has reached a notification marker or has increased by a certain period. 26089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 26094df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project public interface OnPlaybackPositionUpdateListener { 26109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 26119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Called on the listener to notify it that the previously set marker has been reached 26129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * by the playback head. 26139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 26149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void onMarkerReached(AudioTrack track); 2615fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten 26169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 26179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Called on the listener to periodically notify it that the playback head has reached 26189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a multiple of the notification period. 26199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 26209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void onPeriodicNotification(AudioTrack track); 26219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 26229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 26239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //--------------------------------------------------------- 26249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Inner classes 26259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //-------------------- 26269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 26274df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project * Helper class to handle the forwarding of native events to the appropriate listener 26284df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project * (potentially) handled in a different thread 26295c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten */ 2630d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean private class NativePositionEventHandlerDelegate { 26314df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project private final Handler mHandler; 2632fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten 2633d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean NativePositionEventHandlerDelegate(final AudioTrack track, 263495bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten final OnPlaybackPositionUpdateListener listener, 263595bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten Handler handler) { 26364df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project // find the looper for our new event handler 26374df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project Looper looper; 26384df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project if (handler != null) { 26394df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project looper = handler.getLooper(); 26404df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project } else { 2641105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project // no given handler, use the looper the AudioTrack was created in 2642105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project looper = mInitializationLooper; 26439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2644fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten 26454df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project // construct the event handler with this looper 26464df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project if (looper != null) { 26474df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project // implement the event handler delegate 26484df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project mHandler = new Handler(looper) { 26494df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project @Override 26504df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project public void handleMessage(Message msg) { 265195bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten if (track == null) { 26524df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project return; 26534df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project } 26544df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project switch(msg.what) { 26554df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project case NATIVE_EVENT_MARKER: 26564df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project if (listener != null) { 265795bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten listener.onMarkerReached(track); 26584df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project } 26594df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project break; 26604df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project case NATIVE_EVENT_NEW_POS: 26614df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project if (listener != null) { 266295bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten listener.onPeriodicNotification(track); 26634df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project } 26644df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project break; 26654df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project default: 26661f61d01508651b4475397414e1fe06af1ab8fadaGlenn Kasten loge("Unknown native event type: " + msg.what); 26674df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project break; 26684df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project } 26694df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project } 26704df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project }; 26714df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project } else { 26724df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project mHandler = null; 2673fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten } 26744df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project } 2675fb2ab9efc3805c81521afb9ff91a58ff5097a36eGlenn Kasten 26764df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project Handler getHandler() { 26774df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project return mHandler; 26789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 26799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 26809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2681d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean /** 2682d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean * Helper class to handle the forwarding of native events to the appropriate listener 2683d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean * (potentially) handled in a different thread 2684d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean */ 2685d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean private class NativeRoutingEventHandlerDelegate { 2686d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean private final Handler mHandler; 2687d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean 2688d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean NativeRoutingEventHandlerDelegate(final AudioTrack track, 2689ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean final AudioRouting.OnRoutingChangedListener listener, 2690ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean Handler handler) { 2691ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean // find the looper for our new event handler 2692ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean Looper looper; 2693ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean if (handler != null) { 2694ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean looper = handler.getLooper(); 2695ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean } else { 2696ed36ca3d4f4f8aa0ee2951eab143a3c96b76158bPaul McLean // no given handler, use the looper the AudioTrack was created in 2697d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean looper = mInitializationLooper; 2698d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean } 2699d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean 2700d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean // construct the event handler with this looper 2701d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean if (looper != null) { 2702d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean // implement the event handler delegate 2703d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean mHandler = new Handler(looper) { 2704d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean @Override 2705d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean public void handleMessage(Message msg) { 2706d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean if (track == null) { 2707d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean return; 2708d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean } 2709d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean switch(msg.what) { 27104bcdba848449b33d7022de527c526943aff1f5fdEric Laurent case AudioSystem.NATIVE_EVENT_ROUTING_CHANGE: 2711d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean if (listener != null) { 2712e3383cc4539921756232ae4f3f54e99b95fb20ccPaul McLean listener.onRoutingChanged(track); 2713d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean } 2714d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean break; 2715d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean default: 2716d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean loge("Unknown native event type: " + msg.what); 2717d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean break; 2718d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean } 2719d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean } 2720d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean }; 2721d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean } else { 2722d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean mHandler = null; 2723d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean } 2724d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean } 2725d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean 2726d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean Handler getHandler() { 2727d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean return mHandler; 2728d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean } 2729d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean } 27309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //--------------------------------------------------------- 27329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Java methods called from the native side 27339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //-------------------- 27349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @SuppressWarnings("unused") 27359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void postEventFromNative(Object audiotrack_ref, 27369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int what, int arg1, int arg2, Object obj) { 27379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //logd("Event posted from the native side: event="+ what + " args="+ arg1+" "+arg2); 27389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AudioTrack track = (AudioTrack)((WeakReference)audiotrack_ref).get(); 27399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (track == null) { 27409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 27419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27434bcdba848449b33d7022de527c526943aff1f5fdEric Laurent if (what == AudioSystem.NATIVE_EVENT_ROUTING_CHANGE) { 27444bcdba848449b33d7022de527c526943aff1f5fdEric Laurent track.broadcastRoutingChange(); 27454bcdba848449b33d7022de527c526943aff1f5fdEric Laurent return; 27464bcdba848449b33d7022de527c526943aff1f5fdEric Laurent } 2747d5bad53a0cfb675d945442f5794ae991dbd035caPaul McLean NativePositionEventHandlerDelegate delegate = track.mEventHandlerDelegate; 274895bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten if (delegate != null) { 274995bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten Handler handler = delegate.getHandler(); 275095bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten if (handler != null) { 275195bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten Message m = handler.obtainMessage(what, arg1, arg2, obj); 275295bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten handler.sendMessage(m); 275395bd2329c6a36211f18be3e089eaa775ec62df62Glenn Kasten } 27549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //--------------------------------------------------------- 27599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Native methods called from the Java side 27609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //-------------------- 27619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2762a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi // post-condition: mStreamType is overwritten with a value 2763a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi // that reflects the audio attributes (e.g. an AudioAttributes object with a usage of 2764a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi // AudioAttributes.USAGE_MEDIA will map to AudioManager.STREAM_MUSIC 2765a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi private native final int native_setup(Object /*WeakReference<AudioTrack>*/ audiotrack_this, 2766a1d80e3b1d210c60c6881a55ed39a4077ff66080Jean-Michel Trivi Object /*AudioAttributes*/ attributes, 27671cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten int[] sampleRate, int channelMask, int channelIndexMask, int audioFormat, 27689b09e533ac67d3d25465e3312b4957bc90b0c84fPaul McLean int buffSizeInBytes, int mode, int[] sessionId, long nativeAudioTrack); 27699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native final void native_finalize(); 27719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2772c69ac54111b271bdaf2dd9e40218906435bbde9fPaul McLean /** 2773c69ac54111b271bdaf2dd9e40218906435bbde9fPaul McLean * @hide 2774c69ac54111b271bdaf2dd9e40218906435bbde9fPaul McLean */ 2775c69ac54111b271bdaf2dd9e40218906435bbde9fPaul McLean public native final void native_release(); 27769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native final void native_start(); 27789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native final void native_stop(); 27809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native final void native_pause(); 27829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native final void native_flush(); 27849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native final int native_write_byte(byte[] audioData, 27867ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi int offsetInBytes, int sizeInBytes, int format, 27877ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi boolean isBlocking); 27889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native final int native_write_short(short[] audioData, 27904aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung int offsetInShorts, int sizeInShorts, int format, 27914aacc903e3f0216a1aec00d57d34f902025d5bd0Andy Hung boolean isBlocking); 27929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 279354955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten private native final int native_write_float(float[] audioData, 279454955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten int offsetInFloats, int sizeInFloats, int format, 279554955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten boolean isBlocking); 279654955e33c8612a737a76177408f3e7c8482cfcf4Glenn Kasten 27977ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi private native final int native_write_native_bytes(Object audioData, 27985d21f679c58dbb13c8c931ffec6e06b6b8cd454fJean-Michel Trivi int positionInBytes, int sizeInBytes, int format, boolean blocking); 27997ca0452fa62b9c15bd45b0fd52aef97442555a6eJean-Michel Trivi 28009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native final int native_reload_static(); 28019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 280210a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk private native final int native_get_buffer_size_frames(); 280310a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk private native final int native_set_buffer_size_frames(int bufferSizeInFrames); 280410a33e499c97767f8d6bfc6514ba8b5f485394daPhil Burk private native final int native_get_buffer_capacity_frames(); 28059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 28069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native final void native_setVolume(float leftVolume, float rightVolume); 28079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 280888e209dcf8c2ebddda5c272f46d1bd5478bc639cEric Laurent private native final int native_set_playback_rate(int sampleRateInHz); 280988e209dcf8c2ebddda5c272f46d1bd5478bc639cEric Laurent private native final int native_get_playback_rate(); 28109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 28112d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia private native final void native_set_playback_params(@NonNull PlaybackParams params); 28122d61e2b97c92ac2de80ebb3782b728ae5cdf5306Wei Jia private native final @NonNull PlaybackParams native_get_playback_params(); 2813263b4c97823295c41900210515d0c769a236190cAndy Hung 28149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native final int native_set_marker_pos(int marker); 28159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native final int native_get_marker_pos(); 28169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 28179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native final int native_set_pos_update_period(int updatePeriod); 28189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native final int native_get_pos_update_period(); 28199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 28209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native final int native_set_position(int position); 28219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native final int native_get_position(); 28229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 282361dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman private native final int native_get_latency(); 282461dcdf3764b614c6f01e77cb4342d192e3101f8aOliver Woodman 282503f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk private native final int native_get_underrun_count(); 282603f61bbb2e7293592ad4a304b0f0b8e6ee8e6aacPhil Burk 2827948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten // longArray must be a non-null array of length >= 2 2828948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten // [0] is assigned the frame position 2829948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten // [1] is assigned the time in CLOCK_MONOTONIC nanoseconds 2830948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten private native final int native_get_timestamp(long[] longArray); 2831948c2e6ff46d65942277f2e0e9ce0c038972b9d8Glenn Kasten 28329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private native final int native_set_loop(int start, int end, int loopCount); 28339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 28349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static private native final int native_get_output_sample_rate(int streamType); 28359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static private native final int native_get_min_buff_size( 28369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int sampleRateInHz, int channelConfig, int audioFormat); 28379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 28387070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent private native final int native_attachAuxEffect(int effectId); 28393009f0b911e39d3b26c69bd7667d6444eacb9d11Glenn Kasten private native final int native_setAuxEffectSendLevel(float level); 28407070b36549d511d6627538c73dfbab23fbae5b43Eric Laurent 284188e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean private native final boolean native_setOutputDevice(int deviceId); 28424bcdba848449b33d7022de527c526943aff1f5fdEric Laurent private native final int native_getRoutedDeviceId(); 28434bcdba848449b33d7022de527c526943aff1f5fdEric Laurent private native final void native_enableDeviceCallback(); 28444bcdba848449b33d7022de527c526943aff1f5fdEric Laurent private native final void native_disableDeviceCallback(); 284525d3c7c49bafb22723138bfab2e315d2d0a926fbGlenn Kasten static private native int native_get_FCC_8(); 284688e1d86a879d8802e775dd0566ffb64425e8e3c8Paul McLean 28479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //--------------------------------------------------------- 28489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Utility methods 28499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //------------------ 28509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 28519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void logd(String msg) { 28521f61d01508651b4475397414e1fe06af1ab8fadaGlenn Kasten Log.d(TAG, msg); 28539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 28549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 28559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void loge(String msg) { 28561f61d01508651b4475397414e1fe06af1ab8fadaGlenn Kasten Log.e(TAG, msg); 28579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 28589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2859