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