AudioTrack.java revision 5a4ee7b62ecf680c4408c0cc0cccf7780bdfa0ce
1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.media; 18 19import java.lang.annotation.Retention; 20import java.lang.annotation.RetentionPolicy; 21import java.lang.ref.WeakReference; 22import java.lang.Math; 23import java.nio.ByteBuffer; 24import java.nio.ByteOrder; 25import java.nio.NioUtils; 26import java.util.Collection; 27 28import android.annotation.IntDef; 29import android.annotation.NonNull; 30import android.annotation.SystemApi; 31import android.app.ActivityThread; 32import android.app.AppOpsManager; 33import android.content.Context; 34import android.os.Handler; 35import android.os.IBinder; 36import android.os.Looper; 37import android.os.Message; 38import android.os.Process; 39import android.os.RemoteException; 40import android.os.ServiceManager; 41import android.util.ArrayMap; 42import android.util.Log; 43 44import com.android.internal.app.IAppOpsService; 45 46 47/** 48 * The AudioTrack class manages and plays a single audio resource for Java applications. 49 * It allows streaming of PCM audio buffers to the audio sink for playback. This is 50 * achieved by "pushing" the data to the AudioTrack object using one of the 51 * {@link #write(byte[], int, int)}, {@link #write(short[], int, int)}, 52 * and {@link #write(float[], int, int, int)} methods. 53 * 54 * <p>An AudioTrack instance can operate under two modes: static or streaming.<br> 55 * In Streaming mode, the application writes a continuous stream of data to the AudioTrack, using 56 * one of the {@code write()} methods. These are blocking and return when the data has been 57 * transferred from the Java layer to the native layer and queued for playback. The streaming 58 * mode is most useful when playing blocks of audio data that for instance are: 59 * 60 * <ul> 61 * <li>too big to fit in memory because of the duration of the sound to play,</li> 62 * <li>too big to fit in memory because of the characteristics of the audio data 63 * (high sampling rate, bits per sample ...)</li> 64 * <li>received or generated while previously queued audio is playing.</li> 65 * </ul> 66 * 67 * The static mode should be chosen when dealing with short sounds that fit in memory and 68 * that need to be played with the smallest latency possible. The static mode will 69 * therefore be preferred for UI and game sounds that are played often, and with the 70 * smallest overhead possible. 71 * 72 * <p>Upon creation, an AudioTrack object initializes its associated audio buffer. 73 * The size of this buffer, specified during the construction, determines how long an AudioTrack 74 * can play before running out of data.<br> 75 * For an AudioTrack using the static mode, this size is the maximum size of the sound that can 76 * be played from it.<br> 77 * For the streaming mode, data will be written to the audio sink in chunks of 78 * sizes less than or equal to the total buffer size. 79 * 80 * AudioTrack is not final and thus permits subclasses, but such use is not recommended. 81 */ 82public class AudioTrack 83{ 84 //--------------------------------------------------------- 85 // Constants 86 //-------------------- 87 /** Minimum value for a linear gain or auxiliary effect level. 88 * This value must be exactly equal to 0.0f; do not change it. 89 */ 90 private static final float GAIN_MIN = 0.0f; 91 /** Maximum value for a linear gain or auxiliary effect level. 92 * This value must be greater than or equal to 1.0f. 93 */ 94 private static final float GAIN_MAX = 1.0f; 95 96 /** Minimum value for sample rate */ 97 private static final int SAMPLE_RATE_HZ_MIN = 4000; 98 /** Maximum value for sample rate */ 99 private static final int SAMPLE_RATE_HZ_MAX = 192000; 100 101 /** Maximum value for AudioTrack channel count */ 102 private static final int CHANNEL_COUNT_MAX = 8; 103 104 /** indicates AudioTrack state is stopped */ 105 public static final int PLAYSTATE_STOPPED = 1; // matches SL_PLAYSTATE_STOPPED 106 /** indicates AudioTrack state is paused */ 107 public static final int PLAYSTATE_PAUSED = 2; // matches SL_PLAYSTATE_PAUSED 108 /** indicates AudioTrack state is playing */ 109 public static final int PLAYSTATE_PLAYING = 3; // matches SL_PLAYSTATE_PLAYING 110 111 // keep these values in sync with android_media_AudioTrack.cpp 112 /** 113 * Creation mode where audio data is transferred from Java to the native layer 114 * only once before the audio starts playing. 115 */ 116 public static final int MODE_STATIC = 0; 117 /** 118 * Creation mode where audio data is streamed from Java to the native layer 119 * as the audio is playing. 120 */ 121 public static final int MODE_STREAM = 1; 122 123 /** @hide */ 124 @IntDef({ 125 MODE_STATIC, 126 MODE_STREAM 127 }) 128 @Retention(RetentionPolicy.SOURCE) 129 public @interface TransferMode {} 130 131 /** 132 * State of an AudioTrack that was not successfully initialized upon creation. 133 */ 134 public static final int STATE_UNINITIALIZED = 0; 135 /** 136 * State of an AudioTrack that is ready to be used. 137 */ 138 public static final int STATE_INITIALIZED = 1; 139 /** 140 * State of a successfully initialized AudioTrack that uses static data, 141 * but that hasn't received that data yet. 142 */ 143 public static final int STATE_NO_STATIC_DATA = 2; 144 145 /** 146 * Denotes a successful operation. 147 */ 148 public static final int SUCCESS = AudioSystem.SUCCESS; 149 /** 150 * Denotes a generic operation failure. 151 */ 152 public static final int ERROR = AudioSystem.ERROR; 153 /** 154 * Denotes a failure due to the use of an invalid value. 155 */ 156 public static final int ERROR_BAD_VALUE = AudioSystem.BAD_VALUE; 157 /** 158 * Denotes a failure due to the improper use of a method. 159 */ 160 public static final int ERROR_INVALID_OPERATION = AudioSystem.INVALID_OPERATION; 161 162 // Error codes: 163 // to keep in sync with frameworks/base/core/jni/android_media_AudioTrack.cpp 164 private static final int ERROR_NATIVESETUP_AUDIOSYSTEM = -16; 165 private static final int ERROR_NATIVESETUP_INVALIDCHANNELMASK = -17; 166 private static final int ERROR_NATIVESETUP_INVALIDFORMAT = -18; 167 private static final int ERROR_NATIVESETUP_INVALIDSTREAMTYPE = -19; 168 private static final int ERROR_NATIVESETUP_NATIVEINITFAILED = -20; 169 170 // Events: 171 // to keep in sync with frameworks/av/include/media/AudioTrack.h 172 /** 173 * Event id denotes when playback head has reached a previously set marker. 174 */ 175 private static final int NATIVE_EVENT_MARKER = 3; 176 /** 177 * Event id denotes when previously set update period has elapsed during playback. 178 */ 179 private static final int NATIVE_EVENT_NEW_POS = 4; 180 181 /** 182 * Event id denotes when the routing changes. 183 */ 184 private final static int NATIVE_EVENT_ROUTING_CHANGE = 1000; 185 186 187 private final static String TAG = "android.media.AudioTrack"; 188 189 190 /** @hide */ 191 @IntDef({ 192 WRITE_BLOCKING, 193 WRITE_NON_BLOCKING 194 }) 195 @Retention(RetentionPolicy.SOURCE) 196 public @interface WriteMode {} 197 198 /** 199 * The write mode indicating the write operation will block until all data has been written, 200 * to be used in {@link #write(ByteBuffer, int, int)} 201 */ 202 public final static int WRITE_BLOCKING = 0; 203 /** 204 * The write mode indicating the write operation will return immediately after 205 * queuing as much audio data for playback as possible without blocking, to be used in 206 * {@link #write(ByteBuffer, int, int)}. 207 */ 208 public final static int WRITE_NON_BLOCKING = 1; 209 210 //-------------------------------------------------------------------------- 211 // Member variables 212 //-------------------- 213 /** 214 * Indicates the state of the AudioTrack instance. 215 */ 216 private int mState = STATE_UNINITIALIZED; 217 /** 218 * Indicates the play state of the AudioTrack instance. 219 */ 220 private int mPlayState = PLAYSTATE_STOPPED; 221 /** 222 * Lock to make sure mPlayState updates are reflecting the actual state of the object. 223 */ 224 private final Object mPlayStateLock = new Object(); 225 /** 226 * Sizes of the native audio buffer. 227 * These values are set during construction and can be stale. 228 * To obtain the current native audio buffer frame count use {@link #getNativeFrameCount()}. 229 */ 230 private int mNativeBufferSizeInBytes = 0; 231 private int mNativeBufferSizeInFrames = 0; 232 /** 233 * Handler for events coming from the native code. 234 */ 235 private NativePositionEventHandlerDelegate mEventHandlerDelegate; 236 /** 237 * Looper associated with the thread that creates the AudioTrack instance. 238 */ 239 private final Looper mInitializationLooper; 240 /** 241 * The audio data source sampling rate in Hz. 242 */ 243 private int mSampleRate; // initialized by all constructors 244 /** 245 * The number of audio output channels (1 is mono, 2 is stereo). 246 */ 247 private int mChannelCount = 1; 248 /** 249 * The audio channel mask used for calling native AudioTrack 250 */ 251 private int mChannels = AudioFormat.CHANNEL_OUT_MONO; 252 253 /** 254 * The type of the audio stream to play. See 255 * {@link AudioManager#STREAM_VOICE_CALL}, {@link AudioManager#STREAM_SYSTEM}, 256 * {@link AudioManager#STREAM_RING}, {@link AudioManager#STREAM_MUSIC}, 257 * {@link AudioManager#STREAM_ALARM}, {@link AudioManager#STREAM_NOTIFICATION}, and 258 * {@link AudioManager#STREAM_DTMF}. 259 */ 260 private int mStreamType = AudioManager.STREAM_MUSIC; 261 262 private final AudioAttributes mAttributes; 263 /** 264 * The way audio is consumed by the audio sink, streaming or static. 265 */ 266 private int mDataLoadMode = MODE_STREAM; 267 /** 268 * The current channel position mask, as specified on AudioTrack creation. 269 * Can be set simultaneously with channel index mask {@link #mChannelIndexMask}. 270 * May be set to {@link AudioFormat#CHANNEL_INVALID} if a channel index mask is specified. 271 */ 272 private int mChannelConfiguration = AudioFormat.CHANNEL_OUT_MONO; 273 /** 274 * The current audio channel index configuration (if specified). 275 */ 276 private int mChannelIndexMask = 0; 277 /** 278 * The encoding of the audio samples. 279 * @see AudioFormat#ENCODING_PCM_8BIT 280 * @see AudioFormat#ENCODING_PCM_16BIT 281 * @see AudioFormat#ENCODING_PCM_FLOAT 282 */ 283 private int mAudioFormat = AudioFormat.ENCODING_PCM_16BIT; 284 /** 285 * Audio session ID 286 */ 287 private int mSessionId = AudioSystem.AUDIO_SESSION_ALLOCATE; 288 /** 289 * Reference to the app-ops service. 290 */ 291 private final IAppOpsService mAppOps; 292 /** 293 * HW_AV_SYNC track AV Sync Header 294 */ 295 private ByteBuffer mAvSyncHeader = null; 296 /** 297 * HW_AV_SYNC track audio data bytes remaining to write after current AV sync header 298 */ 299 private int mAvSyncBytesRemaining = 0; 300 301 //-------------------------------- 302 // Used exclusively by native code 303 //-------------------- 304 /** 305 * Accessed by native methods: provides access to C++ AudioTrack object. 306 */ 307 @SuppressWarnings("unused") 308 private long mNativeTrackInJavaObj; 309 /** 310 * Accessed by native methods: provides access to the JNI data (i.e. resources used by 311 * the native AudioTrack object, but not stored in it). 312 */ 313 @SuppressWarnings("unused") 314 private long mJniData; 315 316 317 //-------------------------------------------------------------------------- 318 // Constructor, Finalize 319 //-------------------- 320 /** 321 * Class constructor. 322 * @param streamType the type of the audio stream. See 323 * {@link AudioManager#STREAM_VOICE_CALL}, {@link AudioManager#STREAM_SYSTEM}, 324 * {@link AudioManager#STREAM_RING}, {@link AudioManager#STREAM_MUSIC}, 325 * {@link AudioManager#STREAM_ALARM}, and {@link AudioManager#STREAM_NOTIFICATION}. 326 * @param sampleRateInHz the initial source sample rate expressed in Hz. 327 * @param channelConfig describes the configuration of the audio channels. 328 * See {@link AudioFormat#CHANNEL_OUT_MONO} and 329 * {@link AudioFormat#CHANNEL_OUT_STEREO} 330 * @param audioFormat the format in which the audio data is represented. 331 * See {@link AudioFormat#ENCODING_PCM_16BIT}, 332 * {@link AudioFormat#ENCODING_PCM_8BIT}, 333 * and {@link AudioFormat#ENCODING_PCM_FLOAT}. 334 * @param bufferSizeInBytes the total size (in bytes) of the internal buffer where audio data is 335 * read from for playback. This should be a multiple of the frame size in bytes. 336 * <p> If the track's creation mode is {@link #MODE_STATIC}, 337 * this is the maximum length sample, or audio clip, that can be played by this instance. 338 * <p> If the track's creation mode is {@link #MODE_STREAM}, 339 * this should be the desired buffer size 340 * for the <code>AudioTrack</code> to satisfy the application's 341 * natural latency requirements. 342 * If <code>bufferSizeInBytes</code> is less than the 343 * minimum buffer size for the output sink, it is automatically increased to the minimum 344 * buffer size. 345 * The method {@link #getNativeFrameCount()} returns the 346 * actual size in frames of the native buffer created, which 347 * determines the frequency to write 348 * to the streaming <code>AudioTrack</code> to avoid underrun. 349 * @param mode streaming or static buffer. See {@link #MODE_STATIC} and {@link #MODE_STREAM} 350 * @throws java.lang.IllegalArgumentException 351 */ 352 public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat, 353 int bufferSizeInBytes, int mode) 354 throws IllegalArgumentException { 355 this(streamType, sampleRateInHz, channelConfig, audioFormat, 356 bufferSizeInBytes, mode, AudioSystem.AUDIO_SESSION_ALLOCATE); 357 } 358 359 /** 360 * Class constructor with audio session. Use this constructor when the AudioTrack must be 361 * attached to a particular audio session. The primary use of the audio session ID is to 362 * associate audio effects to a particular instance of AudioTrack: if an audio session ID 363 * is provided when creating an AudioEffect, this effect will be applied only to audio tracks 364 * and media players in the same session and not to the output mix. 365 * When an AudioTrack is created without specifying a session, it will create its own session 366 * which can be retrieved by calling the {@link #getAudioSessionId()} method. 367 * If a non-zero session ID is provided, this AudioTrack will share effects attached to this 368 * session 369 * with all other media players or audio tracks in the same session, otherwise a new session 370 * will be created for this track if none is supplied. 371 * @param streamType the type of the audio stream. See 372 * {@link AudioManager#STREAM_VOICE_CALL}, {@link AudioManager#STREAM_SYSTEM}, 373 * {@link AudioManager#STREAM_RING}, {@link AudioManager#STREAM_MUSIC}, 374 * {@link AudioManager#STREAM_ALARM}, and {@link AudioManager#STREAM_NOTIFICATION}. 375 * @param sampleRateInHz the initial source sample rate expressed in Hz. 376 * @param channelConfig describes the configuration of the audio channels. 377 * See {@link AudioFormat#CHANNEL_OUT_MONO} and 378 * {@link AudioFormat#CHANNEL_OUT_STEREO} 379 * @param audioFormat the format in which the audio data is represented. 380 * See {@link AudioFormat#ENCODING_PCM_16BIT} and 381 * {@link AudioFormat#ENCODING_PCM_8BIT}, 382 * and {@link AudioFormat#ENCODING_PCM_FLOAT}. 383 * @param bufferSizeInBytes the total size (in bytes) of the buffer where audio data is read 384 * from for playback. If using the AudioTrack in streaming mode, you can write data into 385 * this buffer in smaller chunks than this size. If using the AudioTrack in static mode, 386 * this is the maximum size of the sound that will be played for this instance. 387 * See {@link #getMinBufferSize(int, int, int)} to determine the minimum required buffer size 388 * for the successful creation of an AudioTrack instance in streaming mode. Using values 389 * smaller than getMinBufferSize() will result in an initialization failure. 390 * @param mode streaming or static buffer. See {@link #MODE_STATIC} and {@link #MODE_STREAM} 391 * @param sessionId Id of audio session the AudioTrack must be attached to 392 * @throws java.lang.IllegalArgumentException 393 */ 394 public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat, 395 int bufferSizeInBytes, int mode, int sessionId) 396 throws IllegalArgumentException { 397 // mState already == STATE_UNINITIALIZED 398 this((new AudioAttributes.Builder()) 399 .setLegacyStreamType(streamType) 400 .build(), 401 (new AudioFormat.Builder()) 402 .setChannelMask(channelConfig) 403 .setEncoding(audioFormat) 404 .setSampleRate(sampleRateInHz) 405 .build(), 406 bufferSizeInBytes, 407 mode, sessionId); 408 } 409 410 /** 411 * Class constructor with {@link AudioAttributes} and {@link AudioFormat}. 412 * @param attributes a non-null {@link AudioAttributes} instance. 413 * @param format a non-null {@link AudioFormat} instance describing the format of the data 414 * that will be played through this AudioTrack. See {@link AudioFormat.Builder} for 415 * configuring the audio format parameters such as encoding, channel mask and sample rate. 416 * @param bufferSizeInBytes the total size (in bytes) of the buffer where audio data is read 417 * from for playback. If using the AudioTrack in streaming mode, you can write data into 418 * this buffer in smaller chunks than this size. If using the AudioTrack in static mode, 419 * this is the maximum size of the sound that will be played for this instance. 420 * See {@link #getMinBufferSize(int, int, int)} to determine the minimum required buffer size 421 * for the successful creation of an AudioTrack instance in streaming mode. Using values 422 * smaller than getMinBufferSize() will result in an initialization failure. 423 * @param mode streaming or static buffer. See {@link #MODE_STATIC} and {@link #MODE_STREAM}. 424 * @param sessionId ID of audio session the AudioTrack must be attached to, or 425 * {@link AudioManager#AUDIO_SESSION_ID_GENERATE} if the session isn't known at construction 426 * time. See also {@link AudioManager#generateAudioSessionId()} to obtain a session ID before 427 * construction. 428 * @throws IllegalArgumentException 429 */ 430 public AudioTrack(AudioAttributes attributes, AudioFormat format, int bufferSizeInBytes, 431 int mode, int sessionId) 432 throws IllegalArgumentException { 433 // mState already == STATE_UNINITIALIZED 434 435 if (attributes == null) { 436 throw new IllegalArgumentException("Illegal null AudioAttributes"); 437 } 438 if (format == null) { 439 throw new IllegalArgumentException("Illegal null AudioFormat"); 440 } 441 442 // remember which looper is associated with the AudioTrack instantiation 443 Looper looper; 444 if ((looper = Looper.myLooper()) == null) { 445 looper = Looper.getMainLooper(); 446 } 447 448 int rate = 0; 449 if ((format.getPropertySetMask() & AudioFormat.AUDIO_FORMAT_HAS_PROPERTY_SAMPLE_RATE) != 0) 450 { 451 rate = format.getSampleRate(); 452 } else { 453 rate = AudioSystem.getPrimaryOutputSamplingRate(); 454 if (rate <= 0) { 455 rate = 44100; 456 } 457 } 458 int channelIndexMask = 0; 459 if ((format.getPropertySetMask() 460 & AudioFormat.AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_INDEX_MASK) != 0) { 461 channelIndexMask = format.getChannelIndexMask(); 462 } 463 int channelMask = 0; 464 if ((format.getPropertySetMask() 465 & AudioFormat.AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_MASK) != 0) { 466 channelMask = format.getChannelMask(); 467 } else if (channelIndexMask == 0) { // if no masks at all, use stereo 468 channelMask = AudioFormat.CHANNEL_OUT_FRONT_LEFT 469 | AudioFormat.CHANNEL_OUT_FRONT_RIGHT; 470 } 471 int encoding = AudioFormat.ENCODING_DEFAULT; 472 if ((format.getPropertySetMask() & AudioFormat.AUDIO_FORMAT_HAS_PROPERTY_ENCODING) != 0) { 473 encoding = format.getEncoding(); 474 } 475 audioParamCheck(rate, channelMask, channelIndexMask, encoding, mode); 476 mStreamType = AudioSystem.STREAM_DEFAULT; 477 478 audioBuffSizeCheck(bufferSizeInBytes); 479 480 mInitializationLooper = looper; 481 IBinder b = ServiceManager.getService(Context.APP_OPS_SERVICE); 482 mAppOps = IAppOpsService.Stub.asInterface(b); 483 484 mAttributes = (new AudioAttributes.Builder(attributes).build()); 485 486 if (sessionId < 0) { 487 throw new IllegalArgumentException("Invalid audio session ID: "+sessionId); 488 } 489 490 int[] session = new int[1]; 491 session[0] = sessionId; 492 // native initialization 493 int initResult = native_setup(new WeakReference<AudioTrack>(this), mAttributes, 494 mSampleRate, mChannels, mAudioFormat, 495 mNativeBufferSizeInBytes, mDataLoadMode, session); 496 if (initResult != SUCCESS) { 497 loge("Error code "+initResult+" when initializing AudioTrack."); 498 return; // with mState == STATE_UNINITIALIZED 499 } 500 501 mSessionId = session[0]; 502 503 if (mDataLoadMode == MODE_STATIC) { 504 mState = STATE_NO_STATIC_DATA; 505 } else { 506 mState = STATE_INITIALIZED; 507 } 508 } 509 510 /** 511 * Builder class for {@link AudioTrack} objects. 512 * Use this class to configure and create an <code>AudioTrack</code> instance. By setting audio 513 * attributes and audio format parameters, you indicate which of those vary from the default 514 * behavior on the device. 515 * <p> Here is an example where <code>Builder</code> is used to specify all {@link AudioFormat} 516 * parameters, to be used by a new <code>AudioTrack</code> instance: 517 * 518 * <pre class="prettyprint"> 519 * AudioTrack player = new AudioTrack.Builder() 520 * .setAudioAttributes(new AudioAttributes.Builder() 521 * .setUsage(AudioAttributes.USAGE_ALARM) 522 * .setContentType(CONTENT_TYPE_MUSIC) 523 * .build()) 524 * .setAudioFormat(new AudioFormat.Builder() 525 * .setEncoding(AudioFormat.ENCODING_PCM_16BIT) 526 * .setSampleRate(441000) 527 * .setChannelMask(AudioFormat.CHANNEL_OUT_STEREO) 528 * .build()) 529 * .setBufferSize(minBuffSize) 530 * .build(); 531 * </pre> 532 * <p> 533 * If the audio attributes are not set with {@link #setAudioAttributes(AudioAttributes)}, 534 * attributes comprising {@link AudioAttributes#USAGE_MEDIA} will be used. 535 * <br>If the audio format is not specified or is incomplete, its sample rate will be the 536 * default output sample rate of the device (see 537 * {@link AudioManager#PROPERTY_OUTPUT_SAMPLE_RATE}), its channel configuration will be 538 * {@link AudioFormat#CHANNEL_OUT_STEREO} and the encoding will be 539 * {@link AudioFormat#ENCODING_PCM_16BIT}. 540 * <br>If the buffer size is not specified with {@link #setBufferSizeInBytes(int)}, 541 * and the mode is {@link AudioTrack#MODE_STREAM}, the minimum buffer size is used. 542 * <br>If the transfer mode is not specified with {@link #setTransferMode(int)}, 543 * <code>MODE_STREAM</code> will be used. 544 * <br>If the session ID is not specified with {@link #setSessionId(int)}, a new one will 545 * be generated. 546 */ 547 public static class Builder { 548 private AudioAttributes mAttributes; 549 private AudioFormat mFormat; 550 private int mBufferSizeInBytes; 551 private int mSessionId = AudioManager.AUDIO_SESSION_ID_GENERATE; 552 private int mMode = MODE_STREAM; 553 554 /** 555 * Constructs a new Builder with the default values as described above. 556 */ 557 public Builder() { 558 } 559 560 /** 561 * Sets the {@link AudioAttributes}. 562 * @param attributes a non-null {@link AudioAttributes} instance that describes the audio 563 * data to be played. 564 * @return the same Builder instance. 565 * @throws IllegalArgumentException 566 */ 567 public @NonNull Builder setAudioAttributes(@NonNull AudioAttributes attributes) 568 throws IllegalArgumentException { 569 if (attributes == null) { 570 throw new IllegalArgumentException("Illegal null AudioAttributes argument"); 571 } 572 // keep reference, we only copy the data when building 573 mAttributes = attributes; 574 return this; 575 } 576 577 /** 578 * Sets the format of the audio data to be played by the {@link AudioTrack}. 579 * See {@link AudioFormat.Builder} for configuring the audio format parameters such 580 * as encoding, channel mask and sample rate. 581 * @param format a non-null {@link AudioFormat} instance. 582 * @return the same Builder instance. 583 * @throws IllegalArgumentException 584 */ 585 public @NonNull Builder setAudioFormat(@NonNull AudioFormat format) 586 throws IllegalArgumentException { 587 if (format == null) { 588 throw new IllegalArgumentException("Illegal null AudioFormat argument"); 589 } 590 // keep reference, we only copy the data when building 591 mFormat = format; 592 return this; 593 } 594 595 /** 596 * Sets the total size (in bytes) of the buffer where audio data is read from for playback. 597 * If using the {@link AudioTrack} in streaming mode 598 * (see {@link AudioTrack#MODE_STREAM}, you can write data into this buffer in smaller 599 * chunks than this size. See {@link #getMinBufferSize(int, int, int)} to determine 600 * the minimum required buffer size for the successful creation of an AudioTrack instance 601 * in streaming mode. Using values smaller than <code>getMinBufferSize()</code> will result 602 * in an exception when trying to build the <code>AudioTrack</code>. 603 * <br>If using the <code>AudioTrack</code> in static mode (see 604 * {@link AudioTrack#MODE_STATIC}), this is the maximum size of the sound that will be 605 * played by this instance. 606 * @param bufferSizeInBytes 607 * @return the same Builder instance. 608 * @throws IllegalArgumentException 609 */ 610 public @NonNull Builder setBufferSizeInBytes(int bufferSizeInBytes) 611 throws IllegalArgumentException { 612 if (bufferSizeInBytes <= 0) { 613 throw new IllegalArgumentException("Invalid buffer size " + bufferSizeInBytes); 614 } 615 mBufferSizeInBytes = bufferSizeInBytes; 616 return this; 617 } 618 619 /** 620 * Sets the mode under which buffers of audio data are transferred from the 621 * {@link AudioTrack} to the framework. 622 * @param mode one of {@link AudioTrack#MODE_STREAM}, {@link AudioTrack#MODE_STATIC}. 623 * @return the same Builder instance. 624 * @throws IllegalArgumentException 625 */ 626 public @NonNull Builder setTransferMode(@TransferMode int mode) 627 throws IllegalArgumentException { 628 switch(mode) { 629 case MODE_STREAM: 630 case MODE_STATIC: 631 mMode = mode; 632 break; 633 default: 634 throw new IllegalArgumentException("Invalid transfer mode " + mode); 635 } 636 return this; 637 } 638 639 /** 640 * Sets the session ID the {@link AudioTrack} will be attached to. 641 * @param sessionId a strictly positive ID number retrieved from another 642 * <code>AudioTrack</code> via {@link AudioTrack#getAudioSessionId()} or allocated by 643 * {@link AudioManager} via {@link AudioManager#generateAudioSessionId()}, or 644 * {@link AudioManager#AUDIO_SESSION_ID_GENERATE}. 645 * @return the same Builder instance. 646 * @throws IllegalArgumentException 647 */ 648 public @NonNull Builder setSessionId(int sessionId) 649 throws IllegalArgumentException { 650 if ((sessionId != AudioManager.AUDIO_SESSION_ID_GENERATE) && (sessionId < 1)) { 651 throw new IllegalArgumentException("Invalid audio session ID " + sessionId); 652 } 653 mSessionId = sessionId; 654 return this; 655 } 656 657 /** 658 * Builds an {@link AudioTrack} instance initialized with all the parameters set 659 * on this <code>Builder</code>. 660 * @return a new {@link AudioTrack} instance. 661 * @throws UnsupportedOperationException if the parameters set on the <code>Builder</code> 662 * were incompatible, or if they are not supported by the device. 663 */ 664 public @NonNull AudioTrack build() throws UnsupportedOperationException { 665 if (mAttributes == null) { 666 mAttributes = new AudioAttributes.Builder() 667 .setUsage(AudioAttributes.USAGE_MEDIA) 668 .build(); 669 } 670 if (mFormat == null) { 671 mFormat = new AudioFormat.Builder() 672 .setChannelMask(AudioFormat.CHANNEL_OUT_STEREO) 673 .setSampleRate(AudioSystem.getPrimaryOutputSamplingRate()) 674 .setEncoding(AudioFormat.ENCODING_DEFAULT) 675 .build(); 676 } 677 try { 678 // If the buffer size is not specified in streaming mode, 679 // use a single frame for the buffer size and let the 680 // native code figure out the minimum buffer size. 681 if (mMode == MODE_STREAM && mBufferSizeInBytes == 0) { 682 mBufferSizeInBytes = mFormat.getChannelCount() 683 * mFormat.getBytesPerSample(mFormat.getEncoding()); 684 } 685 return new AudioTrack(mAttributes, mFormat, mBufferSizeInBytes, mMode, mSessionId); 686 } catch (IllegalArgumentException e) { 687 throw new UnsupportedOperationException(e.getMessage()); 688 } 689 } 690 } 691 692 // mask of all the channels supported by this implementation 693 private static final int SUPPORTED_OUT_CHANNELS = 694 AudioFormat.CHANNEL_OUT_FRONT_LEFT | 695 AudioFormat.CHANNEL_OUT_FRONT_RIGHT | 696 AudioFormat.CHANNEL_OUT_FRONT_CENTER | 697 AudioFormat.CHANNEL_OUT_LOW_FREQUENCY | 698 AudioFormat.CHANNEL_OUT_BACK_LEFT | 699 AudioFormat.CHANNEL_OUT_BACK_RIGHT | 700 AudioFormat.CHANNEL_OUT_BACK_CENTER | 701 AudioFormat.CHANNEL_OUT_SIDE_LEFT | 702 AudioFormat.CHANNEL_OUT_SIDE_RIGHT; 703 704 // Java channel mask definitions below match those 705 // in /system/core/include/system/audio.h in the JNI code of AudioTrack. 706 707 // internal maximum size for bits parameter, not part of public API 708 private static final int AUDIO_CHANNEL_BITS_LOG2 = 30; 709 710 // log(2) of maximum number of representations, not part of public API 711 private static final int AUDIO_CHANNEL_REPRESENTATION_LOG2 = 2; 712 713 // used to create a channel index mask or channel position mask 714 // with getChannelMaskFromRepresentationAndBits(); 715 private static final int CHANNEL_OUT_REPRESENTATION_POSITION = 0; 716 private static final int CHANNEL_OUT_REPRESENTATION_INDEX = 2; 717 718 /** 719 * Return the channel mask from its representation and bits. 720 * 721 * This creates a channel mask for mChannels which combines a 722 * representation field and a bits field. This is for internal 723 * communication to native code, not part of the public API. 724 * 725 * @param representation the type of channel mask, 726 * either CHANNEL_OUT_REPRESENTATION_POSITION 727 * or CHANNEL_OUT_REPRESENTATION_INDEX 728 * @param bits is the channel bits specifying occupancy 729 * @return the channel mask 730 * @throws java.lang.IllegalArgumentException if representation is not recognized or 731 * the bits field is not acceptable for that representation 732 */ 733 private static int getChannelMaskFromRepresentationAndBits(int representation, int bits) { 734 switch (representation) { 735 case CHANNEL_OUT_REPRESENTATION_POSITION: 736 case CHANNEL_OUT_REPRESENTATION_INDEX: 737 if ((bits & ~((1 << AUDIO_CHANNEL_BITS_LOG2) - 1)) != 0) { 738 throw new IllegalArgumentException("invalid bits " + bits); 739 } 740 return representation << AUDIO_CHANNEL_BITS_LOG2 | bits; 741 default: 742 throw new IllegalArgumentException("invalid representation " + representation); 743 } 744 } 745 746 // Convenience method for the constructor's parameter checks. 747 // This is where constructor IllegalArgumentException-s are thrown 748 // postconditions: 749 // mChannelCount is valid 750 // mChannels is valid 751 // mAudioFormat is valid 752 // mSampleRate is valid 753 // mDataLoadMode is valid 754 private void audioParamCheck(int sampleRateInHz, int channelConfig, int channelIndexMask, 755 int audioFormat, int mode) { 756 //-------------- 757 // sample rate, note these values are subject to change 758 if (sampleRateInHz < SAMPLE_RATE_HZ_MIN || sampleRateInHz > SAMPLE_RATE_HZ_MAX) { 759 throw new IllegalArgumentException(sampleRateInHz 760 + "Hz is not a supported sample rate."); 761 } 762 mSampleRate = sampleRateInHz; 763 764 //-------------- 765 // channel config 766 mChannelConfiguration = channelConfig; 767 768 switch (channelConfig) { 769 case AudioFormat.CHANNEL_OUT_DEFAULT: //AudioFormat.CHANNEL_CONFIGURATION_DEFAULT 770 case AudioFormat.CHANNEL_OUT_MONO: 771 case AudioFormat.CHANNEL_CONFIGURATION_MONO: 772 mChannelCount = 1; 773 mChannels = AudioFormat.CHANNEL_OUT_MONO; 774 break; 775 case AudioFormat.CHANNEL_OUT_STEREO: 776 case AudioFormat.CHANNEL_CONFIGURATION_STEREO: 777 mChannelCount = 2; 778 mChannels = AudioFormat.CHANNEL_OUT_STEREO; 779 break; 780 default: 781 if (channelConfig == AudioFormat.CHANNEL_INVALID && channelIndexMask != 0) { 782 mChannelCount = 0; 783 break; // channel index configuration only 784 } 785 if (!isMultichannelConfigSupported(channelConfig)) { 786 // input channel configuration features unsupported channels 787 throw new IllegalArgumentException("Unsupported channel configuration."); 788 } 789 mChannels = channelConfig; 790 mChannelCount = AudioFormat.channelCountFromOutChannelMask(channelConfig); 791 } 792 // check the channel index configuration (if present) 793 mChannelIndexMask = channelIndexMask; 794 if (mChannelIndexMask != 0) { 795 // restrictive: indexMask could allow up to AUDIO_CHANNEL_BITS_LOG2 796 final int indexMask = (1 << CHANNEL_COUNT_MAX) - 1; 797 if ((channelIndexMask & ~indexMask) != 0) { 798 throw new IllegalArgumentException("Unsupported channel index configuration " 799 + channelIndexMask); 800 } 801 int channelIndexCount = Integer.bitCount(channelIndexMask); 802 if (mChannelCount == 0) { 803 mChannelCount = channelIndexCount; 804 } else if (mChannelCount != channelIndexCount) { 805 throw new IllegalArgumentException("Channel count must match"); 806 } 807 808 // AudioTrack prefers to use the channel index configuration 809 // over the channel position configuration if both are specified. 810 mChannels = getChannelMaskFromRepresentationAndBits( 811 CHANNEL_OUT_REPRESENTATION_INDEX, mChannelIndexMask); 812 } 813 814 //-------------- 815 // audio format 816 if (audioFormat == AudioFormat.ENCODING_DEFAULT) { 817 audioFormat = AudioFormat.ENCODING_PCM_16BIT; 818 } 819 820 if (!AudioFormat.isValidEncoding(audioFormat)) { 821 throw new IllegalArgumentException("Unsupported audio encoding."); 822 } 823 mAudioFormat = audioFormat; 824 825 //-------------- 826 // audio load mode 827 if (((mode != MODE_STREAM) && (mode != MODE_STATIC)) || 828 ((mode != MODE_STREAM) && !AudioFormat.isEncodingLinearPcm(mAudioFormat))) { 829 throw new IllegalArgumentException("Invalid mode."); 830 } 831 mDataLoadMode = mode; 832 } 833 834 /** 835 * Convenience method to check that the channel configuration (a.k.a channel mask) is supported 836 * @param channelConfig the mask to validate 837 * @return false if the AudioTrack can't be used with such a mask 838 */ 839 private static boolean isMultichannelConfigSupported(int channelConfig) { 840 // check for unsupported channels 841 if ((channelConfig & SUPPORTED_OUT_CHANNELS) != channelConfig) { 842 loge("Channel configuration features unsupported channels"); 843 return false; 844 } 845 final int channelCount = AudioFormat.channelCountFromOutChannelMask(channelConfig); 846 if (channelCount > CHANNEL_COUNT_MAX) { 847 loge("Channel configuration contains too many channels " + 848 channelCount + ">" + CHANNEL_COUNT_MAX); 849 return false; 850 } 851 // check for unsupported multichannel combinations: 852 // - FL/FR must be present 853 // - L/R channels must be paired (e.g. no single L channel) 854 final int frontPair = 855 AudioFormat.CHANNEL_OUT_FRONT_LEFT | AudioFormat.CHANNEL_OUT_FRONT_RIGHT; 856 if ((channelConfig & frontPair) != frontPair) { 857 loge("Front channels must be present in multichannel configurations"); 858 return false; 859 } 860 final int backPair = 861 AudioFormat.CHANNEL_OUT_BACK_LEFT | AudioFormat.CHANNEL_OUT_BACK_RIGHT; 862 if ((channelConfig & backPair) != 0) { 863 if ((channelConfig & backPair) != backPair) { 864 loge("Rear channels can't be used independently"); 865 return false; 866 } 867 } 868 final int sidePair = 869 AudioFormat.CHANNEL_OUT_SIDE_LEFT | AudioFormat.CHANNEL_OUT_SIDE_RIGHT; 870 if ((channelConfig & sidePair) != 0 871 && (channelConfig & sidePair) != sidePair) { 872 loge("Side channels can't be used independently"); 873 return false; 874 } 875 return true; 876 } 877 878 879 // Convenience method for the constructor's audio buffer size check. 880 // preconditions: 881 // mChannelCount is valid 882 // mAudioFormat is valid 883 // postcondition: 884 // mNativeBufferSizeInBytes is valid (multiple of frame size, positive) 885 private void audioBuffSizeCheck(int audioBufferSize) { 886 // NB: this section is only valid with PCM data. 887 // To update when supporting compressed formats 888 int frameSizeInBytes; 889 if (AudioFormat.isEncodingLinearPcm(mAudioFormat)) { 890 frameSizeInBytes = mChannelCount 891 * (AudioFormat.getBytesPerSample(mAudioFormat)); 892 } else { 893 frameSizeInBytes = 1; 894 } 895 if ((audioBufferSize % frameSizeInBytes != 0) || (audioBufferSize < 1)) { 896 throw new IllegalArgumentException("Invalid audio buffer size."); 897 } 898 899 mNativeBufferSizeInBytes = audioBufferSize; 900 mNativeBufferSizeInFrames = audioBufferSize / frameSizeInBytes; 901 } 902 903 904 /** 905 * Releases the native AudioTrack resources. 906 */ 907 public void release() { 908 // even though native_release() stops the native AudioTrack, we need to stop 909 // AudioTrack subclasses too. 910 try { 911 stop(); 912 } catch(IllegalStateException ise) { 913 // don't raise an exception, we're releasing the resources. 914 } 915 native_release(); 916 mState = STATE_UNINITIALIZED; 917 } 918 919 @Override 920 protected void finalize() { 921 native_finalize(); 922 } 923 924 //-------------------------------------------------------------------------- 925 // Getters 926 //-------------------- 927 /** 928 * Returns the minimum gain value, which is the constant 0.0. 929 * Gain values less than 0.0 will be clamped to 0.0. 930 * <p>The word "volume" in the API name is historical; this is actually a linear gain. 931 * @return the minimum value, which is the constant 0.0. 932 */ 933 static public float getMinVolume() { 934 return GAIN_MIN; 935 } 936 937 /** 938 * Returns the maximum gain value, which is greater than or equal to 1.0. 939 * Gain values greater than the maximum will be clamped to the maximum. 940 * <p>The word "volume" in the API name is historical; this is actually a gain. 941 * expressed as a linear multiplier on sample values, where a maximum value of 1.0 942 * corresponds to a gain of 0 dB (sample values left unmodified). 943 * @return the maximum value, which is greater than or equal to 1.0. 944 */ 945 static public float getMaxVolume() { 946 return GAIN_MAX; 947 } 948 949 /** 950 * Returns the configured audio data sample rate in Hz 951 */ 952 public int getSampleRate() { 953 return mSampleRate; 954 } 955 956 /** 957 * Returns the current playback sample rate rate in Hz. 958 */ 959 public int getPlaybackRate() { 960 return native_get_playback_rate(); 961 } 962 963 /** 964 * Returns the current playback settings. 965 * See {@link #setPlaybackSettings(PlaybackSettings)} to set playback settings 966 * @return current {@link PlaybackSettings}. 967 * @throws IllegalStateException if track is not initialized. 968 */ 969 public @NonNull PlaybackSettings getPlaybackSettings() { 970 float[] floatArray = new float[2]; 971 int[] intArray = new int[2]; 972 native_get_playback_settings(floatArray, intArray); 973 return new PlaybackSettings() 974 .setSpeed(floatArray[0]) 975 .setPitch(floatArray[1]) 976 .setAudioFallbackMode(intArray[0]) 977 .setAudioStretchMode(intArray[1]); 978 } 979 980 /** 981 * Returns the configured audio data encoding. See {@link AudioFormat#ENCODING_PCM_8BIT}, 982 * {@link AudioFormat#ENCODING_PCM_16BIT}, and {@link AudioFormat#ENCODING_PCM_FLOAT}. 983 */ 984 public int getAudioFormat() { 985 return mAudioFormat; 986 } 987 988 /** 989 * Returns the type of audio stream this AudioTrack is configured for. 990 * Compare the result against {@link AudioManager#STREAM_VOICE_CALL}, 991 * {@link AudioManager#STREAM_SYSTEM}, {@link AudioManager#STREAM_RING}, 992 * {@link AudioManager#STREAM_MUSIC}, {@link AudioManager#STREAM_ALARM}, 993 * {@link AudioManager#STREAM_NOTIFICATION}, or {@link AudioManager#STREAM_DTMF}. 994 */ 995 public int getStreamType() { 996 return mStreamType; 997 } 998 999 /** 1000 * Returns the configured channel position mask. 1001 * <p> For example, refer to {@link AudioFormat#CHANNEL_OUT_MONO}, 1002 * {@link AudioFormat#CHANNEL_OUT_STEREO}, {@link AudioFormat#CHANNEL_OUT_5POINT1}. 1003 * This method may return {@link AudioFormat#CHANNEL_INVALID} if 1004 * a channel index mask is used. Consider 1005 * {@link #getFormat()} instead, to obtain an {@link AudioFormat}, 1006 * which contains both the channel position mask and the channel index mask. 1007 */ 1008 public int getChannelConfiguration() { 1009 return mChannelConfiguration; 1010 } 1011 1012 /** 1013 * Returns the configured <code>AudioTrack</code> format. 1014 * @return an {@link AudioFormat} containing the 1015 * <code>AudioTrack</code> parameters at the time of configuration. 1016 */ 1017 public @NonNull AudioFormat getFormat() { 1018 AudioFormat.Builder builder = new AudioFormat.Builder() 1019 .setSampleRate(mSampleRate) 1020 .setEncoding(mAudioFormat); 1021 if (mChannelConfiguration != AudioFormat.CHANNEL_INVALID) { 1022 builder.setChannelMask(mChannelConfiguration); 1023 } 1024 if (mChannelIndexMask != AudioFormat.CHANNEL_INVALID /* 0 */) { 1025 builder.setChannelIndexMask(mChannelIndexMask); 1026 } 1027 return builder.build(); 1028 } 1029 1030 /** 1031 * Returns the configured number of channels. 1032 */ 1033 public int getChannelCount() { 1034 return mChannelCount; 1035 } 1036 1037 /** 1038 * Returns the state of the AudioTrack instance. This is useful after the 1039 * AudioTrack instance has been created to check if it was initialized 1040 * properly. This ensures that the appropriate resources have been acquired. 1041 * @see #STATE_INITIALIZED 1042 * @see #STATE_NO_STATIC_DATA 1043 * @see #STATE_UNINITIALIZED 1044 */ 1045 public int getState() { 1046 return mState; 1047 } 1048 1049 /** 1050 * Returns the playback state of the AudioTrack instance. 1051 * @see #PLAYSTATE_STOPPED 1052 * @see #PLAYSTATE_PAUSED 1053 * @see #PLAYSTATE_PLAYING 1054 */ 1055 public int getPlayState() { 1056 synchronized (mPlayStateLock) { 1057 return mPlayState; 1058 } 1059 } 1060 1061 /** 1062 * Returns the "native frame count" of the <code>AudioTrack</code> buffer. 1063 * <p> If the track's creation mode is {@link #MODE_STATIC}, 1064 * it is equal to the specified bufferSizeInBytes on construction, converted to frame units. 1065 * A static track's native frame count will not change. 1066 * <p> If the track's creation mode is {@link #MODE_STREAM}, 1067 * it is greater than or equal to the specified bufferSizeInBytes converted to frame units. 1068 * For streaming tracks, this value may be rounded up to a larger value if needed by 1069 * the target output sink, and 1070 * if the track is subsequently routed to a different output sink, the native 1071 * frame count may enlarge to accommodate. 1072 * See also {@link AudioManager#getProperty(String)} for key 1073 * {@link AudioManager#PROPERTY_OUTPUT_FRAMES_PER_BUFFER}. 1074 * @return current size in frames of the audio track buffer. 1075 * @throws IllegalStateException 1076 */ 1077 public int getNativeFrameCount() throws IllegalStateException { 1078 return native_get_native_frame_count(); 1079 } 1080 1081 /** 1082 * Returns marker position expressed in frames. 1083 * @return marker position in wrapping frame units similar to {@link #getPlaybackHeadPosition}, 1084 * or zero if marker is disabled. 1085 */ 1086 public int getNotificationMarkerPosition() { 1087 return native_get_marker_pos(); 1088 } 1089 1090 /** 1091 * Returns the notification update period expressed in frames. 1092 * Zero means that no position update notifications are being delivered. 1093 */ 1094 public int getPositionNotificationPeriod() { 1095 return native_get_pos_update_period(); 1096 } 1097 1098 /** 1099 * Returns the playback head position expressed in frames. 1100 * Though the "int" type is signed 32-bits, the value should be reinterpreted as if it is 1101 * unsigned 32-bits. That is, the next position after 0x7FFFFFFF is (int) 0x80000000. 1102 * This is a continuously advancing counter. It will wrap (overflow) periodically, 1103 * for example approximately once every 27:03:11 hours:minutes:seconds at 44.1 kHz. 1104 * It is reset to zero by {@link #flush()}, {@link #reloadStaticData()}, and {@link #stop()}. 1105 * If the track's creation mode is {@link #MODE_STATIC}, the return value indicates 1106 * the total number of frames played since reset, 1107 * <i>not</i> the current offset within the buffer. 1108 */ 1109 public int getPlaybackHeadPosition() { 1110 return native_get_position(); 1111 } 1112 1113 /** 1114 * Returns this track's estimated latency in milliseconds. This includes the latency due 1115 * to AudioTrack buffer size, AudioMixer (if any) and audio hardware driver. 1116 * 1117 * DO NOT UNHIDE. The existing approach for doing A/V sync has too many problems. We need 1118 * a better solution. 1119 * @hide 1120 */ 1121 public int getLatency() { 1122 return native_get_latency(); 1123 } 1124 1125 /** 1126 * Returns the output sample rate in Hz for the specified stream type. 1127 */ 1128 static public int getNativeOutputSampleRate(int streamType) { 1129 return native_get_output_sample_rate(streamType); 1130 } 1131 1132 /** 1133 * Returns the minimum buffer size required for the successful creation of an AudioTrack 1134 * object to be created in the {@link #MODE_STREAM} mode. Note that this size doesn't 1135 * guarantee a smooth playback under load, and higher values should be chosen according to 1136 * the expected frequency at which the buffer will be refilled with additional data to play. 1137 * For example, if you intend to dynamically set the source sample rate of an AudioTrack 1138 * to a higher value than the initial source sample rate, be sure to configure the buffer size 1139 * based on the highest planned sample rate. 1140 * @param sampleRateInHz the source sample rate expressed in Hz. 1141 * @param channelConfig describes the configuration of the audio channels. 1142 * See {@link AudioFormat#CHANNEL_OUT_MONO} and 1143 * {@link AudioFormat#CHANNEL_OUT_STEREO} 1144 * @param audioFormat the format in which the audio data is represented. 1145 * See {@link AudioFormat#ENCODING_PCM_16BIT} and 1146 * {@link AudioFormat#ENCODING_PCM_8BIT}, 1147 * and {@link AudioFormat#ENCODING_PCM_FLOAT}. 1148 * @return {@link #ERROR_BAD_VALUE} if an invalid parameter was passed, 1149 * or {@link #ERROR} if unable to query for output properties, 1150 * or the minimum buffer size expressed in bytes. 1151 */ 1152 static public int getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat) { 1153 int channelCount = 0; 1154 switch(channelConfig) { 1155 case AudioFormat.CHANNEL_OUT_MONO: 1156 case AudioFormat.CHANNEL_CONFIGURATION_MONO: 1157 channelCount = 1; 1158 break; 1159 case AudioFormat.CHANNEL_OUT_STEREO: 1160 case AudioFormat.CHANNEL_CONFIGURATION_STEREO: 1161 channelCount = 2; 1162 break; 1163 default: 1164 if (!isMultichannelConfigSupported(channelConfig)) { 1165 loge("getMinBufferSize(): Invalid channel configuration."); 1166 return ERROR_BAD_VALUE; 1167 } else { 1168 channelCount = AudioFormat.channelCountFromOutChannelMask(channelConfig); 1169 } 1170 } 1171 1172 if (!AudioFormat.isValidEncoding(audioFormat)) { 1173 loge("getMinBufferSize(): Invalid audio format."); 1174 return ERROR_BAD_VALUE; 1175 } 1176 1177 // sample rate, note these values are subject to change 1178 if ( (sampleRateInHz < SAMPLE_RATE_HZ_MIN) || (sampleRateInHz > SAMPLE_RATE_HZ_MAX) ) { 1179 loge("getMinBufferSize(): " + sampleRateInHz + " Hz is not a supported sample rate."); 1180 return ERROR_BAD_VALUE; 1181 } 1182 1183 int size = native_get_min_buff_size(sampleRateInHz, channelCount, audioFormat); 1184 if (size <= 0) { 1185 loge("getMinBufferSize(): error querying hardware"); 1186 return ERROR; 1187 } 1188 else { 1189 return size; 1190 } 1191 } 1192 1193 /** 1194 * Returns the audio session ID. 1195 * 1196 * @return the ID of the audio session this AudioTrack belongs to. 1197 */ 1198 public int getAudioSessionId() { 1199 return mSessionId; 1200 } 1201 1202 /** 1203 * Poll for a timestamp on demand. 1204 * <p> 1205 * If you need to track timestamps during initial warmup or after a routing or mode change, 1206 * you should request a new timestamp once per second until the reported timestamps 1207 * show that the audio clock is stable. 1208 * Thereafter, query for a new timestamp approximately once every 10 seconds to once per minute. 1209 * Calling this method more often is inefficient. 1210 * It is also counter-productive to call this method more often than recommended, 1211 * because the short-term differences between successive timestamp reports are not meaningful. 1212 * If you need a high-resolution mapping between frame position and presentation time, 1213 * consider implementing that at application level, based on low-resolution timestamps. 1214 * <p> 1215 * The audio data at the returned position may either already have been 1216 * presented, or may have not yet been presented but is committed to be presented. 1217 * It is not possible to request the time corresponding to a particular position, 1218 * or to request the (fractional) position corresponding to a particular time. 1219 * If you need such features, consider implementing them at application level. 1220 * 1221 * @param timestamp a reference to a non-null AudioTimestamp instance allocated 1222 * and owned by caller. 1223 * @return true if a timestamp is available, or false if no timestamp is available. 1224 * If a timestamp if available, 1225 * the AudioTimestamp instance is filled in with a position in frame units, together 1226 * with the estimated time when that frame was presented or is committed to 1227 * be presented. 1228 * In the case that no timestamp is available, any supplied instance is left unaltered. 1229 * A timestamp may be temporarily unavailable while the audio clock is stabilizing, 1230 * or during and immediately after a route change. 1231 */ 1232 // Add this text when the "on new timestamp" API is added: 1233 // Use if you need to get the most recent timestamp outside of the event callback handler. 1234 public boolean getTimestamp(AudioTimestamp timestamp) 1235 { 1236 if (timestamp == null) { 1237 throw new IllegalArgumentException(); 1238 } 1239 // It's unfortunate, but we have to either create garbage every time or use synchronized 1240 long[] longArray = new long[2]; 1241 int ret = native_get_timestamp(longArray); 1242 if (ret != SUCCESS) { 1243 return false; 1244 } 1245 timestamp.framePosition = longArray[0]; 1246 timestamp.nanoTime = longArray[1]; 1247 return true; 1248 } 1249 1250 1251 //-------------------------------------------------------------------------- 1252 // Initialization / configuration 1253 //-------------------- 1254 /** 1255 * Sets the listener the AudioTrack notifies when a previously set marker is reached or 1256 * for each periodic playback head position update. 1257 * Notifications will be received in the same thread as the one in which the AudioTrack 1258 * instance was created. 1259 * @param listener 1260 */ 1261 public void setPlaybackPositionUpdateListener(OnPlaybackPositionUpdateListener listener) { 1262 setPlaybackPositionUpdateListener(listener, null); 1263 } 1264 1265 /** 1266 * Sets the listener the AudioTrack notifies when a previously set marker is reached or 1267 * for each periodic playback head position update. 1268 * Use this method to receive AudioTrack events in the Handler associated with another 1269 * thread than the one in which you created the AudioTrack instance. 1270 * @param listener 1271 * @param handler the Handler that will receive the event notification messages. 1272 */ 1273 public void setPlaybackPositionUpdateListener(OnPlaybackPositionUpdateListener listener, 1274 Handler handler) { 1275 if (listener != null) { 1276 mEventHandlerDelegate = new NativePositionEventHandlerDelegate(this, listener, handler); 1277 } else { 1278 mEventHandlerDelegate = null; 1279 } 1280 } 1281 1282 1283 private static float clampGainOrLevel(float gainOrLevel) { 1284 if (Float.isNaN(gainOrLevel)) { 1285 throw new IllegalArgumentException(); 1286 } 1287 if (gainOrLevel < GAIN_MIN) { 1288 gainOrLevel = GAIN_MIN; 1289 } else if (gainOrLevel > GAIN_MAX) { 1290 gainOrLevel = GAIN_MAX; 1291 } 1292 return gainOrLevel; 1293 } 1294 1295 1296 /** 1297 * Sets the specified left and right output gain values on the AudioTrack. 1298 * <p>Gain values are clamped to the closed interval [0.0, max] where 1299 * max is the value of {@link #getMaxVolume}. 1300 * A value of 0.0 results in zero gain (silence), and 1301 * a value of 1.0 means unity gain (signal unchanged). 1302 * The default value is 1.0 meaning unity gain. 1303 * <p>The word "volume" in the API name is historical; this is actually a linear gain. 1304 * @param leftGain output gain for the left channel. 1305 * @param rightGain output gain for the right channel 1306 * @return error code or success, see {@link #SUCCESS}, 1307 * {@link #ERROR_INVALID_OPERATION} 1308 * @deprecated Applications should use {@link #setVolume} instead, as it 1309 * more gracefully scales down to mono, and up to multi-channel content beyond stereo. 1310 */ 1311 public int setStereoVolume(float leftGain, float rightGain) { 1312 if (isRestricted()) { 1313 return SUCCESS; 1314 } 1315 if (mState == STATE_UNINITIALIZED) { 1316 return ERROR_INVALID_OPERATION; 1317 } 1318 1319 leftGain = clampGainOrLevel(leftGain); 1320 rightGain = clampGainOrLevel(rightGain); 1321 1322 native_setVolume(leftGain, rightGain); 1323 1324 return SUCCESS; 1325 } 1326 1327 1328 /** 1329 * Sets the specified output gain value on all channels of this track. 1330 * <p>Gain values are clamped to the closed interval [0.0, max] where 1331 * max is the value of {@link #getMaxVolume}. 1332 * A value of 0.0 results in zero gain (silence), and 1333 * a value of 1.0 means unity gain (signal unchanged). 1334 * The default value is 1.0 meaning unity gain. 1335 * <p>This API is preferred over {@link #setStereoVolume}, as it 1336 * more gracefully scales down to mono, and up to multi-channel content beyond stereo. 1337 * <p>The word "volume" in the API name is historical; this is actually a linear gain. 1338 * @param gain output gain for all channels. 1339 * @return error code or success, see {@link #SUCCESS}, 1340 * {@link #ERROR_INVALID_OPERATION} 1341 */ 1342 public int setVolume(float gain) { 1343 return setStereoVolume(gain, gain); 1344 } 1345 1346 1347 /** 1348 * Sets the playback sample rate for this track. This sets the sampling rate at which 1349 * the audio data will be consumed and played back 1350 * (as set by the sampleRateInHz parameter in the 1351 * {@link #AudioTrack(int, int, int, int, int, int)} constructor), 1352 * not the original sampling rate of the 1353 * content. For example, setting it to half the sample rate of the content will cause the 1354 * playback to last twice as long, but will also result in a pitch shift down by one octave. 1355 * The valid sample rate range is from 1 Hz to twice the value returned by 1356 * {@link #getNativeOutputSampleRate(int)}. 1357 * Use {@link #setPlaybackSettings(PlaybackSettings)} for speed control. 1358 * @param sampleRateInHz the sample rate expressed in Hz 1359 * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE}, 1360 * {@link #ERROR_INVALID_OPERATION} 1361 */ 1362 public int setPlaybackRate(int sampleRateInHz) { 1363 if (mState != STATE_INITIALIZED) { 1364 return ERROR_INVALID_OPERATION; 1365 } 1366 if (sampleRateInHz <= 0) { 1367 return ERROR_BAD_VALUE; 1368 } 1369 return native_set_playback_rate(sampleRateInHz); 1370 } 1371 1372 1373 /** 1374 * Sets the playback settings. 1375 * This method returns failure if it cannot apply the playback settings. 1376 * One possible cause is that the parameters for speed or pitch are out of range. 1377 * Another possible cause is that the <code>AudioTrack</code> is streaming 1378 * (see {@link #MODE_STREAM}) and the 1379 * buffer size is too small. For speeds greater than 1.0f, the <code>AudioTrack</code> buffer 1380 * on configuration must be larger than the speed multiplied by the minimum size 1381 * {@link #getMinBufferSize(int, int, int)}) to allow proper playback. 1382 * @param settings see {@link PlaybackSettings}. In particular, 1383 * speed, pitch, and audio mode should be set. 1384 * @throws IllegalArgumentException if the settings are invalid or not accepted. 1385 * @throws IllegalStateException if track is not initialized. 1386 */ 1387 public void setPlaybackSettings(@NonNull PlaybackSettings settings) { 1388 if (settings == null) { 1389 throw new IllegalArgumentException("settings is null"); 1390 } 1391 float[] floatArray; 1392 int[] intArray; 1393 try { 1394 floatArray = new float[] { 1395 settings.getSpeed(), 1396 settings.getPitch(), 1397 }; 1398 intArray = new int[] { 1399 settings.getAudioFallbackMode(), 1400 settings.getAudioStretchMode(), 1401 }; 1402 } catch (IllegalStateException e) { 1403 throw new IllegalArgumentException(e); 1404 } 1405 native_set_playback_settings(floatArray, intArray); 1406 } 1407 1408 1409 /** 1410 * Sets the position of the notification marker. At most one marker can be active. 1411 * @param markerInFrames marker position in wrapping frame units similar to 1412 * {@link #getPlaybackHeadPosition}, or zero to disable the marker. 1413 * To set a marker at a position which would appear as zero due to wraparound, 1414 * a workaround is to use a non-zero position near zero, such as -1 or 1. 1415 * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE}, 1416 * {@link #ERROR_INVALID_OPERATION} 1417 */ 1418 public int setNotificationMarkerPosition(int markerInFrames) { 1419 if (mState == STATE_UNINITIALIZED) { 1420 return ERROR_INVALID_OPERATION; 1421 } 1422 return native_set_marker_pos(markerInFrames); 1423 } 1424 1425 1426 /** 1427 * Sets the period for the periodic notification event. 1428 * @param periodInFrames update period expressed in frames. 1429 * Zero period means no position updates. A negative period is not allowed. 1430 * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_INVALID_OPERATION} 1431 */ 1432 public int setPositionNotificationPeriod(int periodInFrames) { 1433 if (mState == STATE_UNINITIALIZED) { 1434 return ERROR_INVALID_OPERATION; 1435 } 1436 return native_set_pos_update_period(periodInFrames); 1437 } 1438 1439 1440 /** 1441 * Sets the playback head position within the static buffer. 1442 * The track must be stopped or paused for the position to be changed, 1443 * and must use the {@link #MODE_STATIC} mode. 1444 * @param positionInFrames playback head position within buffer, expressed in frames. 1445 * Zero corresponds to start of buffer. 1446 * The position must not be greater than the buffer size in frames, or negative. 1447 * Though this method and {@link #getPlaybackHeadPosition()} have similar names, 1448 * the position values have different meanings. 1449 * <br> 1450 * If looping is currently enabled and the new position is greater than or equal to the 1451 * loop end marker, the behavior varies by API level: 1452 * as of {@link android.os.Build.VERSION_CODES#MNC}, 1453 * the looping is first disabled and then the position is set. 1454 * For earlier API levels, the behavior is unspecified. 1455 * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE}, 1456 * {@link #ERROR_INVALID_OPERATION} 1457 */ 1458 public int setPlaybackHeadPosition(int positionInFrames) { 1459 if (mDataLoadMode == MODE_STREAM || mState == STATE_UNINITIALIZED || 1460 getPlayState() == PLAYSTATE_PLAYING) { 1461 return ERROR_INVALID_OPERATION; 1462 } 1463 if (!(0 <= positionInFrames && positionInFrames <= mNativeBufferSizeInFrames)) { 1464 return ERROR_BAD_VALUE; 1465 } 1466 return native_set_position(positionInFrames); 1467 } 1468 1469 /** 1470 * Sets the loop points and the loop count. The loop can be infinite. 1471 * Similarly to setPlaybackHeadPosition, 1472 * the track must be stopped or paused for the loop points to be changed, 1473 * and must use the {@link #MODE_STATIC} mode. 1474 * @param startInFrames loop start marker expressed in frames. 1475 * Zero corresponds to start of buffer. 1476 * The start marker must not be greater than or equal to the buffer size in frames, or negative. 1477 * @param endInFrames loop end marker expressed in frames. 1478 * The total buffer size in frames corresponds to end of buffer. 1479 * The end marker must not be greater than the buffer size in frames. 1480 * For looping, the end marker must not be less than or equal to the start marker, 1481 * but to disable looping 1482 * it is permitted for start marker, end marker, and loop count to all be 0. 1483 * If any input parameters are out of range, this method returns {@link #ERROR_BAD_VALUE}. 1484 * If the loop period (endInFrames - startInFrames) is too small for the implementation to 1485 * support, 1486 * {@link #ERROR_BAD_VALUE} is returned. 1487 * The loop range is the interval [startInFrames, endInFrames). 1488 * <br> 1489 * As of {@link android.os.Build.VERSION_CODES#MNC}, the position is left unchanged, 1490 * unless it is greater than or equal to the loop end marker, in which case 1491 * it is forced to the loop start marker. 1492 * For earlier API levels, the effect on position is unspecified. 1493 * @param loopCount the number of times the loop is looped; must be greater than or equal to -1. 1494 * A value of -1 means infinite looping, and 0 disables looping. 1495 * A value of positive N means to "loop" (go back) N times. For example, 1496 * a value of one means to play the region two times in total. 1497 * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE}, 1498 * {@link #ERROR_INVALID_OPERATION} 1499 */ 1500 public int setLoopPoints(int startInFrames, int endInFrames, int loopCount) { 1501 if (mDataLoadMode == MODE_STREAM || mState == STATE_UNINITIALIZED || 1502 getPlayState() == PLAYSTATE_PLAYING) { 1503 return ERROR_INVALID_OPERATION; 1504 } 1505 if (loopCount == 0) { 1506 ; // explicitly allowed as an exception to the loop region range check 1507 } else if (!(0 <= startInFrames && startInFrames < mNativeBufferSizeInFrames && 1508 startInFrames < endInFrames && endInFrames <= mNativeBufferSizeInFrames)) { 1509 return ERROR_BAD_VALUE; 1510 } 1511 return native_set_loop(startInFrames, endInFrames, loopCount); 1512 } 1513 1514 /** 1515 * Sets the initialization state of the instance. This method was originally intended to be used 1516 * in an AudioTrack subclass constructor to set a subclass-specific post-initialization state. 1517 * However, subclasses of AudioTrack are no longer recommended, so this method is obsolete. 1518 * @param state the state of the AudioTrack instance 1519 * @deprecated Only accessible by subclasses, which are not recommended for AudioTrack. 1520 */ 1521 @Deprecated 1522 protected void setState(int state) { 1523 mState = state; 1524 } 1525 1526 1527 //--------------------------------------------------------- 1528 // Transport control methods 1529 //-------------------- 1530 /** 1531 * Starts playing an AudioTrack. 1532 * If track's creation mode is {@link #MODE_STATIC}, you must have called one of 1533 * the {@link #write(byte[], int, int)}, {@link #write(short[], int, int)}, 1534 * or {@link #write(float[], int, int, int)} methods. 1535 * If the mode is {@link #MODE_STREAM}, you can optionally prime the 1536 * output buffer by writing up to bufferSizeInBytes (from constructor) before starting. 1537 * This priming will avoid an immediate underrun, but is not required. 1538 * 1539 * @throws IllegalStateException 1540 */ 1541 public void play() 1542 throws IllegalStateException { 1543 if (mState != STATE_INITIALIZED) { 1544 throw new IllegalStateException("play() called on uninitialized AudioTrack."); 1545 } 1546 if (isRestricted()) { 1547 setVolume(0); 1548 } 1549 synchronized(mPlayStateLock) { 1550 native_start(); 1551 mPlayState = PLAYSTATE_PLAYING; 1552 } 1553 } 1554 1555 private boolean isRestricted() { 1556 if ((mAttributes.getFlags() & AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY) != 0) { 1557 return false; 1558 } 1559 try { 1560 final int usage = AudioAttributes.usageForLegacyStreamType(mStreamType); 1561 final int mode = mAppOps.checkAudioOperation(AppOpsManager.OP_PLAY_AUDIO, usage, 1562 Process.myUid(), ActivityThread.currentPackageName()); 1563 return mode != AppOpsManager.MODE_ALLOWED; 1564 } catch (RemoteException e) { 1565 return false; 1566 } 1567 } 1568 1569 /** 1570 * Stops playing the audio data. 1571 * When used on an instance created in {@link #MODE_STREAM} mode, audio will stop playing 1572 * after the last buffer that was written has been played. For an immediate stop, use 1573 * {@link #pause()}, followed by {@link #flush()} to discard audio data that hasn't been played 1574 * back yet. 1575 * @throws IllegalStateException 1576 */ 1577 public void stop() 1578 throws IllegalStateException { 1579 if (mState != STATE_INITIALIZED) { 1580 throw new IllegalStateException("stop() called on uninitialized AudioTrack."); 1581 } 1582 1583 // stop playing 1584 synchronized(mPlayStateLock) { 1585 native_stop(); 1586 mPlayState = PLAYSTATE_STOPPED; 1587 mAvSyncHeader = null; 1588 mAvSyncBytesRemaining = 0; 1589 } 1590 } 1591 1592 /** 1593 * Pauses the playback of the audio data. Data that has not been played 1594 * back will not be discarded. Subsequent calls to {@link #play} will play 1595 * this data back. See {@link #flush()} to discard this data. 1596 * 1597 * @throws IllegalStateException 1598 */ 1599 public void pause() 1600 throws IllegalStateException { 1601 if (mState != STATE_INITIALIZED) { 1602 throw new IllegalStateException("pause() called on uninitialized AudioTrack."); 1603 } 1604 //logd("pause()"); 1605 1606 // pause playback 1607 synchronized(mPlayStateLock) { 1608 native_pause(); 1609 mPlayState = PLAYSTATE_PAUSED; 1610 } 1611 } 1612 1613 1614 //--------------------------------------------------------- 1615 // Audio data supply 1616 //-------------------- 1617 1618 /** 1619 * Flushes the audio data currently queued for playback. Any data that has 1620 * been written but not yet presented will be discarded. No-op if not stopped or paused, 1621 * or if the track's creation mode is not {@link #MODE_STREAM}. 1622 * <BR> Note that although data written but not yet presented is discarded, there is no 1623 * guarantee that all of the buffer space formerly used by that data 1624 * is available for a subsequent write. 1625 * For example, a call to {@link #write(byte[], int, int)} with <code>sizeInBytes</code> 1626 * less than or equal to the total buffer size 1627 * may return a short actual transfer count. 1628 */ 1629 public void flush() { 1630 if (mState == STATE_INITIALIZED) { 1631 // flush the data in native layer 1632 native_flush(); 1633 mAvSyncHeader = null; 1634 mAvSyncBytesRemaining = 0; 1635 } 1636 1637 } 1638 1639 /** 1640 * Writes the audio data to the audio sink for playback (streaming mode), 1641 * or copies audio data for later playback (static buffer mode). 1642 * The format specified in the AudioTrack constructor should be 1643 * {@link AudioFormat#ENCODING_PCM_8BIT} to correspond to the data in the array. 1644 * In streaming mode, will block until all data has been written to the audio sink. 1645 * In static buffer mode, copies the data to the buffer starting at offset 0. 1646 * Note that the actual playback of this data might occur after this function 1647 * returns. This function is thread safe with respect to {@link #stop} calls, 1648 * in which case all of the specified data might not be written to the audio sink. 1649 * 1650 * @param audioData the array that holds the data to play. 1651 * @param offsetInBytes the offset expressed in bytes in audioData where the data to play 1652 * starts. 1653 * @param sizeInBytes the number of bytes to read in audioData after the offset. 1654 * @return the number of bytes that were written or {@link #ERROR_INVALID_OPERATION} 1655 * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if 1656 * the parameters don't resolve to valid data and indexes, or 1657 * {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and 1658 * needs to be recreated. 1659 */ 1660 public int write(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes) { 1661 return write(audioData, offsetInBytes, sizeInBytes, WRITE_BLOCKING); 1662 } 1663 1664 /** 1665 * Writes the audio data to the audio sink for playback (streaming mode), 1666 * or copies audio data for later playback (static buffer mode). 1667 * The format specified in the AudioTrack constructor should be 1668 * {@link AudioFormat#ENCODING_PCM_8BIT} to correspond to the data in the array. 1669 * In streaming mode, will block until all data has been written to the audio sink. 1670 * In static buffer mode, copies the data to the buffer starting at offset 0. 1671 * Note that the actual playback of this data might occur after this function 1672 * returns. This function is thread safe with respect to {@link #stop} calls, 1673 * in which case all of the specified data might not be written to the audio sink. 1674 * 1675 * @param audioData the array that holds the data to play. 1676 * @param offsetInBytes the offset expressed in bytes in audioData where the data to play 1677 * starts. 1678 * @param sizeInBytes the number of bytes to read in audioData after the offset. 1679 * @param writeMode one of {@link #WRITE_BLOCKING}, {@link #WRITE_NON_BLOCKING}. It has no 1680 * effect in static mode. 1681 * <br>With {@link #WRITE_BLOCKING}, the write will block until all data has been written 1682 * to the audio sink. 1683 * <br>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after 1684 * queuing as much audio data for playback as possible without blocking. 1685 * @return the number of bytes that were written or {@link #ERROR_INVALID_OPERATION} 1686 * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if 1687 * the parameters don't resolve to valid data and indexes, or 1688 * {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and 1689 * needs to be recreated. 1690 */ 1691 public int write(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes, 1692 @WriteMode int writeMode) { 1693 1694 if (mState == STATE_UNINITIALIZED || mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT) { 1695 return ERROR_INVALID_OPERATION; 1696 } 1697 1698 if ((writeMode != WRITE_BLOCKING) && (writeMode != WRITE_NON_BLOCKING)) { 1699 Log.e(TAG, "AudioTrack.write() called with invalid blocking mode"); 1700 return ERROR_BAD_VALUE; 1701 } 1702 1703 if ( (audioData == null) || (offsetInBytes < 0 ) || (sizeInBytes < 0) 1704 || (offsetInBytes + sizeInBytes < 0) // detect integer overflow 1705 || (offsetInBytes + sizeInBytes > audioData.length)) { 1706 return ERROR_BAD_VALUE; 1707 } 1708 1709 int ret = native_write_byte(audioData, offsetInBytes, sizeInBytes, mAudioFormat, 1710 writeMode == WRITE_BLOCKING); 1711 1712 if ((mDataLoadMode == MODE_STATIC) 1713 && (mState == STATE_NO_STATIC_DATA) 1714 && (ret > 0)) { 1715 // benign race with respect to other APIs that read mState 1716 mState = STATE_INITIALIZED; 1717 } 1718 1719 return ret; 1720 } 1721 1722 /** 1723 * Writes the audio data to the audio sink for playback (streaming mode), 1724 * or copies audio data for later playback (static buffer mode). 1725 * The format specified in the AudioTrack constructor should be 1726 * {@link AudioFormat#ENCODING_PCM_16BIT} to correspond to the data in the array. 1727 * In streaming mode, will block until all data has been written to the audio sink. 1728 * In static buffer mode, copies the data to the buffer starting at offset 0. 1729 * Note that the actual playback of this data might occur after this function 1730 * returns. This function is thread safe with respect to {@link #stop} calls, 1731 * in which case all of the specified data might not be written to the audio sink. 1732 * 1733 * @param audioData the array that holds the data to play. 1734 * @param offsetInShorts the offset expressed in shorts in audioData where the data to play 1735 * starts. 1736 * @param sizeInShorts the number of shorts to read in audioData after the offset. 1737 * @return the number of shorts that were written or {@link #ERROR_INVALID_OPERATION} 1738 * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if 1739 * the parameters don't resolve to valid data and indexes, or 1740 * {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and 1741 * needs to be recreated. 1742 */ 1743 public int write(@NonNull short[] audioData, int offsetInShorts, int sizeInShorts) { 1744 return write(audioData, offsetInShorts, sizeInShorts, WRITE_BLOCKING); 1745 } 1746 1747 /** 1748 * Writes the audio data to the audio sink for playback (streaming mode), 1749 * or copies audio data for later playback (static buffer mode). 1750 * The format specified in the AudioTrack constructor should be 1751 * {@link AudioFormat#ENCODING_PCM_16BIT} to correspond to the data in the array. 1752 * In streaming mode, will block until all data has been written to the audio sink. 1753 * In static buffer mode, copies the data to the buffer starting at offset 0. 1754 * Note that the actual playback of this data might occur after this function 1755 * returns. This function is thread safe with respect to {@link #stop} calls, 1756 * in which case all of the specified data might not be written to the audio sink. 1757 * 1758 * @param audioData the array that holds the data to play. 1759 * @param offsetInShorts the offset expressed in shorts in audioData where the data to play 1760 * starts. 1761 * @param sizeInShorts the number of shorts to read in audioData after the offset. 1762 * @param writeMode one of {@link #WRITE_BLOCKING}, {@link #WRITE_NON_BLOCKING}. It has no 1763 * effect in static mode. 1764 * <br>With {@link #WRITE_BLOCKING}, the write will block until all data has been written 1765 * to the audio sink. 1766 * <br>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after 1767 * queuing as much audio data for playback as possible without blocking. 1768 * @return the number of shorts that were written or {@link #ERROR_INVALID_OPERATION} 1769 * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if 1770 * the parameters don't resolve to valid data and indexes, or 1771 * {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and 1772 * needs to be recreated. 1773 */ 1774 public int write(@NonNull short[] audioData, int offsetInShorts, int sizeInShorts, 1775 @WriteMode int writeMode) { 1776 1777 if (mState == STATE_UNINITIALIZED || mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT) { 1778 return ERROR_INVALID_OPERATION; 1779 } 1780 1781 if ((writeMode != WRITE_BLOCKING) && (writeMode != WRITE_NON_BLOCKING)) { 1782 Log.e(TAG, "AudioTrack.write() called with invalid blocking mode"); 1783 return ERROR_BAD_VALUE; 1784 } 1785 1786 if ( (audioData == null) || (offsetInShorts < 0 ) || (sizeInShorts < 0) 1787 || (offsetInShorts + sizeInShorts < 0) // detect integer overflow 1788 || (offsetInShorts + sizeInShorts > audioData.length)) { 1789 return ERROR_BAD_VALUE; 1790 } 1791 1792 int ret = native_write_short(audioData, offsetInShorts, sizeInShorts, mAudioFormat, 1793 writeMode == WRITE_BLOCKING); 1794 1795 if ((mDataLoadMode == MODE_STATIC) 1796 && (mState == STATE_NO_STATIC_DATA) 1797 && (ret > 0)) { 1798 // benign race with respect to other APIs that read mState 1799 mState = STATE_INITIALIZED; 1800 } 1801 1802 return ret; 1803 } 1804 1805 /** 1806 * Writes the audio data to the audio sink for playback (streaming mode), 1807 * or copies audio data for later playback (static buffer mode). 1808 * The format specified in the AudioTrack constructor should be 1809 * {@link AudioFormat#ENCODING_PCM_FLOAT} to correspond to the data in the array. 1810 * In static buffer mode, copies the data to the buffer starting at offset 0, 1811 * and the write mode is ignored. 1812 * In streaming mode, the blocking behavior will depend on the write mode. 1813 * <p> 1814 * Note that the actual playback of this data might occur after this function 1815 * returns. This function is thread safe with respect to {@link #stop} calls, 1816 * in which case all of the specified data might not be written to the audio sink. 1817 * <p> 1818 * @param audioData the array that holds the data to play. 1819 * The implementation does not clip for sample values within the nominal range 1820 * [-1.0f, 1.0f], provided that all gains in the audio pipeline are 1821 * less than or equal to unity (1.0f), and in the absence of post-processing effects 1822 * that could add energy, such as reverb. For the convenience of applications 1823 * that compute samples using filters with non-unity gain, 1824 * sample values +3 dB beyond the nominal range are permitted. 1825 * However such values may eventually be limited or clipped, depending on various gains 1826 * and later processing in the audio path. Therefore applications are encouraged 1827 * to provide samples values within the nominal range. 1828 * @param offsetInFloats the offset, expressed as a number of floats, 1829 * in audioData where the data to play starts. 1830 * @param sizeInFloats the number of floats to read in audioData after the offset. 1831 * @param writeMode one of {@link #WRITE_BLOCKING}, {@link #WRITE_NON_BLOCKING}. It has no 1832 * effect in static mode. 1833 * <br>With {@link #WRITE_BLOCKING}, the write will block until all data has been written 1834 * to the audio sink. 1835 * <br>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after 1836 * queuing as much audio data for playback as possible without blocking. 1837 * @return the number of floats that were written, or {@link #ERROR_INVALID_OPERATION} 1838 * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if 1839 * the parameters don't resolve to valid data and indexes, or 1840 * {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and 1841 * needs to be recreated. 1842 */ 1843 public int write(@NonNull float[] audioData, int offsetInFloats, int sizeInFloats, 1844 @WriteMode int writeMode) { 1845 1846 if (mState == STATE_UNINITIALIZED) { 1847 Log.e(TAG, "AudioTrack.write() called in invalid state STATE_UNINITIALIZED"); 1848 return ERROR_INVALID_OPERATION; 1849 } 1850 1851 if (mAudioFormat != AudioFormat.ENCODING_PCM_FLOAT) { 1852 Log.e(TAG, "AudioTrack.write(float[] ...) requires format ENCODING_PCM_FLOAT"); 1853 return ERROR_INVALID_OPERATION; 1854 } 1855 1856 if ((writeMode != WRITE_BLOCKING) && (writeMode != WRITE_NON_BLOCKING)) { 1857 Log.e(TAG, "AudioTrack.write() called with invalid blocking mode"); 1858 return ERROR_BAD_VALUE; 1859 } 1860 1861 if ( (audioData == null) || (offsetInFloats < 0 ) || (sizeInFloats < 0) 1862 || (offsetInFloats + sizeInFloats < 0) // detect integer overflow 1863 || (offsetInFloats + sizeInFloats > audioData.length)) { 1864 Log.e(TAG, "AudioTrack.write() called with invalid array, offset, or size"); 1865 return ERROR_BAD_VALUE; 1866 } 1867 1868 int ret = native_write_float(audioData, offsetInFloats, sizeInFloats, mAudioFormat, 1869 writeMode == WRITE_BLOCKING); 1870 1871 if ((mDataLoadMode == MODE_STATIC) 1872 && (mState == STATE_NO_STATIC_DATA) 1873 && (ret > 0)) { 1874 // benign race with respect to other APIs that read mState 1875 mState = STATE_INITIALIZED; 1876 } 1877 1878 return ret; 1879 } 1880 1881 1882 /** 1883 * Writes the audio data to the audio sink for playback (streaming mode), 1884 * or copies audio data for later playback (static buffer mode). 1885 * In static buffer mode, copies the data to the buffer starting at its 0 offset, and the write 1886 * mode is ignored. 1887 * In streaming mode, the blocking behavior will depend on the write mode. 1888 * @param audioData the buffer that holds the data to play, starting at the position reported 1889 * by <code>audioData.position()</code>. 1890 * <BR>Note that upon return, the buffer position (<code>audioData.position()</code>) will 1891 * have been advanced to reflect the amount of data that was successfully written to 1892 * the AudioTrack. 1893 * @param sizeInBytes number of bytes to write. 1894 * <BR>Note this may differ from <code>audioData.remaining()</code>, but cannot exceed it. 1895 * @param writeMode one of {@link #WRITE_BLOCKING}, {@link #WRITE_NON_BLOCKING}. It has no 1896 * effect in static mode. 1897 * <BR>With {@link #WRITE_BLOCKING}, the write will block until all data has been written 1898 * to the audio sink. 1899 * <BR>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after 1900 * queuing as much audio data for playback as possible without blocking. 1901 * @return 0 or a positive number of bytes that were written, or 1902 * {@link #ERROR_BAD_VALUE}, {@link #ERROR_INVALID_OPERATION}, or 1903 * {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and 1904 * needs to be recreated. 1905 */ 1906 public int write(@NonNull ByteBuffer audioData, int sizeInBytes, 1907 @WriteMode int writeMode) { 1908 1909 if (mState == STATE_UNINITIALIZED) { 1910 Log.e(TAG, "AudioTrack.write() called in invalid state STATE_UNINITIALIZED"); 1911 return ERROR_INVALID_OPERATION; 1912 } 1913 1914 if ((writeMode != WRITE_BLOCKING) && (writeMode != WRITE_NON_BLOCKING)) { 1915 Log.e(TAG, "AudioTrack.write() called with invalid blocking mode"); 1916 return ERROR_BAD_VALUE; 1917 } 1918 1919 if ( (audioData == null) || (sizeInBytes < 0) || (sizeInBytes > audioData.remaining())) { 1920 Log.e(TAG, "AudioTrack.write() called with invalid size (" + sizeInBytes + ") value"); 1921 return ERROR_BAD_VALUE; 1922 } 1923 1924 int ret = 0; 1925 if (audioData.isDirect()) { 1926 ret = native_write_native_bytes(audioData, 1927 audioData.position(), sizeInBytes, mAudioFormat, 1928 writeMode == WRITE_BLOCKING); 1929 } else { 1930 ret = native_write_byte(NioUtils.unsafeArray(audioData), 1931 NioUtils.unsafeArrayOffset(audioData) + audioData.position(), 1932 sizeInBytes, mAudioFormat, 1933 writeMode == WRITE_BLOCKING); 1934 } 1935 1936 if ((mDataLoadMode == MODE_STATIC) 1937 && (mState == STATE_NO_STATIC_DATA) 1938 && (ret > 0)) { 1939 // benign race with respect to other APIs that read mState 1940 mState = STATE_INITIALIZED; 1941 } 1942 1943 if (ret > 0) { 1944 audioData.position(audioData.position() + ret); 1945 } 1946 1947 return ret; 1948 } 1949 1950 /** 1951 * Writes the audio data to the audio sink for playback (streaming mode) on a HW_AV_SYNC track. 1952 * In streaming mode, the blocking behavior will depend on the write mode. 1953 * @param audioData the buffer that holds the data to play, starting at the position reported 1954 * by <code>audioData.position()</code>. 1955 * <BR>Note that upon return, the buffer position (<code>audioData.position()</code>) will 1956 * have been advanced to reflect the amount of data that was successfully written to 1957 * the AudioTrack. 1958 * @param sizeInBytes number of bytes to write. 1959 * <BR>Note this may differ from <code>audioData.remaining()</code>, but cannot exceed it. 1960 * @param writeMode one of {@link #WRITE_BLOCKING}, {@link #WRITE_NON_BLOCKING}. 1961 * <BR>With {@link #WRITE_BLOCKING}, the write will block until all data has been written 1962 * to the audio sink. 1963 * <BR>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after 1964 * queuing as much audio data for playback as possible without blocking. 1965 * @param timestamp The timestamp of the first decodable audio frame in the provided audioData. 1966 * @return 0 or a positive number of bytes that were written, or 1967 * {@link #ERROR_BAD_VALUE}, {@link #ERROR_INVALID_OPERATION}, or 1968 * {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and 1969 * needs to be recreated. 1970 */ 1971 public int write(ByteBuffer audioData, int sizeInBytes, 1972 @WriteMode int writeMode, long timestamp) { 1973 1974 if ((mAttributes.getFlags() & AudioAttributes.FLAG_HW_AV_SYNC) == 0) { 1975 Log.d(TAG, "AudioTrack.write() called on a regular AudioTrack. Ignoring pts..."); 1976 return write(audioData, sizeInBytes, writeMode); 1977 } 1978 1979 if ((audioData == null) || (sizeInBytes < 0) || (sizeInBytes > audioData.remaining())) { 1980 Log.e(TAG, "AudioTrack.write() called with invalid size (" + sizeInBytes + ") value"); 1981 return ERROR_BAD_VALUE; 1982 } 1983 1984 // create timestamp header if none exists 1985 if (mAvSyncHeader == null) { 1986 mAvSyncHeader = ByteBuffer.allocate(16); 1987 mAvSyncHeader.order(ByteOrder.BIG_ENDIAN); 1988 mAvSyncHeader.putInt(0x55550001); 1989 mAvSyncHeader.putInt(sizeInBytes); 1990 mAvSyncHeader.putLong(timestamp); 1991 mAvSyncHeader.position(0); 1992 mAvSyncBytesRemaining = sizeInBytes; 1993 } 1994 1995 // write timestamp header if not completely written already 1996 int ret = 0; 1997 if (mAvSyncHeader.remaining() != 0) { 1998 ret = write(mAvSyncHeader, mAvSyncHeader.remaining(), writeMode); 1999 if (ret < 0) { 2000 Log.e(TAG, "AudioTrack.write() could not write timestamp header!"); 2001 mAvSyncHeader = null; 2002 mAvSyncBytesRemaining = 0; 2003 return ret; 2004 } 2005 if (mAvSyncHeader.remaining() > 0) { 2006 Log.v(TAG, "AudioTrack.write() partial timestamp header written."); 2007 return 0; 2008 } 2009 } 2010 2011 // write audio data 2012 int sizeToWrite = Math.min(mAvSyncBytesRemaining, sizeInBytes); 2013 ret = write(audioData, sizeToWrite, writeMode); 2014 if (ret < 0) { 2015 Log.e(TAG, "AudioTrack.write() could not write audio data!"); 2016 mAvSyncHeader = null; 2017 mAvSyncBytesRemaining = 0; 2018 return ret; 2019 } 2020 2021 mAvSyncBytesRemaining -= ret; 2022 if (mAvSyncBytesRemaining == 0) { 2023 mAvSyncHeader = null; 2024 } 2025 2026 return ret; 2027 } 2028 2029 2030 /** 2031 * Sets the playback head position within the static buffer to zero, 2032 * that is it rewinds to start of static buffer. 2033 * The track must be stopped or paused, and 2034 * the track's creation mode must be {@link #MODE_STATIC}. 2035 * <p> 2036 * As of {@link android.os.Build.VERSION_CODES#MNC}, also resets the value returned by 2037 * {@link #getPlaybackHeadPosition()} to zero. 2038 * For earlier API levels, the reset behavior is unspecified. 2039 * <p> 2040 * Use {@link #setPlaybackHeadPosition(int)} with a zero position 2041 * if the reset of <code>getPlaybackHeadPosition()</code> is not needed. 2042 * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE}, 2043 * {@link #ERROR_INVALID_OPERATION} 2044 */ 2045 public int reloadStaticData() { 2046 if (mDataLoadMode == MODE_STREAM || mState != STATE_INITIALIZED) { 2047 return ERROR_INVALID_OPERATION; 2048 } 2049 return native_reload_static(); 2050 } 2051 2052 //-------------------------------------------------------------------------- 2053 // Audio effects management 2054 //-------------------- 2055 2056 /** 2057 * Attaches an auxiliary effect to the audio track. A typical auxiliary 2058 * effect is a reverberation effect which can be applied on any sound source 2059 * that directs a certain amount of its energy to this effect. This amount 2060 * is defined by setAuxEffectSendLevel(). 2061 * {@see #setAuxEffectSendLevel(float)}. 2062 * <p>After creating an auxiliary effect (e.g. 2063 * {@link android.media.audiofx.EnvironmentalReverb}), retrieve its ID with 2064 * {@link android.media.audiofx.AudioEffect#getId()} and use it when calling 2065 * this method to attach the audio track to the effect. 2066 * <p>To detach the effect from the audio track, call this method with a 2067 * null effect id. 2068 * 2069 * @param effectId system wide unique id of the effect to attach 2070 * @return error code or success, see {@link #SUCCESS}, 2071 * {@link #ERROR_INVALID_OPERATION}, {@link #ERROR_BAD_VALUE} 2072 */ 2073 public int attachAuxEffect(int effectId) { 2074 if (mState == STATE_UNINITIALIZED) { 2075 return ERROR_INVALID_OPERATION; 2076 } 2077 return native_attachAuxEffect(effectId); 2078 } 2079 2080 /** 2081 * Sets the send level of the audio track to the attached auxiliary effect 2082 * {@link #attachAuxEffect(int)}. Effect levels 2083 * are clamped to the closed interval [0.0, max] where 2084 * max is the value of {@link #getMaxVolume}. 2085 * A value of 0.0 results in no effect, and a value of 1.0 is full send. 2086 * <p>By default the send level is 0.0f, so even if an effect is attached to the player 2087 * this method must be called for the effect to be applied. 2088 * <p>Note that the passed level value is a linear scalar. UI controls should be scaled 2089 * logarithmically: the gain applied by audio framework ranges from -72dB to at least 0dB, 2090 * so an appropriate conversion from linear UI input x to level is: 2091 * x == 0 -> level = 0 2092 * 0 < x <= R -> level = 10^(72*(x-R)/20/R) 2093 * 2094 * @param level linear send level 2095 * @return error code or success, see {@link #SUCCESS}, 2096 * {@link #ERROR_INVALID_OPERATION}, {@link #ERROR} 2097 */ 2098 public int setAuxEffectSendLevel(float level) { 2099 if (isRestricted()) { 2100 return SUCCESS; 2101 } 2102 if (mState == STATE_UNINITIALIZED) { 2103 return ERROR_INVALID_OPERATION; 2104 } 2105 level = clampGainOrLevel(level); 2106 int err = native_setAuxEffectSendLevel(level); 2107 return err == 0 ? SUCCESS : ERROR; 2108 } 2109 2110 //-------------------------------------------------------------------------- 2111 // Explicit Routing 2112 //-------------------- 2113 private AudioDeviceInfo mPreferredDevice = null; 2114 2115 /** 2116 * Specifies an audio device (via an {@link AudioDeviceInfo} object) to route 2117 * the output from this AudioTrack. 2118 * @param deviceInfo The {@link AudioDeviceInfo} specifying the audio sink. 2119 * If deviceInfo is null, default routing is restored. 2120 * @return true if succesful, false if the specified {@link AudioDeviceInfo} is non-null and 2121 * does not correspond to a valid audio output device. 2122 */ 2123 public boolean setPreferredOutputDevice(AudioDeviceInfo deviceInfo) { 2124 // Do some validation.... 2125 if (deviceInfo != null && !deviceInfo.isSink()) { 2126 return false; 2127 } 2128 2129 mPreferredDevice = deviceInfo; 2130 int preferredDeviceId = mPreferredDevice != null ? deviceInfo.getId() : 0; 2131 2132 return native_setOutputDevice(preferredDeviceId); 2133 } 2134 2135 /** 2136 * Returns the selected output specified by {@link #setPreferredOutputDevice}. Note that this 2137 * is not guaranteed to correspond to the actual device being used for playback. 2138 */ 2139 public AudioDeviceInfo getPreferredOutputDevice() { 2140 return mPreferredDevice; 2141 } 2142 2143 //-------------------------------------------------------------------------- 2144 // (Re)Routing Info 2145 //-------------------- 2146 /** 2147 * Returns an {@link AudioDeviceInfo} identifying the current routing of this AudioTrack. 2148 */ 2149 public AudioDeviceInfo getRoutedDevice() { 2150 return null; 2151 } 2152 2153 /** 2154 * The message sent to apps when the routing of this AudioTrack changes if they provide 2155 * a {#link Handler} object to addOnAudioTrackRoutingListener(). 2156 */ 2157 private ArrayMap<OnAudioTrackRoutingListener, NativeRoutingEventHandlerDelegate> 2158 mRoutingChangeListeners = 2159 new ArrayMap<OnAudioTrackRoutingListener, NativeRoutingEventHandlerDelegate>(); 2160 2161 /** 2162 * Adds an {@link OnAudioTrackRoutingListener} to receive notifications of routing changes 2163 * on this AudioTrack. 2164 */ 2165 public void addOnAudioTrackRoutingListener(OnAudioTrackRoutingListener listener, 2166 android.os.Handler handler) { 2167 if (listener != null && !mRoutingChangeListeners.containsKey(listener)) { 2168 synchronized (mRoutingChangeListeners) { 2169 mRoutingChangeListeners.put( 2170 listener, new NativeRoutingEventHandlerDelegate(this, listener, handler)); 2171 } 2172 } 2173 } 2174 2175 /** 2176 * Removes an {@link OnAudioTrackRoutingListener} which has been previously added 2177 * to receive notifications of changes to the set of connected audio devices. 2178 */ 2179 public void removeOnAudioTrackRoutingListener(OnAudioTrackRoutingListener listener) { 2180 synchronized (mRoutingChangeListeners) { 2181 if (mRoutingChangeListeners.containsKey(listener)) { 2182 mRoutingChangeListeners.remove(listener); 2183 } 2184 } 2185 } 2186 2187 /** 2188 * Sends device list change notification to all listeners. 2189 */ 2190 private void broadcastRoutingChange() { 2191 Collection<NativeRoutingEventHandlerDelegate> values; 2192 synchronized (mRoutingChangeListeners) { 2193 values = mRoutingChangeListeners.values(); 2194 } 2195 for(NativeRoutingEventHandlerDelegate delegate : values) { 2196 Handler handler = delegate.getHandler(); 2197 if (handler != null) { 2198 handler.sendEmptyMessage(NATIVE_EVENT_ROUTING_CHANGE); 2199 } 2200 } 2201 } 2202 2203 //--------------------------------------------------------- 2204 // Interface definitions 2205 //-------------------- 2206 /** 2207 * Interface definition for a callback to be invoked when the playback head position of 2208 * an AudioTrack has reached a notification marker or has increased by a certain period. 2209 */ 2210 public interface OnPlaybackPositionUpdateListener { 2211 /** 2212 * Called on the listener to notify it that the previously set marker has been reached 2213 * by the playback head. 2214 */ 2215 void onMarkerReached(AudioTrack track); 2216 2217 /** 2218 * Called on the listener to periodically notify it that the playback head has reached 2219 * a multiple of the notification period. 2220 */ 2221 void onPeriodicNotification(AudioTrack track); 2222 } 2223 2224 //--------------------------------------------------------- 2225 // Inner classes 2226 //-------------------- 2227 /** 2228 * Helper class to handle the forwarding of native events to the appropriate listener 2229 * (potentially) handled in a different thread 2230 */ 2231 private class NativePositionEventHandlerDelegate { 2232 private final Handler mHandler; 2233 2234 NativePositionEventHandlerDelegate(final AudioTrack track, 2235 final OnPlaybackPositionUpdateListener listener, 2236 Handler handler) { 2237 // find the looper for our new event handler 2238 Looper looper; 2239 if (handler != null) { 2240 looper = handler.getLooper(); 2241 } else { 2242 // no given handler, use the looper the AudioTrack was created in 2243 looper = mInitializationLooper; 2244 } 2245 2246 // construct the event handler with this looper 2247 if (looper != null) { 2248 // implement the event handler delegate 2249 mHandler = new Handler(looper) { 2250 @Override 2251 public void handleMessage(Message msg) { 2252 if (track == null) { 2253 return; 2254 } 2255 switch(msg.what) { 2256 case NATIVE_EVENT_MARKER: 2257 if (listener != null) { 2258 listener.onMarkerReached(track); 2259 } 2260 break; 2261 case NATIVE_EVENT_NEW_POS: 2262 if (listener != null) { 2263 listener.onPeriodicNotification(track); 2264 } 2265 break; 2266 default: 2267 loge("Unknown native event type: " + msg.what); 2268 break; 2269 } 2270 } 2271 }; 2272 } else { 2273 mHandler = null; 2274 } 2275 } 2276 2277 Handler getHandler() { 2278 return mHandler; 2279 } 2280 } 2281 2282 /** 2283 * Helper class to handle the forwarding of native events to the appropriate listener 2284 * (potentially) handled in a different thread 2285 */ 2286 private class NativeRoutingEventHandlerDelegate { 2287 private final Handler mHandler; 2288 2289 NativeRoutingEventHandlerDelegate(final AudioTrack track, 2290 final OnAudioTrackRoutingListener listener, 2291 Handler handler) { 2292 // find the looper for our new event handler 2293 Looper looper; 2294 if (handler != null) { 2295 looper = handler.getLooper(); 2296 } else { 2297 // no given handler, use the looper the AudioTrack was created in 2298 looper = mInitializationLooper; 2299 } 2300 2301 // construct the event handler with this looper 2302 if (looper != null) { 2303 // implement the event handler delegate 2304 mHandler = new Handler(looper) { 2305 @Override 2306 public void handleMessage(Message msg) { 2307 if (track == null) { 2308 return; 2309 } 2310 switch(msg.what) { 2311 case NATIVE_EVENT_ROUTING_CHANGE: 2312 if (listener != null) { 2313 listener.onAudioTrackRouting(track); 2314 } 2315 break; 2316 default: 2317 loge("Unknown native event type: " + msg.what); 2318 break; 2319 } 2320 } 2321 }; 2322 } else { 2323 mHandler = null; 2324 } 2325 } 2326 2327 Handler getHandler() { 2328 return mHandler; 2329 } 2330 } 2331 2332 //--------------------------------------------------------- 2333 // Java methods called from the native side 2334 //-------------------- 2335 @SuppressWarnings("unused") 2336 private static void postEventFromNative(Object audiotrack_ref, 2337 int what, int arg1, int arg2, Object obj) { 2338 //logd("Event posted from the native side: event="+ what + " args="+ arg1+" "+arg2); 2339 AudioTrack track = (AudioTrack)((WeakReference)audiotrack_ref).get(); 2340 if (track == null) { 2341 return; 2342 } 2343 2344 NativePositionEventHandlerDelegate delegate = track.mEventHandlerDelegate; 2345 if (delegate != null) { 2346 Handler handler = delegate.getHandler(); 2347 if (handler != null) { 2348 Message m = handler.obtainMessage(what, arg1, arg2, obj); 2349 handler.sendMessage(m); 2350 } 2351 } 2352 2353 } 2354 2355 2356 //--------------------------------------------------------- 2357 // Native methods called from the Java side 2358 //-------------------- 2359 2360 // post-condition: mStreamType is overwritten with a value 2361 // that reflects the audio attributes (e.g. an AudioAttributes object with a usage of 2362 // AudioAttributes.USAGE_MEDIA will map to AudioManager.STREAM_MUSIC 2363 private native final int native_setup(Object /*WeakReference<AudioTrack>*/ audiotrack_this, 2364 Object /*AudioAttributes*/ attributes, 2365 int sampleRate, int channelMask, int audioFormat, 2366 int buffSizeInBytes, int mode, int[] sessionId); 2367 2368 private native final void native_finalize(); 2369 2370 private native final void native_release(); 2371 2372 private native final void native_start(); 2373 2374 private native final void native_stop(); 2375 2376 private native final void native_pause(); 2377 2378 private native final void native_flush(); 2379 2380 private native final int native_write_byte(byte[] audioData, 2381 int offsetInBytes, int sizeInBytes, int format, 2382 boolean isBlocking); 2383 2384 private native final int native_write_short(short[] audioData, 2385 int offsetInShorts, int sizeInShorts, int format, 2386 boolean isBlocking); 2387 2388 private native final int native_write_float(float[] audioData, 2389 int offsetInFloats, int sizeInFloats, int format, 2390 boolean isBlocking); 2391 2392 private native final int native_write_native_bytes(Object audioData, 2393 int positionInBytes, int sizeInBytes, int format, boolean blocking); 2394 2395 private native final int native_reload_static(); 2396 2397 private native final int native_get_native_frame_count(); 2398 2399 private native final void native_setVolume(float leftVolume, float rightVolume); 2400 2401 private native final int native_set_playback_rate(int sampleRateInHz); 2402 private native final int native_get_playback_rate(); 2403 2404 // floatArray must be a non-null array of length >= 2 2405 // [0] is speed 2406 // [1] is pitch 2407 // intArray must be a non-null array of length >= 2 2408 // [0] is audio fallback mode 2409 // [1] is audio stretch mode 2410 private native final void native_set_playback_settings(float[] floatArray, int[] intArray); 2411 private native final void native_get_playback_settings(float[] floatArray, int[] intArray); 2412 2413 private native final int native_set_marker_pos(int marker); 2414 private native final int native_get_marker_pos(); 2415 2416 private native final int native_set_pos_update_period(int updatePeriod); 2417 private native final int native_get_pos_update_period(); 2418 2419 private native final int native_set_position(int position); 2420 private native final int native_get_position(); 2421 2422 private native final int native_get_latency(); 2423 2424 // longArray must be a non-null array of length >= 2 2425 // [0] is assigned the frame position 2426 // [1] is assigned the time in CLOCK_MONOTONIC nanoseconds 2427 private native final int native_get_timestamp(long[] longArray); 2428 2429 private native final int native_set_loop(int start, int end, int loopCount); 2430 2431 static private native final int native_get_output_sample_rate(int streamType); 2432 static private native final int native_get_min_buff_size( 2433 int sampleRateInHz, int channelConfig, int audioFormat); 2434 2435 private native final int native_attachAuxEffect(int effectId); 2436 private native final int native_setAuxEffectSendLevel(float level); 2437 2438 private native final boolean native_setOutputDevice(int deviceId); 2439 2440 //--------------------------------------------------------- 2441 // Utility methods 2442 //------------------ 2443 2444 private static void logd(String msg) { 2445 Log.d(TAG, msg); 2446 } 2447 2448 private static void loge(String msg) { 2449 Log.e(TAG, msg); 2450 } 2451} 2452