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