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