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