一、AudioTrack 基本使用
AudioTrack 类可以完成Android平台上音频数据的输出任务。AudioTrack有两种数据加载模式(MODE_STREAM和MODE_STATIC),对应的是数据加载模式和音频流类型, 对应着两种完全不同的使用场景。
- MODE_STREAM:在这种模式下,通过write一次次把音频数据写到AudioTrack中。这和平时通过write系统调用往文件中写数据类似,但这种工作方式每次都需要把数据从用户提供的Buffer中拷贝到AudioTrack内部的Buffer中,这在一定程度上会使引入延时。为解决这一问题,AudioTrack就引入了第二种模式。
- MODE_STATIC:这种模式下,在play之前只需要把所有数据通过一次write调用传递到AudioTrack中的内部缓冲区,后续就不必再传递数据了。这种模式适用于像铃声这种内存占用量较小,延时要求较高的文件。但它也有一个缺点,就是一次write的数据不能太多,否则系统无法分配足够的内存来存储全部数据。
1.1 MODE_STATIC模式
MODE_STATIC模式输出音频的方式如下(注意:如果采用STATIC模式,须先调用write写数据,然后再调用play。):
public class AudioTrackPlayerDemoActivity extends Activity implements OnClickListener {</span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">final</span> String TAG = "AudioTrackPlayerDemoActivity"<span style="color: #000000;">; </span><span style="color: #0000ff;">private</span><span style="color: #000000;"> Button button; </span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">byte</span><span style="color: #000000;">[] audioData; </span><span style="color: #0000ff;">private</span><span style="color: #000000;"> AudioTrack audioTrack; @Override </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> onCreate(Bundle savedInstanceState) { </span><span style="color: #0000ff;">super</span><span style="color: #000000;">.onCreate(savedInstanceState); </span><span style="color: #0000ff;">super</span><span style="color: #000000;">.setContentView(R.layout.main); </span><span style="color: #0000ff;">this</span>.button = (Button) <span style="color: #0000ff;">super</span><span style="color: #000000;">.findViewById(R.id.play); </span><span style="color: #0000ff;">this</span>.button.setOnClickListener(<span style="color: #0000ff;">this</span><span style="color: #000000;">); </span><span style="color: #0000ff;">this</span>.button.setEnabled(<span style="color: #0000ff;">false</span><span style="color: #000000;">); </span><span style="color: #0000ff;">new</span> AsyncTask<Void, Void, Void><span style="color: #000000;">() { @Override </span><span style="color: #0000ff;">protected</span><span style="color: #000000;"> Void doInBackground(Void... params) { </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> { InputStream in </span>=<span style="color: #000000;"> getResources().openRawResource(R.raw.ding); </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> { ByteArrayOutputStream out </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> ByteArrayOutputStream( </span>264848<span style="color: #000000;">); </span><span style="color: #0000ff;">for</span> (<span style="color: #0000ff;">int</span> b; (b = in.read()) != -1<span style="color: #000000;">;) { out.write(b); } Log.d(TAG, </span>"Got the data"<span style="color: #000000;">); audioData </span>=<span style="color: #000000;"> out.toByteArray(); } </span><span style="color: #0000ff;">finally</span><span style="color: #000000;"> { in.close(); } } </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (IOException e) { Log.wtf(TAG, </span>"Failed to read"<span style="color: #000000;">, e); } </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">null</span><span style="color: #000000;">; } @Override </span><span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> onPostExecute(Void v) { Log.d(TAG, </span>"Creating track..."<span style="color: #000000;">); button.setEnabled(</span><span style="color: #0000ff;">true</span><span style="color: #000000;">); Log.d(TAG, </span>"Enabled button"<span style="color: #000000;">); } }.execute(); } </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> onClick(View view) { </span><span style="color: #0000ff;">this</span>.button.setEnabled(<span style="color: #0000ff;">false</span><span style="color: #000000;">); </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.releaseAudioTrack(); </span><span style="color: #0000ff;">this</span>.audioTrack = <span style="color: #0000ff;">new</span> AudioTrack(AudioManager.STREAM_MUSIC, 44100<span style="color: #000000;">, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT, audioData.length, AudioTrack.MODE_STATIC); Log.d(TAG, </span>"Writing audio data..."<span style="color: #000000;">); </span><span style="color: #0000ff;">this</span>.audioTrack.write(audioData, 0<span style="color: #000000;">, audioData.length); Log.d(TAG, </span>"Starting playback"<span style="color: #000000;">); audioTrack.play(); Log.d(TAG, </span>"Playing"<span style="color: #000000;">); </span><span style="color: #0000ff;">this</span>.button.setEnabled(<span style="color: #0000ff;">true</span><span style="color: #000000;">); } </span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> releaseAudioTrack() { </span><span style="color: #0000ff;">if</span> (<span style="color: #0000ff;">this</span>.audioTrack != <span style="color: #0000ff;">null</span><span style="color: #000000;">) { Log.d(TAG, </span>"Stopping"<span style="color: #000000;">); audioTrack.stop(); Log.d(TAG, </span>"Releasing"<span style="color: #000000;">); audioTrack.release(); Log.d(TAG, </span>"Nulling"<span style="color: #000000;">); } } </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> onPause() { </span><span style="color: #0000ff;">super</span><span style="color: #000000;">.onPause(); </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.releaseAudioTrack(); }