AudioTrack

AudioTrack 在Java应用中,管理和播放一个单一的语音资源

The AudioTrack class manages and plays a single audio resource for Java applications.
 * It allows streaming of PCM audio buffers to the audio sink for playback. This is
 * achieved by "pushing" the data to the AudioTrack object using one of the
 *  {@link #write(byte[], int, int)} and {@link #write(short[], int, int)} methods.
 

一个AudioTrack 实例可以在两种模式下运行:static和streaming模式

 

在Streaming模式下,应用调用write()方法,向AudioTrack中写入一段连续的数据流。

这个操作处于阻塞状态,直到数据从java层传递到native层,并且加入播放队列。才返回

streaming模式最适用于   以下音频数据块:

(1)音乐长度太长。导致太大放不进内存

(2)音乐质量太高,导致太大放不进内存。(高取样率,采样位数)

(3)在队列中的前一个audio正在播放时,接收到或生成。

 


 * <p>An AudioTrack instance can operate under two modes: static or streaming.<br>
 * In Streaming mode, the application writes a continuous stream of data to the AudioTrack, using
 * one of the {@code write()} methods. These are blocking and return when the data has been
 * transferred from the Java layer to the native layer and queued for playback. The streaming
 * mode is most useful when playing blocks of audio data that for instance are:
 *
 * <ul>
 *   <li>too big to fit in memory because of the duration of the sound to play,</li>
 *   <li>too big to fit in memory because of the characteristics of the audio data
 *         (high sampling rate, bits per sample ...)</li>
 *   <li>received or generated while previously queued audio is playing.</li>
 * </ul>
 *

static模式适用于  处理可以放在内存中的较短,且需要小的播放开销的声音片段

因此static模式适用于UI声音 和 游戏声音这种经常被播放的情况,开销很小。


 * The static mode should be chosen when dealing with short sounds that fit in memory and
 * that need to be played with the smallest latency possible. The static mode will
 * therefore be preferred for UI and game sounds that are played often, and with the
 * smallest overhead possible.
 

被创建后,一个AudioTrack对象初始化和它相关的音频缓存

缓存的大小在构造方法中被详细指定,决定了一个AudioTrack在用完数据之前能播放多长

对于一个使用static模式的AudioTrack,定义的size大小,是它能播放的声音片段大小的最大值

对使用streaming模式的, 写入audio sink(音频信宿)中的数据总和小于等于缓存大小。

AudioTrack 不是 final的,所以可以有子类,但是不推荐这么做


 * <p>Upon creation, an AudioTrack object initializes its associated audio buffer.
 * The size of this buffer, specified during the construction, determines how long an AudioTrack
 * can play before running out of data.<br>
 * For an AudioTrack using the static mode, this size is the maximum size of the sound that can
 * be played from it.<br>
 * For the streaming mode, data will be written to the audio sink in chunks of
 * sizes less than or equal to the total buffer size.
 *
 * AudioTrack is not final and thus permits subclasses, but such use is not recommended.

 

 

 

 

 

  1    /**
  2      * State of an AudioTrack that was not successfully initialized upon creation.
  3      */
  4     public static final int STATE_UNINITIALIZED = 0;  未成功初始化
  5     /**
  6      * State of an AudioTrack that is ready to be used.
  7      */
  8     public static final int STATE_INITIALIZED   = 1;  成功初始化
  9     /**
 10      * State of a successfully initialized AudioTrack that uses static data,
 11      * but that hasn't received that data yet.
 12      */
 13     public static final int STATE_NO_STATIC_DATA = 2;  使用static模式,成功初始化。但还没有收到任何音频数据
 14 
 15  
 16 
 17     /**
 18      * Indicates the state of the AudioTrack instance.
 19      */
 20     private int mState = STATE_UNINITIALIZED;     mState 记录当前AudioTrack 实例的状态
 21 
 22  
 23 
 24     /**
 25      * Indicates the play state of the AudioTrack instance.
 26      */
 27     private int mPlayState = PLAYSTATE_STOPPED;   mPlayState 记录当前播放状态  初始化为 stopped
 28 
 29  
 30 
 31     /**
 32      * Lock to make sure mPlayState updates are reflecting the actual state of the object.
 33      */
 34     private final Object mPlayStateLock = new Object();    mPlayState的锁 为保证反应播放真实状态
 35 
 36  
 37 
 38     /**
 39      * Looper associated with the thread that creates the AudioTrack instance.
 40      */
 41     private final Looper mInitializationLooper;    创建AudioTrack实例的线程的Looper
 42 
 43  
 44 
 45  
 46 
 47     /**
 48      * The audio data source sampling rate in Hz.
 49      */
 50     private int mSampleRate; // initialized by all constructors    音频数据资源的采样率(Hz)
 51 
 52  
 53 
 54     /**
 55      * The audio channel mask.
 56      */
 57     private int mChannels = AudioFormat.CHANNEL_OUT_MONO;    初始化为单声道
 58 
 59  
 60 
 61     /**
 62      * The type of the audio stream to play. See
 63      *   {@link AudioManager#STREAM_VOICE_CALL}, {@link AudioManager#STREAM_SYSTEM},     通话  系统
 64      *   {@link AudioManager#STREAM_RING}, {@link AudioManager#STREAM_MUSIC},          铃声  音乐
 65      *   {@link AudioManager#STREAM_ALARM}, {@link AudioManager#STREAM_NOTIFICATION}, and  闹铃  通知
 66      *   {@link AudioManager#STREAM_DTMF}.                           DTMF多音双频
 67      */
 68     private int mStreamType = AudioManager.STREAM_MUSIC;      初始化为音乐声道
 69     /**
 70      * The way audio is consumed by the audio sink, streaming or static.
 71      */
 72     private int mDataLoadMode = MODE_STREAM;             数据在音频信宿中的加载模式
 73     /**
 74      * The current audio channel configuration.
 75      */
 76     private int mChannelConfiguration = AudioFormat.CHANNEL_OUT_MONO;  当前音频通道配置
 77     /**
 78      * The encoding of the audio samples.
 79      * @see AudioFormat#ENCODING_PCM_8BIT
 80      * @see AudioFormat#ENCODING_PCM_16BIT
 81      */
 82     private int mAudioFormat = AudioFormat.ENCODING_PCM_16BIT;     音频格式 初始化为16bits per sample(设备保证支持的方式)
 83     /**
 84      * Audio session ID
 85      */
 86     private int mSessionId = 0;
 87 
 88  
 89 
 90  
 91 
 92     public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat,
 93             int bufferSizeInBytes, int mode)
 94       throws IllegalArgumentException {
 95           this(streamType, sampleRateInHz, channelConfig, audioFormat,
 96                   bufferSizeInBytes, mode, 0 /*session*/);
 97     }
 98 
 99  
100 
101 当AudioTrack必须和一个特殊的音频session绑定时。使用这个构造函数。
102 
103 session ID的首要用途是
104 
105 
106     /**
107      * Class constructor with audio session. Use this constructor when the AudioTrack must be
108      * attached to a particular audio session. The primary use of the audio session ID is to
109      * associate audio effects to a particular instance of AudioTrack: if an audio session ID
110      * is provided when creating an AudioEffect, this effect will be applied only to audio tracks
111      * and media players in the same session and not to the output mix.
112      * When an AudioTrack is created without specifying a session, it will create its own session
113      * which can be retrieved by calling the {@link #getAudioSessionId()} method.
114      * If a non-zero session ID is provided, this AudioTrack will share effects attached to this
115      * session
116      * with all other media players or audio tracks in the same session, otherwise a new session
117      * will be created for this track if none is supplied.
118      * @param streamType the type of the audio stream. See
119      *   {@link AudioManager#STREAM_VOICE_CALL}, {@link AudioManager#STREAM_SYSTEM},
120      *   {@link AudioManager#STREAM_RING}, {@link AudioManager#STREAM_MUSIC},
121      *   {@link AudioManager#STREAM_ALARM}, and {@link AudioManager#STREAM_NOTIFICATION}.
122      * @param sampleRateInHz the initial source sample rate expressed in Hz.
123      * @param channelConfig describes the configuration of the audio channels.
124      *   See {@link AudioFormat#CHANNEL_OUT_MONO} and
125      *   {@link AudioFormat#CHANNEL_OUT_STEREO}
126      * @param audioFormat the format in which the audio data is represented.
127      *   See {@link AudioFormat#ENCODING_PCM_16BIT} and
128      *   {@link AudioFormat#ENCODING_PCM_8BIT}
129 
130      * @param bufferSizeInBytes the total size (in bytes) of the buffer where audio data is read    
131      *   from for playback. If using the AudioTrack in streaming mode, you can write data into
132      *   this buffer in smaller chunks than this size. If using the AudioTrack in static mode,
133      *   this is the maximum size of the sound that will be played for this instance.
134      If track's creation mode is {@link #MODE_STREAM}, you can write data into
136      *   this buffer in chunks less than or equal to this size, and it is typical to use
137      *   chunks of 1/2 of the total size to permit double-buffering.
138      *   If the track's creation mode is {@link #MODE_STATIC},
139      *   this is the maximum length sample, or audio clip, that can be played by this instance.
140      *   See {@link #getMinBufferSize(int, int, int)} to determine the minimum required buffer size
141      *   for the successful creation of an AudioTrack instance in streaming mode. Using values
142      *   smaller than getMinBufferSize() will result in an initialization failure.
143 
144   bufferSizeInBytes  是音频缓存区的总大小。从中读出音频数据来播放
146   streaming模式中。写入的数据要小于等于这个值。通常传1/2buffer大小的数据。保证双重缓冲区处理
148   static模式中。这是能播放的音频大小的最大值。
150   通过getMinBufferSize来获得一个AudioTrack实例在streaming模式下正确初始化需要的缓存区最小值。
152   如果buffer比这个最小值还小。将会导致初始化失败
153 
154 
155      * @param mode streaming or static buffer. See {@link #MODE_STATIC} and {@link #MODE_STREAM}
156      * @param sessionId Id of audio session the AudioTrack must be attached to
157      * @throws java.lang.IllegalArgumentException
158      */
159     public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat,
160             int bufferSizeInBytes, int mode, int sessionId)
161 
162     throws IllegalArgumentException {
163         // mState already == STATE_UNINITIALIZED
164 
165         // remember which looper is associated with the AudioTrack instantiation
166         Looper looper;
167         if ((looper = Looper.myLooper()) == null) {
168             looper = Looper.getMainLooper();
169         }
170         mInitializationLooper = looper;      记录创建实例时  所在looper
171 
172         audioParamCheck(streamType, sampleRateInHz, channelConfig, audioFormat, mode);    检查参数合法性
173 
174         audioBuffSizeCheck(bufferSizeInBytes);      检查缓冲区大小
175 
176         if (sessionId < 0) {
177             throw new IllegalArgumentException("Invalid audio session ID: "+sessionId);
178         }
179 
180         int[] session = new int[1];
181         session[0] = sessionId;
182         // native initialization
183         int initResult = native_setup(new WeakReference<AudioTrack>(this),
184                 mStreamType, mSampleRate, mChannels, mAudioFormat,
185                 mNativeBufferSizeInBytes, mDataLoadMode, session);
186         if (initResult != SUCCESS) {
187             loge("Error code "+initResult+" when initializing AudioTrack.");
188             return; // with mState == STATE_UNINITIALIZED
189         }
190 
191         mSessionId = session[0];
192 
193         if (mDataLoadMode == MODE_STATIC) {
194             mState = STATE_NO_STATIC_DATA;
195         } else {
196             mState = STATE_INITIALIZED;
197         }
198     }
199 
200     // mask of all the channels supported by this implementation        按位或  也就是将1叠加。就是支持的所有通道模式
201     private static final int SUPPORTED_OUT_CHANNELS =
202             AudioFormat.CHANNEL_OUT_FRONT_LEFT |
203             AudioFormat.CHANNEL_OUT_FRONT_RIGHT |
204             AudioFormat.CHANNEL_OUT_FRONT_CENTER |
205             AudioFormat.CHANNEL_OUT_LOW_FREQUENCY |
206             AudioFormat.CHANNEL_OUT_BACK_LEFT |
207             AudioFormat.CHANNEL_OUT_BACK_RIGHT |
208             AudioFormat.CHANNEL_OUT_BACK_CENTER;
209 
210     // Convenience method for the constructor's parameter checks.
211     // This is where constructor IllegalArgumentException-s are thrown
212     // postconditions:
213     //    mStreamType is valid
214     //    mChannelCount is valid
215     //    mChannels is valid
216     //    mAudioFormat is valid
217     //    mSampleRate is valid
218     //    mDataLoadMode is valid
219     private void audioParamCheck(int streamType, int sampleRateInHz,        用于构造函数参数检查
220                                  int channelConfig, int audioFormat, int mode) {
221 
222         //--------------
223         // stream type
224         if( (streamType != AudioManager.STREAM_ALARM) && (streamType != AudioManager.STREAM_MUSIC)  
225            && (streamType != AudioManager.STREAM_RING) && (streamType != AudioManager.STREAM_SYSTEM)
226            && (streamType != AudioManager.STREAM_VOICE_CALL)
227            && (streamType != AudioManager.STREAM_NOTIFICATION)
228            && (streamType != AudioManager.STREAM_BLUETOOTH_SCO)
229            && (streamType != AudioManager.STREAM_DTMF)) {
230             throw new IllegalArgumentException("Invalid stream type.");
231         }
232         mStreamType = streamType;
233 
234         //--------------
235         // sample rate, note these values are subject to change
236         if ( (sampleRateInHz < 4000) || (sampleRateInHz > 48000) ) {      4000Hz <= 采样率 <= 48000Hz  合法
237             throw new IllegalArgumentException(sampleRateInHz
238                     + "Hz is not a supported sample rate.");
239         }
240         mSampleRate = sampleRateInHz;
241 
242         //--------------
243         // channel config
244         mChannelConfiguration = channelConfig;
245 
246         switch (channelConfig) {
247         case AudioFormat.CHANNEL_OUT_DEFAULT: //AudioFormat.CHANNEL_CONFIGURATION_DEFAULT
248         case AudioFormat.CHANNEL_OUT_MONO:
249         case AudioFormat.CHANNEL_CONFIGURATION_MONO:
250             mChannelCount = 1;                      声道数:1
251             mChannels = AudioFormat.CHANNEL_OUT_MONO;        单声道
252             break;
253         case AudioFormat.CHANNEL_OUT_STEREO:
254         case AudioFormat.CHANNEL_CONFIGURATION_STEREO:
255             mChannelCount = 2;                         声道数:2
256             mChannels = AudioFormat.CHANNEL_OUT_STEREO;       双声道
257             break;
258         default:
259             if (!isMultichannelConfigSupported(channelConfig)) {        不支持多声道   抛异常
260                 // input channel configuration features unsupported channels
261                 throw new IllegalArgumentException("Unsupported channel configuration.");
262             }
263             mChannels = channelConfig;
264             mChannelCount = Integer.bitCount(channelConfig);          计算1的位数  即为声道数母
265         }
266 
267         //--------------
268         // audio format
269         switch (audioFormat) {
270         case AudioFormat.ENCODING_DEFAULT:            默认16bit
271             mAudioFormat = AudioFormat.ENCODING_PCM_16BIT;
272             break;
273         case AudioFormat.ENCODING_PCM_16BIT:
274         case AudioFormat.ENCODING_PCM_8BIT:
275             mAudioFormat = audioFormat;
276             break;
277         default:
278             throw new IllegalArgumentException("Unsupported sample encoding."
279                 + " Should be ENCODING_PCM_8BIT or ENCODING_PCM_16BIT.");
280         }
281 
282         //--------------
283         // audio load mode
284         if ( (mode != MODE_STREAM) && (mode != MODE_STATIC) ) {  不是stream或者static  抛异常
285             throw new IllegalArgumentException("Invalid mode.");
286         }
287         mDataLoadMode = mode;
288     }
289 
290  
291 
292     // Convenience method for the constructor's audio buffer size check.
293     // preconditions:
294     //    mChannelCount is valid
295     //    mAudioFormat is valid
296     // postcondition:
297     //    mNativeBufferSizeInBytes is valid (multiple of frame size, positive)
298     private void audioBuffSizeCheck(int audioBufferSize) {
299         // NB: this section is only valid with PCM data.
300         //     To update when supporting compressed formats
301         int frameSizeInBytes = mChannelCount
302                 * (mAudioFormat == AudioFormat.ENCODING_PCM_8BIT ? 1 : 2);      帧大小 = 信道数  * (8bits per sample :1,16bits per sample :2303         if ((audioBufferSize % frameSizeInBytes != 0) || (audioBufferSize < 1)) {       不整 或<1。抛异常
304             throw new IllegalArgumentException("Invalid audio buffer size.");
305         }
306 
307         mNativeBufferSizeInBytes = audioBufferSize;
308         mNativeBufferSizeInFrames = audioBufferSize / frameSizeInBytes;          帧数
309     }
310 
311  
312 
313     /**
314      * Convenience method to check that the channel configuration (a.k.a channel mask) is supported
315      * @param channelConfig the mask to validate
316      * @return false if the AudioTrack can't be used with such a mask
317      */
318     private static boolean isMultichannelConfigSupported(int channelConfig) {
319         // check for unsupported channels
320         if ((channelConfig & SUPPORTED_OUT_CHANNELS) != channelConfig) {    不相等,也就是某个1被置0了。说明包含不支持的声道模式
321             loge("Channel configuration features unsupported channels");
322             return false;
323         }
324         // check for unsupported multichannel combinations:
325         // - FL/FR must be present
326         // - L/R channels must be paired (e.g. no single L channel)
327         final int frontPair =
328                 AudioFormat.CHANNEL_OUT_FRONT_LEFT | AudioFormat.CHANNEL_OUT_FRONT_RIGHT;  前置
329         if ((channelConfig & frontPair) != frontPair) {
330                 loge("Front channels must be present in multichannel configurations");
331                 return false;
332         }
333         final int backPair =
334                 AudioFormat.CHANNEL_OUT_BACK_LEFT | AudioFormat.CHANNEL_OUT_BACK_RIGHT;  后置
335         if ((channelConfig & backPair) != 0) {
336             if ((channelConfig & backPair) != backPair) {        支持后置,但是只支持其中一个。
337                 loge("Rear channels can't be used independently");
338                 return false;
339             }
340         }                            ==0情况下返回true。也就是不支持后置时,返回的是true
341         return true;
342     }
343 
344  
345 
346 
347     /**
348      * Releases the native AudioTrack resources.        释放native层的资源
349      */
350     public void release() {
351         // even though native_release() stops the native AudioTrack, we need to stop   即使native_release(); 中停止了native层的AudioTrack。我们还是需要调用stop去停止AudioTrack的子类
352         // AudioTrack subclasses too.
353         try {
354             stop();
355         } catch(IllegalStateException ise) {
356             // don't raise an exception, we're releasing the resources.
357         }
358         native_release();
359         mState = STATE_UNINITIALIZED;      状态设置为  未初始化
360     }
361 
362     @Override
363     protected void finalize() {
364         native_finalize();
365     }
366 
367     //--------------------------------------------------------------------------
368     // Getters
369     //--------------------
370     /**
371      * Returns the minimum valid volume value. Volume values set under this one will    如果音量设置比MIN小,则置为0.1
372      * be clamped at this value.
373      * @return the minimum volume expressed as a linear attenuation.
374      */
375     static public float getMinVolume() {
376         return VOLUME_MIN;
377     }
378 
379     /**
380      * Returns the maximum valid volume value. Volume values set above this one will    如果音量设置比MAX大,则置为1.0
381      * be clamped at this value.
382      * @return the maximum volume expressed as a linear attenuation.
383      */
384     static public float getMaxVolume() {
385         return VOLUME_MAX;
386     }
387 
388  
389 
390  
391 
392     /**
393      * Returns the playback state of the AudioTrack instance.
394      * @see #PLAYSTATE_STOPPED
395      * @see #PLAYSTATE_PAUSED
396      * @see #PLAYSTATE_PLAYING
397      */
398     public int getPlayState() {
399         synchronized (mPlayStateLock) {            互斥锁用在这儿
400             return mPlayState;
401         }
402     }
403 
404  
405 
406 返回stream模式下。成功创建需要的buffer大小
407 
408 注意:这个大小不保证  音频加载后顺利播放。
409 
410 buffer 被数据重复填充的期望频率。需要选择更大的buffer值。
411 
412 例如,如果你想要动态设置一个比初始值大的AudioTrack资源采样率。要保证计算时,使用你想设置的
413 
414 最大采样率去计算buffer大小
415 
416     /**
417      * Returns the minimum buffer size required for the successful creation of an AudioTrack
418      * object to be created in the {@link #MODE_STREAM} mode. Note that this size doesn't
419      * guarantee a smooth playback under load, and higher values should be chosen according to
420      * the expected frequency at which the buffer will be refilled with additional data to play.
421      * For example, if you intend to dynamically set the source sample rate of an AudioTrack
422      * to a higher value than the initial source sample rate, be sure to configure the buffer size
423      * based on the highest planned sample rate.
424      * @param sampleRateInHz the source sample rate expressed in Hz.
425      * @param channelConfig describes the configuration of the audio channels.
426      *   See {@link AudioFormat#CHANNEL_OUT_MONO} and
427      *   {@link AudioFormat#CHANNEL_OUT_STEREO}
428      * @param audioFormat the format in which the audio data is represented.
429      *   See {@link AudioFormat#ENCODING_PCM_16BIT} and
430      *   {@link AudioFormat#ENCODING_PCM_8BIT}
431      * @return {@link #ERROR_BAD_VALUE} if an invalid parameter was passed,
432      *   or {@link #ERROR} if unable to query for output properties,
433      *   or the minimum buffer size expressed in bytes.
434      */
435     static public int getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat) {
436         int channelCount = 0;
437         switch(channelConfig) {                      计算信道数目
438         case AudioFormat.CHANNEL_OUT_MONO:
439         case AudioFormat.CHANNEL_CONFIGURATION_MONO:
440             channelCount = 1;
441             break;
442         case AudioFormat.CHANNEL_OUT_STEREO:
443         case AudioFormat.CHANNEL_CONFIGURATION_STEREO:
444             channelCount = 2;
445             break;
446         default:
447             if ((channelConfig & SUPPORTED_OUT_CHANNELS) != channelConfig) {
448                 // input channel configuration features unsupported channels
449                 loge("getMinBufferSize(): Invalid channel configuration.");
450                 return ERROR_BAD_VALUE;
451             } else {
452                 channelCount = Integer.bitCount(channelConfig);
453             }
454         }
455 
456         if ((audioFormat != AudioFormat.ENCODING_PCM_16BIT)       非法音频格式
457             && (audioFormat != AudioFormat.ENCODING_PCM_8BIT)) {
458             loge("getMinBufferSize(): Invalid audio format.");
459             return ERROR_BAD_VALUE;
460         }
461 
462         // sample rate, note these values are subject to change
463         if ( (sampleRateInHz < SAMPLE_RATE_HZ_MIN) || (sampleRateInHz > SAMPLE_RATE_HZ_MAX) ) {  非法采样率
464             loge("getMinBufferSize(): " + sampleRateInHz + " Hz is not a supported sample rate.");
465             return ERROR_BAD_VALUE;
466         }
467 
468         int size = native_get_min_buff_size(sampleRateInHz, channelCount, audioFormat);    调用native
469         if (size <= 0) {
470             loge("getMinBufferSize(): error querying hardware");
471             return ERROR;
472         }
473         else {
474             return size;
475         }
476     }
477 
478  
479 
480  
481 
482 
483 
484     /**    
485 
486 设置播放的开始位置(帧)。但是此时播放必须处于停止或暂停状态。
487 
488 并且必须是static 模式下。
489 
490  0 <= position <= buffer 可以容纳的帧总数
491 
492 
493      * Sets the playback head position.
494      * The track must be stopped or paused for the position to be changed,
495      * and must use the {@link #MODE_STATIC} mode.
496      * @param positionInFrames playback head position expressed in frames
497      * Zero corresponds to start of buffer.
498      * The position must not be greater than the buffer size in frames, or negative.
499      * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE},
500      *    {@link #ERROR_INVALID_OPERATION}
501      */
502     public int setPlaybackHeadPosition(int positionInFrames) {
503         if (mDataLoadMode == MODE_STREAM || mState != STATE_INITIALIZED ||
504                 getPlayState() == PLAYSTATE_PLAYING) {
505             return ERROR_INVALID_OPERATION;
506         }
507         if (!(0 <= positionInFrames && positionInFrames <= mNativeBufferSizeInFrames)) {
508             return ERROR_BAD_VALUE;
509         }
510         return native_set_position(positionInFrames);
511     }
512 
513  
514 
515 
516     /**
517 
518 设置循环起始位置,终止位置和循环次数。可以无限循环
519 
520 和上一方法一样。前提必须停止 或者暂停。且为static模式
521 
522 起始帧位置。0指代buffer的开头。 start  不能 >= buffer帧总数结束帧位置。end 不能 > buffer帧总数
523 
524 为了循环。 start < end
525 
526 start end 和 loopcount 可以都为0
527 
528 
529      * Sets the loop points and the loop count. The loop can be infinite.
530      * Similarly to setPlaybackHeadPosition,
531      * the track must be stopped or paused for the loop points to be changed,
532      * and must use the {@link #MODE_STATIC} mode.
533      * @param startInFrames loop start marker expressed in frames
534      * Zero corresponds to start of buffer.
535      * The start marker must not be greater than or equal to the buffer size in frames, or negative.
536      * @param endInFrames loop end marker expressed in frames
537      * The total buffer size in frames corresponds to end of buffer.
538      * The end marker must not be greater than the buffer size in frames.
539      * For looping, the end marker must not be less than or equal to the start marker,
540      * but to disable looping
541      * it is permitted for start marker, end marker, and loop count to all be 0.
542      * @param loopCount the number of times the loop is looped.
543      *    A value of -1 means infinite looping, and 0 disables looping.
544      * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE},
545      *    {@link #ERROR_INVALID_OPERATION}
546      */
547     public int setLoopPoints(int startInFrames, int endInFrames, int loopCount) {
548         if (mDataLoadMode == MODE_STREAM || mState != STATE_INITIALIZED ||
549                 getPlayState() == PLAYSTATE_PLAYING) {
550             return ERROR_INVALID_OPERATION;
551         }
552         if (loopCount == 0) {
553             ;   // explicitly allowed as an exception to the loop region range check
554         } else if (!(0 <= startInFrames && startInFrames < mNativeBufferSizeInFrames &&
555                 startInFrames < endInFrames && endInFrames <= mNativeBufferSizeInFrames)) {
556             return ERROR_BAD_VALUE;
557         }
558         return native_set_loop(startInFrames, endInFrames, loopCount);
559     }
560 
561  
562 
563 
564     /**    不让用只有子类让用。但是不建议有子类。所以此方法荒废
565      * Sets the initialization state of the instance. This method was originally intended to be used
566      * in an AudioTrack subclass constructor to set a subclass-specific post-initialization state.
567      * However, subclasses of AudioTrack are no longer recommended, so this method is obsolete.
568      * @param state the state of the AudioTrack instance
569      * @deprecated Only accessible by subclasses, which are not recommended for AudioTrack.
570      */
571     @Deprecated
572     protected void setState(int state) {
573         mState = state;
574     }
575 
576  
577 
578     //---------------------------------------------------------
579     // Transport control methods      以下三个方法格式基本相同   play  stop pause
580     //--------------------
581     /**
582      * Starts playing an AudioTrack.
583      * If track's creation mode is {@link #MODE_STATIC}, you must have called write() prior.    static 模式下,要先调用write()
584      *
585      * @throws IllegalStateException
586      */
587     public void play()
588     throws IllegalStateException {
589         if (mState != STATE_INITIALIZED) {
590             throw new IllegalStateException("play() called on uninitialized AudioTrack.");
591         }
592 
593         synchronized(mPlayStateLock) {
594             native_start();
595             mPlayState = PLAYSTATE_PLAYING;
596         }
597     }
598 
599     /**
601 stream模式下创建的实例,音频会在buffer写入的数据都被播放后才会停止。
602 
603 如果想让它立即停止需要调用  pause() 然后调用flush() 来清除buffer中没被播放的数据
604 * Stops playing the audio data. 605 * When used on an instance created in {@link #MODE_STREAM} mode, audio will stop playing 606 * after the last buffer that was written has been played. For an immediate stop, use 607 * {@link #pause()}, followed by {@link #flush()} to discard audio data that hasn't been played 608 * back yet. 609 * @throws IllegalStateException 610 */ 611 public void stop() 612 throws IllegalStateException { 613 if (mState != STATE_INITIALIZED) { 614 throw new IllegalStateException("stop() called on uninitialized AudioTrack."); 615 } 616 617 // stop playing 618 synchronized(mPlayStateLock) { 619 native_stop(); 620 mPlayState = PLAYSTATE_STOPPED; 621 } 622 } 623 624 /** 625 626 暂停。还没被播放的数据不会被消除。如果再调用play() 会继续播放。 627 628 使用flush() 清除缓存数据 629 630 631 * Pauses the playback of the audio data. Data that has not been played 632 * back will not be discarded. Subsequent calls to {@link #play} will play 633 * this data back. See {@link #flush()} to discard this data. 634 * 635 * @throws IllegalStateException 636 */ 637 public void pause() 638 throws IllegalStateException { 639 if (mState != STATE_INITIALIZED) { 640 throw new IllegalStateException("pause() called on uninitialized AudioTrack."); 641 } 642 //logd("pause()"); 643 644 // pause playback 645 synchronized(mPlayStateLock) { 646 native_pause(); 647 mPlayState = PLAYSTATE_PAUSED; 648 } 649 } 650 651 652 //--------------------------------------------------------- 653 // Audio data supply 654 //-------------------- 655 656 /** 657 658 清除队列中等待播放的音频数据。所有都会被清除。 659 660 如果没有停止或暂停。或者当前模式不是stream。操作会失败 661 662 * Flushes the audio data currently queued for playback. Any data that has 663 * not been played back will be discarded. No-op if not stopped or paused, 664 * or if the track's creation mode is not {@link #MODE_STREAM}. 665 */ 666 public void flush() { 667 if (mState == STATE_INITIALIZED) { 668 // flush the data in native layer 669 native_flush(); 670 } 671 672 } 673 674 675 676 677 678 //-------------------------------------------------------------------------- 679 // Audio effects management      音频效果管理 680 //-------------------- 681 682 /** 683 684 为AudioTrack增加一种辅助效果。一种典型辅助效果是混响,可以应用于所有音频资源。导致 685 686 对这种辅助效果 造成一个具有确切数值的影响。这个数值被setAuxEffectSendLevel()指定 687 688 创建一个辅助效果后,通过AudioEffect.gerId()来获得它的ID,在使用这个ID调用此方法。 689 690 当你想去掉这种辅助效果。再调一次这个方法,此时ID传null 691 692 693 * Attaches an auxiliary effect to the audio track. A typical auxiliary 694 * effect is a reverberation effect which can be applied on any sound source 695 * that directs a certain amount of its energy to this effect. This amount 696 * is defined by setAuxEffectSendLevel(). 697 * {@see #setAuxEffectSendLevel(float)}. 698 * <p>After creating an auxiliary effect (e.g. 699 * {@link android.media.audiofx.EnvironmentalReverb}), retrieve its ID with 700 * {@link android.media.audiofx.AudioEffect#getId()} and use it when calling 701 * this method to attach the audio track to the effect. 702 * <p>To detach the effect from the audio track, call this method with a 703 * null effect id. 704 * 705 * @param effectId system wide unique id of the effect to attach    这个效果id,在系统内是唯一的 706 * @return error code or success, see {@link #SUCCESS}, 707 * {@link #ERROR_INVALID_OPERATION}, {@link #ERROR_BAD_VALUE} 708 */ 709 public int attachAuxEffect(int effectId) { 710 if (mState == STATE_UNINITIALIZED) { 711 return ERROR_INVALID_OPERATION; 712 } 713 return native_attachAuxEffect(effectId); 714 } 715 716 /** 717 718 设置辅助效果的level。从0.0f 到1.0f。超出会被卡掉。默认为0.0f 719 720 所以即使已经指定了效果。也需要调用这个方法,效果才会被应用 721 722 注意:这个值是个未加工过的度量。UI操作需要被对数拉伸 723 724 audio 框架中的增益 从-72dB到0dB。所以从线性UI的输入x到这个level的一个合适的转换为: 725 726 x == 0 则 level==0 727 728 0<x<=R 则 level = 10^(72*(x-R)/20/R) 729 730 731 * Sets the send level of the audio track to the attached auxiliary effect 732 * {@link #attachAuxEffect(int)}. The level value range is 0.0f to 1.0f. 733 * Values are clamped to the (0.0f, 1.0f) interval if outside this range. 734 * <p>By default the send level is 0.0f, so even if an effect is attached to the player 735 * this method must be called for the effect to be applied. 736 * Note that the passed level value is a raw scalar. UI controls should be scaled logarithmically: 737 738 the gain applied by audio framework ranges from -72dB to 0dB, so an appropriate conversion from 739 740 linear UI input x to level is: x == 0 -> level = 0 0 < x <= R -> level = 10^(72*(x-R)/20/R) 741 * 742 * @param level send level scalar 743 * @return error code or success, see {@link #SUCCESS}, 744 * {@link #ERROR_INVALID_OPERATION} 745 */ 746 public int setAuxEffectSendLevel(float level) { 747 if (mState == STATE_UNINITIALIZED) { 748 return ERROR_INVALID_OPERATION; 749 } 750 // clamp the level 751 if (level < getMinVolume()) { 752 level = getMinVolume(); 753 } 754 if (level > getMaxVolume()) { 755 level = getMaxVolume(); 756 } 757 native_setAuxEffectSendLevel(level); 758 return SUCCESS; 759 }

 

posted @ 2015-01-27 20:52  马小豆包  阅读(4790)  评论(0编辑  收藏  举报