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 17 package android.media; 18 19 import java.lang.ref.WeakReference; 20 import java.lang.IllegalArgumentException; 21 import java.lang.IllegalStateException; 22 23 import android.os.Handler; 24 import android.os.Looper; 25 import android.os.Message; 26 import android.media.AudioManager; 27 import android.util.Log; 28 29 30 /** 31 * The AudioTrack class manages and plays a single audio resource for Java applications. 32 * It allows to stream PCM audio buffers to the audio hardware for playback. This is 33 * achieved by "pushing" the data to the AudioTrack object using one of the 34 * {@link #write(byte[], int, int)} and {@link #write(short[], int, int)} methods. 35 * 36 * <p>An AudioTrack instance can operate under two modes: static or streaming.<br> 37 * In Streaming mode, the application writes a continuous stream of data to the AudioTrack, using 38 * one of the {@code write()} methods. These are blocking and return when the data has been 39 * transferred from the Java layer to the native layer and queued for playback. The streaming 40 * mode is most useful when playing blocks of audio data that for instance are: 41 * 42 * <ul> 43 * <li>too big to fit in memory because of the duration of the sound to play,</li> 44 * <li>too big to fit in memory because of the characteristics of the audio data 45 * (high sampling rate, bits per sample ...)</li> 46 * <li>received or generated while previously queued audio is playing.</li> 47 * </ul> 48 * 49 * The static mode is to be chosen when dealing with short sounds that fit in memory and 50 * that need to be played with the smallest latency possible. The static mode will 51 * therefore be preferred for UI and game sounds that are played often, and with the 52 * smallest overhead possible. 53 * 54 * <p>Upon creation, an AudioTrack object initializes its associated audio buffer. 55 * The size of this buffer, specified during the construction, determines how long an AudioTrack 56 * can play before running out of data.<br> 57 * For an AudioTrack using the static mode, this size is the maximum size of the sound that can 58 * be played from it.<br> 59 * For the streaming mode, data will be written to the hardware in chunks of 60 * sizes inferior to the total buffer size. 61 */ 62 public class AudioTrack 63 { 64 //--------------------------------------------------------- 65 // Constants 66 //-------------------- 67 /** Minimum value for a channel volume */ 68 private static final float VOLUME_MIN = 0.0f; 69 /** Maximum value for a channel volume */ 70 private static final float VOLUME_MAX = 1.0f; 71 72 /** indicates AudioTrack state is stopped */ 73 public static final int PLAYSTATE_STOPPED = 1; // matches SL_PLAYSTATE_STOPPED 74 /** indicates AudioTrack state is paused */ 75 public static final int PLAYSTATE_PAUSED = 2; // matches SL_PLAYSTATE_PAUSED 76 /** indicates AudioTrack state is playing */ 77 public static final int PLAYSTATE_PLAYING = 3; // matches SL_PLAYSTATE_PLAYING 78 79 /** 80 * Creation mode where audio data is transferred from Java to the native layer 81 * only once before the audio starts playing. 82 */ 83 public static final int MODE_STATIC = 0; 84 /** 85 * Creation mode where audio data is streamed from Java to the native layer 86 * as the audio is playing. 87 */ 88 public static final int MODE_STREAM = 1; 89 90 /** 91 * State of an AudioTrack that was not successfully initialized upon creation. 92 */ 93 public static final int STATE_UNINITIALIZED = 0; 94 /** 95 * State of an AudioTrack that is ready to be used. 96 */ 97 public static final int STATE_INITIALIZED = 1; 98 /** 99 * State of a successfully initialized AudioTrack that uses static data, 100 * but that hasn't received that data yet. 101 */ 102 public static final int STATE_NO_STATIC_DATA = 2; 103 104 // Error codes: 105 // to keep in sync with frameworks/base/core/jni/android_media_AudioTrack.cpp 106 /** 107 * Denotes a successful operation. 108 */ 109 public static final int SUCCESS = 0; 110 /** 111 * Denotes a generic operation failure. 112 */ 113 public static final int ERROR = -1; 114 /** 115 * Denotes a failure due to the use of an invalid value. 116 */ 117 public static final int ERROR_BAD_VALUE = -2; 118 /** 119 * Denotes a failure due to the improper use of a method. 120 */ 121 public static final int ERROR_INVALID_OPERATION = -3; 122 123 private static final int ERROR_NATIVESETUP_AUDIOSYSTEM = -16; 124 private static final int ERROR_NATIVESETUP_INVALIDCHANNELMASK = -17; 125 private static final int ERROR_NATIVESETUP_INVALIDFORMAT = -18; 126 private static final int ERROR_NATIVESETUP_INVALIDSTREAMTYPE = -19; 127 private static final int ERROR_NATIVESETUP_NATIVEINITFAILED = -20; 128 129 // Events: 130 // to keep in sync with frameworks/base/include/media/AudioTrack.h 131 /** 132 * Event id denotes when playback head has reached a previously set marker. 133 */ 134 private static final int NATIVE_EVENT_MARKER = 3; 135 /** 136 * Event id denotes when previously set update period has elapsed during playback. 137 */ 138 private static final int NATIVE_EVENT_NEW_POS = 4; 139 140 private final static String TAG = "AudioTrack-Java"; 141 142 143 //-------------------------------------------------------------------------- 144 // Member variables 145 //-------------------- 146 /** 147 * Indicates the state of the AudioTrack instance. 148 */ 149 private int mState = STATE_UNINITIALIZED; 150 /** 151 * Indicates the play state of the AudioTrack instance. 152 */ 153 private int mPlayState = PLAYSTATE_STOPPED; 154 /** 155 * Lock to make sure mPlayState updates are reflecting the actual state of the object. 156 */ 157 private final Object mPlayStateLock = new Object(); 158 /** 159 * The listener the AudioTrack notifies when the playback position reaches a marker 160 * or for periodic updates during the progression of the playback head. 161 * @see #setPlaybackPositionUpdateListener(OnPlaybackPositionUpdateListener) 162 */ 163 private OnPlaybackPositionUpdateListener mPositionListener = null; 164 /** 165 * Lock to protect event listener updates against event notifications. 166 */ 167 private final Object mPositionListenerLock = new Object(); 168 /** 169 * Size of the native audio buffer. 170 */ 171 private int mNativeBufferSizeInBytes = 0; 172 /** 173 * Handler for marker events coming from the native code. 174 */ 175 private NativeEventHandlerDelegate mEventHandlerDelegate = null; 176 /** 177 * Looper associated with the thread that creates the AudioTrack instance. 178 */ 179 private Looper mInitializationLooper = null; 180 /** 181 * The audio data sampling rate in Hz. 182 */ 183 private int mSampleRate = 22050; 184 /** 185 * The number of audio output channels (1 is mono, 2 is stereo). 186 */ 187 private int mChannelCount = 1; 188 /** 189 * The audio channel mask. 190 */ 191 private int mChannels = AudioFormat.CHANNEL_OUT_MONO; 192 193 /** 194 * The type of the audio stream to play. See 195 * {@link AudioManager#STREAM_VOICE_CALL}, {@link AudioManager#STREAM_SYSTEM}, 196 * {@link AudioManager#STREAM_RING}, {@link AudioManager#STREAM_MUSIC} and 197 * {@link AudioManager#STREAM_ALARM} 198 */ 199 private int mStreamType = AudioManager.STREAM_MUSIC; 200 /** 201 * The way audio is consumed by the hardware, streaming or static. 202 */ 203 private int mDataLoadMode = MODE_STREAM; 204 /** 205 * The current audio channel configuration. 206 */ 207 private int mChannelConfiguration = AudioFormat.CHANNEL_OUT_MONO; 208 /** 209 * The encoding of the audio samples. 210 * @see AudioFormat#ENCODING_PCM_8BIT 211 * @see AudioFormat#ENCODING_PCM_16BIT 212 */ 213 private int mAudioFormat = AudioFormat.ENCODING_PCM_16BIT; 214 /** 215 * Audio session ID 216 */ 217 private int mSessionId = 0; 218 219 220 //-------------------------------- 221 // Used exclusively by native code 222 //-------------------- 223 /** 224 * Accessed by native methods: provides access to C++ AudioTrack object. 225 */ 226 @SuppressWarnings("unused") 227 private int mNativeTrackInJavaObj; 228 /** 229 * Accessed by native methods: provides access to the JNI data (i.e. resources used by 230 * the native AudioTrack object, but not stored in it). 231 */ 232 @SuppressWarnings("unused") 233 private int mJniData; 234 235 236 //-------------------------------------------------------------------------- 237 // Constructor, Finalize 238 //-------------------- 239 /** 240 * Class constructor. 241 * @param streamType the type of the audio stream. See 242 * {@link AudioManager#STREAM_VOICE_CALL}, {@link AudioManager#STREAM_SYSTEM}, 243 * {@link AudioManager#STREAM_RING}, {@link AudioManager#STREAM_MUSIC} and 244 * {@link AudioManager#STREAM_ALARM} 245 * @param sampleRateInHz the sample rate expressed in Hertz. Examples of rates are (but 246 * not limited to) 44100, 22050 and 11025. 247 * @param channelConfig describes the configuration of the audio channels. 248 * See {@link AudioFormat#CHANNEL_OUT_MONO} and 249 * {@link AudioFormat#CHANNEL_OUT_STEREO} 250 * @param audioFormat the format in which the audio data is represented. 251 * See {@link AudioFormat#ENCODING_PCM_16BIT} and 252 * {@link AudioFormat#ENCODING_PCM_8BIT} 253 * @param bufferSizeInBytes the total size (in bytes) of the buffer where audio data is read 254 * from for playback. If using the AudioTrack in streaming mode, you can write data into 255 * this buffer in smaller chunks than this size. If using the AudioTrack in static mode, 256 * this is the maximum size of the sound that will be played for this instance. 257 * See {@link #getMinBufferSize(int, int, int)} to determine the minimum required buffer size 258 * for the successful creation of an AudioTrack instance in streaming mode. Using values 259 * smaller than getMinBufferSize() will result in an initialization failure. 260 * @param mode streaming or static buffer. See {@link #MODE_STATIC} and {@link #MODE_STREAM} 261 * @throws java.lang.IllegalArgumentException 262 */ AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes, int mode)263 public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat, 264 int bufferSizeInBytes, int mode) 265 throws IllegalArgumentException { 266 this(streamType, sampleRateInHz, channelConfig, audioFormat, 267 bufferSizeInBytes, mode, 0); 268 } 269 270 /** 271 * Class constructor with audio session. Use this constructor when the AudioTrack must be 272 * attached to a particular audio session. The primary use of the audio session ID is to 273 * associate audio effects to a particular instance of AudioTrack: if an audio session ID 274 * is provided when creating an AudioEffect, this effect will be applied only to audio tracks 275 * and media players in the same session and not to the output mix. 276 * When an AudioTrack is created without specifying a session, it will create its own session 277 * which can be retreived by calling the {@link #getAudioSessionId()} method. 278 * If a session ID is provided, this AudioTrack will share effects attached to this session 279 * with all other media players or audio tracks in the same session. 280 * @param streamType the type of the audio stream. See 281 * {@link AudioManager#STREAM_VOICE_CALL}, {@link AudioManager#STREAM_SYSTEM}, 282 * {@link AudioManager#STREAM_RING}, {@link AudioManager#STREAM_MUSIC} and 283 * {@link AudioManager#STREAM_ALARM} 284 * @param sampleRateInHz the sample rate expressed in Hertz. Examples of rates are (but 285 * not limited to) 44100, 22050 and 11025. 286 * @param channelConfig describes the configuration of the audio channels. 287 * See {@link AudioFormat#CHANNEL_OUT_MONO} and 288 * {@link AudioFormat#CHANNEL_OUT_STEREO} 289 * @param audioFormat the format in which the audio data is represented. 290 * See {@link AudioFormat#ENCODING_PCM_16BIT} and 291 * {@link AudioFormat#ENCODING_PCM_8BIT} 292 * @param bufferSizeInBytes the total size (in bytes) of the buffer where audio data is read 293 * from for playback. If using the AudioTrack in streaming mode, you can write data into 294 * this buffer in smaller chunks than this size. If using the AudioTrack in static mode, 295 * this is the maximum size of the sound that will be played for this instance. 296 * See {@link #getMinBufferSize(int, int, int)} to determine the minimum required buffer size 297 * for the successful creation of an AudioTrack instance in streaming mode. Using values 298 * smaller than getMinBufferSize() will result in an initialization failure. 299 * @param mode streaming or static buffer. See {@link #MODE_STATIC} and {@link #MODE_STREAM} 300 * @param sessionId Id of audio session the AudioTrack must be attached to 301 * @throws java.lang.IllegalArgumentException 302 */ AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes, int mode, int sessionId)303 public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat, 304 int bufferSizeInBytes, int mode, int sessionId) 305 throws IllegalArgumentException { 306 mState = STATE_UNINITIALIZED; 307 308 // remember which looper is associated with the AudioTrack instanciation 309 if ((mInitializationLooper = Looper.myLooper()) == null) { 310 mInitializationLooper = Looper.getMainLooper(); 311 } 312 313 audioParamCheck(streamType, sampleRateInHz, channelConfig, audioFormat, mode); 314 315 audioBuffSizeCheck(bufferSizeInBytes); 316 317 if (sessionId < 0) { 318 throw (new IllegalArgumentException("Invalid audio session ID: "+sessionId)); 319 } 320 321 int[] session = new int[1]; 322 session[0] = sessionId; 323 // native initialization 324 int initResult = native_setup(new WeakReference<AudioTrack>(this), 325 mStreamType, mSampleRate, mChannels, mAudioFormat, 326 mNativeBufferSizeInBytes, mDataLoadMode, session); 327 if (initResult != SUCCESS) { 328 loge("Error code "+initResult+" when initializing AudioTrack."); 329 return; // with mState == STATE_UNINITIALIZED 330 } 331 332 mSessionId = session[0]; 333 334 if (mDataLoadMode == MODE_STATIC) { 335 mState = STATE_NO_STATIC_DATA; 336 } else { 337 mState = STATE_INITIALIZED; 338 } 339 } 340 341 342 // Convenience method for the constructor's parameter checks. 343 // This is where constructor IllegalArgumentException-s are thrown 344 // postconditions: 345 // mStreamType is valid 346 // mChannelCount is valid 347 // mChannels is valid 348 // mAudioFormat is valid 349 // mSampleRate is valid 350 // mDataLoadMode is valid audioParamCheck(int streamType, int sampleRateInHz, int channelConfig, int audioFormat, int mode)351 private void audioParamCheck(int streamType, int sampleRateInHz, 352 int channelConfig, int audioFormat, int mode) { 353 354 //-------------- 355 // stream type 356 if( (streamType != AudioManager.STREAM_ALARM) && (streamType != AudioManager.STREAM_MUSIC) 357 && (streamType != AudioManager.STREAM_RING) && (streamType != AudioManager.STREAM_SYSTEM) 358 && (streamType != AudioManager.STREAM_VOICE_CALL) 359 && (streamType != AudioManager.STREAM_NOTIFICATION) 360 && (streamType != AudioManager.STREAM_BLUETOOTH_SCO) 361 && (streamType != AudioManager.STREAM_DTMF)) { 362 throw (new IllegalArgumentException("Invalid stream type.")); 363 } else { 364 mStreamType = streamType; 365 } 366 367 //-------------- 368 // sample rate 369 if ( (sampleRateInHz < 4000) || (sampleRateInHz > 48000) ) { 370 throw (new IllegalArgumentException(sampleRateInHz 371 + "Hz is not a supported sample rate.")); 372 } else { 373 mSampleRate = sampleRateInHz; 374 } 375 376 //-------------- 377 // channel config 378 mChannelConfiguration = channelConfig; 379 380 switch (channelConfig) { 381 case AudioFormat.CHANNEL_OUT_DEFAULT: //AudioFormat.CHANNEL_CONFIGURATION_DEFAULT 382 case AudioFormat.CHANNEL_OUT_MONO: 383 case AudioFormat.CHANNEL_CONFIGURATION_MONO: 384 mChannelCount = 1; 385 mChannels = AudioFormat.CHANNEL_OUT_MONO; 386 break; 387 case AudioFormat.CHANNEL_OUT_STEREO: 388 case AudioFormat.CHANNEL_CONFIGURATION_STEREO: 389 mChannelCount = 2; 390 mChannels = AudioFormat.CHANNEL_OUT_STEREO; 391 break; 392 default: 393 mChannelCount = 0; 394 mChannels = AudioFormat.CHANNEL_INVALID; 395 mChannelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_INVALID; 396 throw(new IllegalArgumentException("Unsupported channel configuration.")); 397 } 398 399 //-------------- 400 // audio format 401 switch (audioFormat) { 402 case AudioFormat.ENCODING_DEFAULT: 403 mAudioFormat = AudioFormat.ENCODING_PCM_16BIT; 404 break; 405 case AudioFormat.ENCODING_PCM_16BIT: 406 case AudioFormat.ENCODING_PCM_8BIT: 407 mAudioFormat = audioFormat; 408 break; 409 default: 410 mAudioFormat = AudioFormat.ENCODING_INVALID; 411 throw(new IllegalArgumentException("Unsupported sample encoding." 412 + " Should be ENCODING_PCM_8BIT or ENCODING_PCM_16BIT.")); 413 } 414 415 //-------------- 416 // audio load mode 417 if ( (mode != MODE_STREAM) && (mode != MODE_STATIC) ) { 418 throw(new IllegalArgumentException("Invalid mode.")); 419 } else { 420 mDataLoadMode = mode; 421 } 422 } 423 424 425 // Convenience method for the contructor's audio buffer size check. 426 // preconditions: 427 // mChannelCount is valid 428 // mAudioFormat is valid 429 // postcondition: 430 // mNativeBufferSizeInBytes is valid (multiple of frame size, positive) audioBuffSizeCheck(int audioBufferSize)431 private void audioBuffSizeCheck(int audioBufferSize) { 432 // NB: this section is only valid with PCM data. 433 // To update when supporting compressed formats 434 int frameSizeInBytes = mChannelCount 435 * (mAudioFormat == AudioFormat.ENCODING_PCM_8BIT ? 1 : 2); 436 if ((audioBufferSize % frameSizeInBytes != 0) || (audioBufferSize < 1)) { 437 throw (new IllegalArgumentException("Invalid audio buffer size.")); 438 } 439 440 mNativeBufferSizeInBytes = audioBufferSize; 441 } 442 443 444 /** 445 * Releases the native AudioTrack resources. 446 */ release()447 public void release() { 448 // even though native_release() stops the native AudioTrack, we need to stop 449 // AudioTrack subclasses too. 450 try { 451 stop(); 452 } catch(IllegalStateException ise) { 453 // don't raise an exception, we're releasing the resources. 454 } 455 native_release(); 456 mState = STATE_UNINITIALIZED; 457 } 458 459 @Override finalize()460 protected void finalize() { 461 native_finalize(); 462 } 463 464 //-------------------------------------------------------------------------- 465 // Getters 466 //-------------------- 467 /** 468 * Returns the minimum valid volume value. Volume values set under this one will 469 * be clamped at this value. 470 * @return the minimum volume expressed as a linear attenuation. 471 */ getMinVolume()472 static public float getMinVolume() { 473 return AudioTrack.VOLUME_MIN; 474 } 475 476 /** 477 * Returns the maximum valid volume value. Volume values set above this one will 478 * be clamped at this value. 479 * @return the maximum volume expressed as a linear attenuation. 480 */ getMaxVolume()481 static public float getMaxVolume() { 482 return AudioTrack.VOLUME_MAX; 483 } 484 485 /** 486 * Returns the configured audio data sample rate in Hz 487 */ getSampleRate()488 public int getSampleRate() { 489 return mSampleRate; 490 } 491 492 /** 493 * Returns the current playback rate in Hz. 494 */ getPlaybackRate()495 public int getPlaybackRate() { 496 return native_get_playback_rate(); 497 } 498 499 /** 500 * Returns the configured audio data format. See {@link AudioFormat#ENCODING_PCM_16BIT} 501 * and {@link AudioFormat#ENCODING_PCM_8BIT}. 502 */ getAudioFormat()503 public int getAudioFormat() { 504 return mAudioFormat; 505 } 506 507 /** 508 * Returns the type of audio stream this AudioTrack is configured for. 509 * Compare the result against {@link AudioManager#STREAM_VOICE_CALL}, 510 * {@link AudioManager#STREAM_SYSTEM}, {@link AudioManager#STREAM_RING}, 511 * {@link AudioManager#STREAM_MUSIC} or {@link AudioManager#STREAM_ALARM} 512 */ getStreamType()513 public int getStreamType() { 514 return mStreamType; 515 } 516 517 /** 518 * Returns the configured channel configuration. 519 520 * See {@link AudioFormat#CHANNEL_OUT_MONO} 521 * and {@link AudioFormat#CHANNEL_OUT_STEREO}. 522 */ getChannelConfiguration()523 public int getChannelConfiguration() { 524 return mChannelConfiguration; 525 } 526 527 /** 528 * Returns the configured number of channels. 529 */ getChannelCount()530 public int getChannelCount() { 531 return mChannelCount; 532 } 533 534 /** 535 * Returns the state of the AudioTrack instance. This is useful after the 536 * AudioTrack instance has been created to check if it was initialized 537 * properly. This ensures that the appropriate hardware resources have been 538 * acquired. 539 * @see #STATE_INITIALIZED 540 * @see #STATE_NO_STATIC_DATA 541 * @see #STATE_UNINITIALIZED 542 */ getState()543 public int getState() { 544 return mState; 545 } 546 547 /** 548 * Returns the playback state of the AudioTrack instance. 549 * @see #PLAYSTATE_STOPPED 550 * @see #PLAYSTATE_PAUSED 551 * @see #PLAYSTATE_PLAYING 552 */ getPlayState()553 public int getPlayState() { 554 synchronized (mPlayStateLock) { 555 return mPlayState; 556 } 557 } 558 559 /** 560 * Returns the native frame count used by the hardware. 561 */ getNativeFrameCount()562 protected int getNativeFrameCount() { 563 return native_get_native_frame_count(); 564 } 565 566 /** 567 * Returns marker position expressed in frames. 568 */ getNotificationMarkerPosition()569 public int getNotificationMarkerPosition() { 570 return native_get_marker_pos(); 571 } 572 573 /** 574 * Returns the notification update period expressed in frames. 575 */ getPositionNotificationPeriod()576 public int getPositionNotificationPeriod() { 577 return native_get_pos_update_period(); 578 } 579 580 /** 581 * Returns the playback head position expressed in frames 582 */ getPlaybackHeadPosition()583 public int getPlaybackHeadPosition() { 584 return native_get_position(); 585 } 586 587 /** 588 * Returns the hardware output sample rate 589 */ getNativeOutputSampleRate(int streamType)590 static public int getNativeOutputSampleRate(int streamType) { 591 return native_get_output_sample_rate(streamType); 592 } 593 594 /** 595 * Returns the minimum buffer size required for the successful creation of an AudioTrack 596 * object to be created in the {@link #MODE_STREAM} mode. Note that this size doesn't 597 * guarantee a smooth playback under load, and higher values should be chosen according to 598 * the expected frequency at which the buffer will be refilled with additional data to play. 599 * @param sampleRateInHz the sample rate expressed in Hertz. 600 * @param channelConfig describes the configuration of the audio channels. 601 * See {@link AudioFormat#CHANNEL_OUT_MONO} and 602 * {@link AudioFormat#CHANNEL_OUT_STEREO} 603 * @param audioFormat the format in which the audio data is represented. 604 * See {@link AudioFormat#ENCODING_PCM_16BIT} and 605 * {@link AudioFormat#ENCODING_PCM_8BIT} 606 * @return {@link #ERROR_BAD_VALUE} if an invalid parameter was passed, 607 * or {@link #ERROR} if the implementation was unable to query the hardware for its output 608 * properties, 609 * or the minimum buffer size expressed in bytes. 610 */ getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat)611 static public int getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat) { 612 int channelCount = 0; 613 switch(channelConfig) { 614 case AudioFormat.CHANNEL_OUT_MONO: 615 case AudioFormat.CHANNEL_CONFIGURATION_MONO: 616 channelCount = 1; 617 break; 618 case AudioFormat.CHANNEL_OUT_STEREO: 619 case AudioFormat.CHANNEL_CONFIGURATION_STEREO: 620 channelCount = 2; 621 break; 622 default: 623 loge("getMinBufferSize(): Invalid channel configuration."); 624 return AudioTrack.ERROR_BAD_VALUE; 625 } 626 627 if ((audioFormat != AudioFormat.ENCODING_PCM_16BIT) 628 && (audioFormat != AudioFormat.ENCODING_PCM_8BIT)) { 629 loge("getMinBufferSize(): Invalid audio format."); 630 return AudioTrack.ERROR_BAD_VALUE; 631 } 632 633 if ( (sampleRateInHz < 4000) || (sampleRateInHz > 48000) ) { 634 loge("getMinBufferSize(): " + sampleRateInHz +"Hz is not a supported sample rate."); 635 return AudioTrack.ERROR_BAD_VALUE; 636 } 637 638 int size = native_get_min_buff_size(sampleRateInHz, channelCount, audioFormat); 639 if ((size == -1) || (size == 0)) { 640 loge("getMinBufferSize(): error querying hardware"); 641 return AudioTrack.ERROR; 642 } 643 else { 644 return size; 645 } 646 } 647 648 /** 649 * Returns the audio session ID. 650 * 651 * @return the ID of the audio session this AudioTrack belongs to. 652 */ getAudioSessionId()653 public int getAudioSessionId() { 654 return mSessionId; 655 } 656 657 //-------------------------------------------------------------------------- 658 // Initialization / configuration 659 //-------------------- 660 /** 661 * Sets the listener the AudioTrack notifies when a previously set marker is reached or 662 * for each periodic playback head position update. 663 * Notifications will be received in the same thread as the one in which the AudioTrack 664 * instance was created. 665 * @param listener 666 */ setPlaybackPositionUpdateListener(OnPlaybackPositionUpdateListener listener)667 public void setPlaybackPositionUpdateListener(OnPlaybackPositionUpdateListener listener) { 668 setPlaybackPositionUpdateListener(listener, null); 669 } 670 671 /** 672 * Sets the listener the AudioTrack notifies when a previously set marker is reached or 673 * for each periodic playback head position update. 674 * Use this method to receive AudioTrack events in the Handler associated with another 675 * thread than the one in which you created the AudioTrack instance. 676 * @param listener 677 * @param handler the Handler that will receive the event notification messages. 678 */ setPlaybackPositionUpdateListener(OnPlaybackPositionUpdateListener listener, Handler handler)679 public void setPlaybackPositionUpdateListener(OnPlaybackPositionUpdateListener listener, 680 Handler handler) { 681 synchronized (mPositionListenerLock) { 682 mPositionListener = listener; 683 } 684 if (listener != null) { 685 mEventHandlerDelegate = new NativeEventHandlerDelegate(this, handler); 686 } 687 688 } 689 690 691 692 /** 693 * Sets the specified left/right output volume values on the AudioTrack. Values are clamped 694 * to the ({@link #getMinVolume()}, {@link #getMaxVolume()}) interval if outside this range. 695 * @param leftVolume output attenuation for the left channel. A value of 0.0f is silence, 696 * a value of 1.0f is no attenuation. 697 * @param rightVolume output attenuation for the right channel 698 * @return error code or success, see {@link #SUCCESS}, 699 * {@link #ERROR_INVALID_OPERATION} 700 */ setStereoVolume(float leftVolume, float rightVolume)701 public int setStereoVolume(float leftVolume, float rightVolume) { 702 if (mState != STATE_INITIALIZED) { 703 return ERROR_INVALID_OPERATION; 704 } 705 706 // clamp the volumes 707 if (leftVolume < getMinVolume()) { 708 leftVolume = getMinVolume(); 709 } 710 if (leftVolume > getMaxVolume()) { 711 leftVolume = getMaxVolume(); 712 } 713 if (rightVolume < getMinVolume()) { 714 rightVolume = getMinVolume(); 715 } 716 if (rightVolume > getMaxVolume()) { 717 rightVolume = getMaxVolume(); 718 } 719 720 native_setVolume(leftVolume, rightVolume); 721 722 return SUCCESS; 723 } 724 725 726 /** 727 * Sets the playback sample rate for this track. This sets the sampling rate at which 728 * the audio data will be consumed and played back, not the original sampling rate of the 729 * content. Setting it to half the sample rate of the content will cause the playback to 730 * last twice as long, but will also result in a negative pitch shift. 731 * The valid sample rate range if from 1Hz to twice the value returned by 732 * {@link #getNativeOutputSampleRate(int)}. 733 * @param sampleRateInHz the sample rate expressed in Hz 734 * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE}, 735 * {@link #ERROR_INVALID_OPERATION} 736 */ setPlaybackRate(int sampleRateInHz)737 public int setPlaybackRate(int sampleRateInHz) { 738 if (mState != STATE_INITIALIZED) { 739 return ERROR_INVALID_OPERATION; 740 } 741 if (sampleRateInHz <= 0) { 742 return ERROR_BAD_VALUE; 743 } 744 return native_set_playback_rate(sampleRateInHz); 745 } 746 747 748 /** 749 * Sets the position of the notification marker. 750 * @param markerInFrames marker in frames 751 * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE}, 752 * {@link #ERROR_INVALID_OPERATION} 753 */ setNotificationMarkerPosition(int markerInFrames)754 public int setNotificationMarkerPosition(int markerInFrames) { 755 if (mState != STATE_INITIALIZED) { 756 return ERROR_INVALID_OPERATION; 757 } 758 return native_set_marker_pos(markerInFrames); 759 } 760 761 762 /** 763 * Sets the period for the periodic notification event. 764 * @param periodInFrames update period expressed in frames 765 * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_INVALID_OPERATION} 766 */ setPositionNotificationPeriod(int periodInFrames)767 public int setPositionNotificationPeriod(int periodInFrames) { 768 if (mState != STATE_INITIALIZED) { 769 return ERROR_INVALID_OPERATION; 770 } 771 return native_set_pos_update_period(periodInFrames); 772 } 773 774 775 /** 776 * Sets the playback head position. The track must be stopped for the position to be changed. 777 * @param positionInFrames playback head position expressed in frames 778 * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE}, 779 * {@link #ERROR_INVALID_OPERATION} 780 */ setPlaybackHeadPosition(int positionInFrames)781 public int setPlaybackHeadPosition(int positionInFrames) { 782 synchronized(mPlayStateLock) { 783 if ((mPlayState == PLAYSTATE_STOPPED) || (mPlayState == PLAYSTATE_PAUSED)) { 784 return native_set_position(positionInFrames); 785 } else { 786 return ERROR_INVALID_OPERATION; 787 } 788 } 789 } 790 791 /** 792 * Sets the loop points and the loop count. The loop can be infinite. 793 * @param startInFrames loop start marker expressed in frames 794 * @param endInFrames loop end marker expressed in frames 795 * @param loopCount the number of times the loop is looped. 796 * A value of -1 means infinite looping. 797 * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE}, 798 * {@link #ERROR_INVALID_OPERATION} 799 */ setLoopPoints(int startInFrames, int endInFrames, int loopCount)800 public int setLoopPoints(int startInFrames, int endInFrames, int loopCount) { 801 if (mDataLoadMode == MODE_STREAM) { 802 return ERROR_INVALID_OPERATION; 803 } 804 return native_set_loop(startInFrames, endInFrames, loopCount); 805 } 806 807 /** 808 * Sets the initialization state of the instance. To be used in an AudioTrack subclass 809 * constructor to set a subclass-specific post-initialization state. 810 * @param state the state of the AudioTrack instance 811 */ setState(int state)812 protected void setState(int state) { 813 mState = state; 814 } 815 816 817 //--------------------------------------------------------- 818 // Transport control methods 819 //-------------------- 820 /** 821 * Starts playing an AudioTrack. 822 * 823 * @throws IllegalStateException 824 */ play()825 public void play() 826 throws IllegalStateException { 827 if (mState != STATE_INITIALIZED) { 828 throw(new IllegalStateException("play() called on uninitialized AudioTrack.")); 829 } 830 831 synchronized(mPlayStateLock) { 832 native_start(); 833 mPlayState = PLAYSTATE_PLAYING; 834 } 835 } 836 837 /** 838 * Stops playing the audio data. 839 * 840 * @throws IllegalStateException 841 */ stop()842 public void stop() 843 throws IllegalStateException { 844 if (mState != STATE_INITIALIZED) { 845 throw(new IllegalStateException("stop() called on uninitialized AudioTrack.")); 846 } 847 848 // stop playing 849 synchronized(mPlayStateLock) { 850 native_stop(); 851 mPlayState = PLAYSTATE_STOPPED; 852 } 853 } 854 855 /** 856 * Pauses the playback of the audio data. Data that has not been played 857 * back will not be discarded. Subsequent calls to {@link #play} will play 858 * this data back. 859 * 860 * @throws IllegalStateException 861 */ pause()862 public void pause() 863 throws IllegalStateException { 864 if (mState != STATE_INITIALIZED) { 865 throw(new IllegalStateException("pause() called on uninitialized AudioTrack.")); 866 } 867 //logd("pause()"); 868 869 // pause playback 870 synchronized(mPlayStateLock) { 871 native_pause(); 872 mPlayState = PLAYSTATE_PAUSED; 873 } 874 } 875 876 877 //--------------------------------------------------------- 878 // Audio data supply 879 //-------------------- 880 881 /** 882 * Flushes the audio data currently queued for playback. Any data that has 883 * not been played back will be discarded. 884 */ flush()885 public void flush() { 886 if (mState == STATE_INITIALIZED) { 887 // flush the data in native layer 888 native_flush(); 889 } 890 891 } 892 893 /** 894 * Writes the audio data to the audio hardware for playback. Will block until 895 * all data has been written to the audio mixer. 896 * Note that the actual playback of this data might occur after this function 897 * returns. This function is thread safe with respect to {@link #stop} calls, 898 * in which case all of the specified data might not be written to the mixer. 899 * 900 * @param audioData the array that holds the data to play. 901 * @param offsetInBytes the offset expressed in bytes in audioData where the data to play 902 * starts. 903 * @param sizeInBytes the number of bytes to read in audioData after the offset. 904 * @return the number of bytes that were written or {@link #ERROR_INVALID_OPERATION} 905 * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if 906 * the parameters don't resolve to valid data and indexes. 907 */ 908 write(byte[] audioData,int offsetInBytes, int sizeInBytes)909 public int write(byte[] audioData,int offsetInBytes, int sizeInBytes) { 910 if ((mDataLoadMode == MODE_STATIC) 911 && (mState == STATE_NO_STATIC_DATA) 912 && (sizeInBytes > 0)) { 913 mState = STATE_INITIALIZED; 914 } 915 916 if (mState != STATE_INITIALIZED) { 917 return ERROR_INVALID_OPERATION; 918 } 919 920 if ( (audioData == null) || (offsetInBytes < 0 ) || (sizeInBytes < 0) 921 || (offsetInBytes + sizeInBytes > audioData.length)) { 922 return ERROR_BAD_VALUE; 923 } 924 925 return native_write_byte(audioData, offsetInBytes, sizeInBytes, mAudioFormat); 926 } 927 928 929 /** 930 * Writes the audio data to the audio hardware for playback. Will block until 931 * all data has been written to the audio mixer. 932 * Note that the actual playback of this data might occur after this function 933 * returns. This function is thread safe with respect to {@link #stop} calls, 934 * in which case all of the specified data might not be written to the mixer. 935 * 936 * @param audioData the array that holds the data to play. 937 * @param offsetInShorts the offset expressed in shorts in audioData where the data to play 938 * starts. 939 * @param sizeInShorts the number of bytes to read in audioData after the offset. 940 * @return the number of shorts that were written or {@link #ERROR_INVALID_OPERATION} 941 * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if 942 * the parameters don't resolve to valid data and indexes. 943 */ 944 write(short[] audioData, int offsetInShorts, int sizeInShorts)945 public int write(short[] audioData, int offsetInShorts, int sizeInShorts) { 946 if ((mDataLoadMode == MODE_STATIC) 947 && (mState == STATE_NO_STATIC_DATA) 948 && (sizeInShorts > 0)) { 949 mState = STATE_INITIALIZED; 950 } 951 952 if (mState != STATE_INITIALIZED) { 953 return ERROR_INVALID_OPERATION; 954 } 955 956 if ( (audioData == null) || (offsetInShorts < 0 ) || (sizeInShorts < 0) 957 || (offsetInShorts + sizeInShorts > audioData.length)) { 958 return ERROR_BAD_VALUE; 959 } 960 961 return native_write_short(audioData, offsetInShorts, sizeInShorts, mAudioFormat); 962 } 963 964 965 /** 966 * Notifies the native resource to reuse the audio data already loaded in the native 967 * layer. This call is only valid with AudioTrack instances that don't use the streaming 968 * model. 969 * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE}, 970 * {@link #ERROR_INVALID_OPERATION} 971 */ reloadStaticData()972 public int reloadStaticData() { 973 if (mDataLoadMode == MODE_STREAM) { 974 return ERROR_INVALID_OPERATION; 975 } 976 return native_reload_static(); 977 } 978 979 //-------------------------------------------------------------------------- 980 // Audio effects management 981 //-------------------- 982 983 /** 984 * Attaches an auxiliary effect to the audio track. A typical auxiliary 985 * effect is a reverberation effect which can be applied on any sound source 986 * that directs a certain amount of its energy to this effect. This amount 987 * is defined by setAuxEffectSendLevel(). 988 * {@see #setAuxEffectSendLevel(float)}. 989 * <p>After creating an auxiliary effect (e.g. 990 * {@link android.media.audiofx.EnvironmentalReverb}), retrieve its ID with 991 * {@link android.media.audiofx.AudioEffect#getId()} and use it when calling 992 * this method to attach the audio track to the effect. 993 * <p>To detach the effect from the audio track, call this method with a 994 * null effect id. 995 * 996 * @param effectId system wide unique id of the effect to attach 997 * @return error code or success, see {@link #SUCCESS}, 998 * {@link #ERROR_INVALID_OPERATION}, {@link #ERROR_BAD_VALUE} 999 */ attachAuxEffect(int effectId)1000 public int attachAuxEffect(int effectId) { 1001 if (mState != STATE_INITIALIZED) { 1002 return ERROR_INVALID_OPERATION; 1003 } 1004 return native_attachAuxEffect(effectId); 1005 } 1006 1007 /** 1008 * Sets the send level of the audio track to the attached auxiliary effect 1009 * {@link #attachAuxEffect(int)}. The level value range is 0 to 1.0. 1010 * <p>By default the send level is 0, so even if an effect is attached to the player 1011 * this method must be called for the effect to be applied. 1012 * <p>Note that the passed level value is a raw scalar. UI controls should be scaled 1013 * logarithmically: the gain applied by audio framework ranges from -72dB to 0dB, 1014 * so an appropriate conversion from linear UI input x to level is: 1015 * x == 0 -> level = 0 1016 * 0 < x <= R -> level = 10^(72*(x-R)/20/R) 1017 * 1018 * @param level send level scalar 1019 * @return error code or success, see {@link #SUCCESS}, 1020 * {@link #ERROR_INVALID_OPERATION} 1021 */ setAuxEffectSendLevel(float level)1022 public int setAuxEffectSendLevel(float level) { 1023 if (mState != STATE_INITIALIZED) { 1024 return ERROR_INVALID_OPERATION; 1025 } 1026 // clamp the level 1027 if (level < getMinVolume()) { 1028 level = getMinVolume(); 1029 } 1030 if (level > getMaxVolume()) { 1031 level = getMaxVolume(); 1032 } 1033 native_setAuxEffectSendLevel(level); 1034 return SUCCESS; 1035 } 1036 1037 //--------------------------------------------------------- 1038 // Interface definitions 1039 //-------------------- 1040 /** 1041 * Interface definition for a callback to be invoked when the playback head position of 1042 * an AudioTrack has reached a notification marker or has increased by a certain period. 1043 */ 1044 public interface OnPlaybackPositionUpdateListener { 1045 /** 1046 * Called on the listener to notify it that the previously set marker has been reached 1047 * by the playback head. 1048 */ onMarkerReached(AudioTrack track)1049 void onMarkerReached(AudioTrack track); 1050 1051 /** 1052 * Called on the listener to periodically notify it that the playback head has reached 1053 * a multiple of the notification period. 1054 */ onPeriodicNotification(AudioTrack track)1055 void onPeriodicNotification(AudioTrack track); 1056 } 1057 1058 1059 //--------------------------------------------------------- 1060 // Inner classes 1061 //-------------------- 1062 /** 1063 * Helper class to handle the forwarding of native events to the appropriate listener 1064 * (potentially) handled in a different thread 1065 */ 1066 private class NativeEventHandlerDelegate { 1067 private final AudioTrack mAudioTrack; 1068 private final Handler mHandler; 1069 NativeEventHandlerDelegate(AudioTrack track, Handler handler)1070 NativeEventHandlerDelegate(AudioTrack track, Handler handler) { 1071 mAudioTrack = track; 1072 // find the looper for our new event handler 1073 Looper looper; 1074 if (handler != null) { 1075 looper = handler.getLooper(); 1076 } else { 1077 // no given handler, use the looper the AudioTrack was created in 1078 looper = mInitializationLooper; 1079 } 1080 1081 // construct the event handler with this looper 1082 if (looper != null) { 1083 // implement the event handler delegate 1084 mHandler = new Handler(looper) { 1085 @Override 1086 public void handleMessage(Message msg) { 1087 if (mAudioTrack == null) { 1088 return; 1089 } 1090 OnPlaybackPositionUpdateListener listener = null; 1091 synchronized (mPositionListenerLock) { 1092 listener = mAudioTrack.mPositionListener; 1093 } 1094 switch(msg.what) { 1095 case NATIVE_EVENT_MARKER: 1096 if (listener != null) { 1097 listener.onMarkerReached(mAudioTrack); 1098 } 1099 break; 1100 case NATIVE_EVENT_NEW_POS: 1101 if (listener != null) { 1102 listener.onPeriodicNotification(mAudioTrack); 1103 } 1104 break; 1105 default: 1106 Log.e(TAG, "[ android.media.AudioTrack.NativeEventHandler ] " + 1107 "Unknown event type: " + msg.what); 1108 break; 1109 } 1110 } 1111 }; 1112 } else { 1113 mHandler = null; 1114 } 1115 } 1116 getHandler()1117 Handler getHandler() { 1118 return mHandler; 1119 } 1120 } 1121 1122 1123 //--------------------------------------------------------- 1124 // Java methods called from the native side 1125 //-------------------- 1126 @SuppressWarnings("unused") postEventFromNative(Object audiotrack_ref, int what, int arg1, int arg2, Object obj)1127 private static void postEventFromNative(Object audiotrack_ref, 1128 int what, int arg1, int arg2, Object obj) { 1129 //logd("Event posted from the native side: event="+ what + " args="+ arg1+" "+arg2); 1130 AudioTrack track = (AudioTrack)((WeakReference)audiotrack_ref).get(); 1131 if (track == null) { 1132 return; 1133 } 1134 1135 if (track.mEventHandlerDelegate != null) { 1136 Message m = 1137 track.mEventHandlerDelegate.getHandler().obtainMessage(what, arg1, arg2, obj); 1138 track.mEventHandlerDelegate.getHandler().sendMessage(m); 1139 } 1140 1141 } 1142 1143 1144 //--------------------------------------------------------- 1145 // Native methods called from the Java side 1146 //-------------------- 1147 native_setup(Object audiotrack_this, int streamType, int sampleRate, int nbChannels, int audioFormat, int buffSizeInBytes, int mode, int[] sessionId)1148 private native final int native_setup(Object audiotrack_this, 1149 int streamType, int sampleRate, int nbChannels, int audioFormat, 1150 int buffSizeInBytes, int mode, int[] sessionId); 1151 native_finalize()1152 private native final void native_finalize(); 1153 native_release()1154 private native final void native_release(); 1155 native_start()1156 private native final void native_start(); 1157 native_stop()1158 private native final void native_stop(); 1159 native_pause()1160 private native final void native_pause(); 1161 native_flush()1162 private native final void native_flush(); 1163 native_write_byte(byte[] audioData, int offsetInBytes, int sizeInBytes, int format)1164 private native final int native_write_byte(byte[] audioData, 1165 int offsetInBytes, int sizeInBytes, int format); 1166 native_write_short(short[] audioData, int offsetInShorts, int sizeInShorts, int format)1167 private native final int native_write_short(short[] audioData, 1168 int offsetInShorts, int sizeInShorts, int format); 1169 native_reload_static()1170 private native final int native_reload_static(); 1171 native_get_native_frame_count()1172 private native final int native_get_native_frame_count(); 1173 native_setVolume(float leftVolume, float rightVolume)1174 private native final void native_setVolume(float leftVolume, float rightVolume); 1175 native_set_playback_rate(int sampleRateInHz)1176 private native final int native_set_playback_rate(int sampleRateInHz); native_get_playback_rate()1177 private native final int native_get_playback_rate(); 1178 native_set_marker_pos(int marker)1179 private native final int native_set_marker_pos(int marker); native_get_marker_pos()1180 private native final int native_get_marker_pos(); 1181 native_set_pos_update_period(int updatePeriod)1182 private native final int native_set_pos_update_period(int updatePeriod); native_get_pos_update_period()1183 private native final int native_get_pos_update_period(); 1184 native_set_position(int position)1185 private native final int native_set_position(int position); native_get_position()1186 private native final int native_get_position(); 1187 native_set_loop(int start, int end, int loopCount)1188 private native final int native_set_loop(int start, int end, int loopCount); 1189 native_get_output_sample_rate(int streamType)1190 static private native final int native_get_output_sample_rate(int streamType); native_get_min_buff_size( int sampleRateInHz, int channelConfig, int audioFormat)1191 static private native final int native_get_min_buff_size( 1192 int sampleRateInHz, int channelConfig, int audioFormat); 1193 native_get_session_id()1194 private native final int native_get_session_id(); 1195 native_attachAuxEffect(int effectId)1196 private native final int native_attachAuxEffect(int effectId); native_setAuxEffectSendLevel(float level)1197 private native final void native_setAuxEffectSendLevel(float level); 1198 1199 //--------------------------------------------------------- 1200 // Utility methods 1201 //------------------ 1202 logd(String msg)1203 private static void logd(String msg) { 1204 Log.d(TAG, "[ android.media.AudioTrack ] " + msg); 1205 } 1206 loge(String msg)1207 private static void loge(String msg) { 1208 Log.e(TAG, "[ android.media.AudioTrack ] " + msg); 1209 } 1210 1211 } 1212