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

AudioTrack的更多相关文章

  1. Android音频开发之AudioTrack实时播放

    前言: 其实在Android中录音可以用MediaRecord录音,操作比较简单.但是不能对音频进行处理.考虑到项目中做的是实时语音只能选择AudioRecord进行录音.然后实时播放也只能采用Aud ...

  2. Android使用AudioTrack发送红外信号

    最近要做一个项目,利用手机的耳机口输出红外信号,从而把手机变成红外遥控器,信号处理的知识基本都还给老师了,刚开始真的挺头疼.找了不少资料研究了一下,总算有点心得,在这里做个备忘. 一.音频信号输出原理 ...

  3. MediaPlayer中创建AudioTrack的过程

    使用MediaPlayer播放音视频时,会创建AudioTrack对象用于播放音频数据.下面就来看看MediaPlayer创建AudioTrack的过程: 1.创建AudioTrack对象MediaP ...

  4. MediaPlayer和AudioTrack播放Audio的区别与联系

    转自http://blog.csdn.net/ameyume/article/details/7618820 播放声音可以用MediaPlayer和AudioTrack,两者都提供了java API供 ...

  5. Android深入浅出之 AudioTrack分析

    Android深入浅出之Audio 第一部分 AudioTrack分析 一 目的 本文的目的是通过从Audio系统来分析Android的代码,包括Android自定义的那套机制和一些常见类的使用,比如 ...

  6. [Android] AudioTrack::start

    AudioTrack的start方法用于实现Android的音频输出,start究竟做了什么?回顾一下上一小节createTrack_l的最后部分,通过binder返回了一个Track的句柄,并以被保 ...

  7. [Android] AudioTrack实例

    AudioTrack在Android系统中是用于PCM数据的混音.播放,并不涉及到音频的解码.因此MP3这类经过编码的音频格式文件不能直接通过AudioTrack正确地播放,AudioTrack只能播 ...

  8. 使用AudioTrack播放PCM音频数据(android)

    众所周知,Android的MediaPlayer包含了Audio和video的播放功能,在Android的界面上,Music和Video两个应用程序都是调用MediaPlayer实现的.MediaPl ...

  9. Android Audio System 之一:AudioTrack如何与AudioFlinger

    Android Framework的音频子系统中,每一个音频流对应着一个AudioTrack类的一个实例,每个AudioTrack会在创建时注册到 AudioFlinger中,由AudioFlinge ...

  10. Android音频: 怎样使用AudioTrack播放一个WAV格式文件?

    翻译 By Long Luo 原文链接:Android Audio: Play a WAV file on an AudioTrack 译者注: 1. 因为这是技术文章,所以有些词句使用原文,表达更准 ...

随机推荐

  1. JavaWeb学习总结(一)JavaWeb入门与Tomcat

    一.常见软件系统体系结构B/S.C/S 1. C/S C/S结构即客户端/服务器(Client/Server),例如QQ: 需要编写服务器端程序,以及客户端程序,例如我们安装的就是QQ的客户端程序: ...

  2. IT从业人员必看的10个论坛(转)

    IT方面的论坛太多了,有综合,有专业,有行业,在各个论坛里混了几年,体会颇深,以前是论坛哪里人多,往哪里去,新浪论坛,网易是经常去的,人多啊,好几十万,去了以后才发现没有意思,没有共同的语言,于是逛专 ...

  3. LeetCode OJ:Delete Node in a Linked List(链表节点删除)

    Write a function to delete a node (except the tail) in a singly linked list, given only access to th ...

  4. python 生成唯一字符串UUID与MD5

    1 Python使用UUID库生成唯一ID UUID是128位的全局唯一标识符,通常由32字节的字符串表示,保证时间和空间的唯一性 通过MAC地址.时间戳.命名空间.随机数.伪随机数来保证生成ID的唯 ...

  5. Leetcode 969. Pancake Sorting

    每次找到当前最大数,转两下把最大数转到最右边.重复这个操作,直到都转完. 时间复杂度O(n**2) class Solution(object): def pancakeSort(self, A): ...

  6. tag问题

  7. Redis的一些常用命令操作

    五种 基本数据 类型 以及操作命令操作命令的网址:http://doc.redisfans.com/ 一.在可视化界面上打开命令窗口 二.打开后就是这样子 三.命令操作---查询.删除.字符串 1.k ...

  8. webpack 单页面应用实战

    这篇文章将介绍如何利用 webpack 进行单页面应用的开发,算是我在实际开发中的一些心得和体会,在这里给大家做一个分享.webpack 的介绍这里就不多说了,可以直接去官网查看. 关于这个单页面应用 ...

  9. 尚硅谷Java视频教程导航(学习路线图)

    最近很火,上去看了看,对于入门的人还是有点作用的,做个记号,留着以后学习. Java视频教程下载导航(学习路线图) 网站地址:http://www.atguigu.com/download.shtml

  10. ubuntu tftp server config

    1.安装tftp-server sudo apt-get install tftpd-hpa sudo apt-get install tftp-hpa(如果不需要客户端可以不安装) tftp-hpa ...