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