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