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