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