• 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 }
  • 相关阅读:
    获得CCNA和CCNP及CCIE认证的必备条件和有效期绍
    Js6利用class创建类
    Js6利用class创建类
    权益证明机制 (PoS):权益决定验证权,谁更有钱谁发言
    关于共识机制的一些想法
    有向无环图 (DAG) 技术:超越区块链的分布式账本
    寻找一种易于理解的一致性算法(扩展版)
    如何使用python语言中的方法对列表进行增删改操作
    如何操作python语言中的元素并计算相应的属性
    如何操作python语言中的列表并获取对应的元素
  • 原文地址:https://www.cnblogs.com/maxiaodoubao/p/4253924.html
Copyright © 2020-2023  润新知