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