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