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