Android AudioTrack/AudioRecord <1>
刚才纠正了一个jni第七节一个错误,昨晚一个晚上没睡着啊.
为什么要看看AudioTrack和AudioRecord,没有为什么,因为不看看,会死人的.
AudioTrack API :http://developer.android.com/reference/android/media/AudioTrack.html
<1> : AudioTrack构造函数有两种:第二种我很少用.下面第一种:
public AudioTrack (int streamType, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes, int mode)
第一个参数:streamType : 可以去查看AudioManager名下的常量STREAM_VOICE_CALL,STREAM_MUSIC,STREAM_NOTIFICATION等等;
第二个参数:sampleRateInHz : 采样率,一般使用44100,当然还有16000等等;
第三个参数:channelConfig : 通道配置AudioFormat.CHANNEL_OUT_MONO/AudioFormat.CHANNEL_OUT_STEREO;
第四个参数:bufferSizeInBytes : 可以自行根据实际情况配置,也可以通过getMinBufferSize(int, int, int)获取系统能够给出的.
<2> : 初始化如下:
private AudioTrack mPlayer; private int mPlayBufferSize; private final int mSampleRateInHz=44100; ... mPlayBufferSize = AudioTrack.getMinBufferSize(mSampleRateInHz, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT); mPlayer = new AudioTrack(AudioManager.STREAM_MUSIC, mSampleRateInHz, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, mPlayBufferSize, AudioTrack.MODE_STREAM);
开始准备播放:
mPlayer.play();
AudioTrack是通过向其写入数据流的形式进行播放:
数据流来源:
<a> : 网络;
<b> : 本地存储介质:要读取外部存储介质权限
File mFile=new File(Environment.getExternalStorageDirectory(),"yourwavname.wav"); try { FileInputStream fis=new FileInputStream(mFile); try { while((length=fis.read(stream_buffer, 0, length))!=-1){ mPlayer.write(stream_buffer, 0, length); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } catch (FileNotFoundException e1) { // TODO Auto-generated catch block e1.printStackTrace(); }
<c> : android工程raw文件夹内的wav等文件.
InputStream is=this.getResources().openRawResource(R.raw.dialtone); try { while((length=is.read(stream_buffer))!=-1){ mPlayer.write(stream_buffer, 0, length); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace();
<d> : 其他等等.
<3> : 停止播放:
if(mPlayer!=null){ mPlayer.stop(); mPlayer.release(); }
也可以再加一个判断播放状态:
getPlayState ()
<4> : 下面给出全部demo :
package com.example.audiodemo01; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import android.media.AudioFormat; import android.media.AudioManager; import android.media.AudioTrack; import android.os.Bundle; import android.os.Environment; import android.app.Activity; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class MainActivity extends Activity implements OnClickListener{ private AudioTrack mPlayer; private int mPlayBufferSize; private final int mSampleRateInHz=44100; private Button mPlayBtn; private Button mStopBtn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mPlayBufferSize = AudioTrack.getMinBufferSize(mSampleRateInHz, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT); mPlayer = new AudioTrack(AudioManager.STREAM_MUSIC, mSampleRateInHz, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, mPlayBufferSize, AudioTrack.MODE_STREAM); mPlayer.play(); mPlayBtn=(Button)findViewById(R.id.button1); mPlayBtn.setOnClickListener(this); mStopBtn=(Button)findViewById(R.id.button2); mStopBtn.setOnClickListener(this); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public void onClick(View arg0) { // TODO Auto-generated method stub int id; id=arg0.getId(); switch(id){ case R.id.button1: new Thread(new Runnable(){ @Override public void run() { // TODO Auto-generated method stub playWav(); } }).start(); break; case R.id.button2: if(mPlayer!=null){ mPlayer.stop(); mPlayer.release(); } break; } } private void playWav(){ byte[] stream_buffer=new byte[44100]; int length = 0; /*File mFile=new File(Environment.getExternalStorageDirectory(),"yourwavname.wav"); try { FileInputStream fis=new FileInputStream(mFile); try { while((length=fis.read(stream_buffer, 0, length))!=-1){ mPlayer.write(stream_buffer, 0, length); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } catch (FileNotFoundException e1) { // TODO Auto-generated catch block e1.printStackTrace(); }*/ InputStream is=this.getResources().openRawResource(R.raw.dialtone); try { while((length=is.read(stream_buffer))!=-1){ mPlayer.write(stream_buffer, 0, length); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
<5> : 上面不够优化,将初始化等所有操作都放到一个单独的线程中:
package com.example.audiodemo01; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import android.media.AudioFormat; import android.media.AudioManager; import android.media.AudioTrack; import android.os.Bundle; import android.os.Environment; import android.app.Activity; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class MainActivity extends Activity implements OnClickListener { private AudioTrack mPlayer; private int mPlayBufferSize; private final int mSampleRateInHz = 44100; private Button mPlayBtn; private Button mStopBtn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mPlayBtn = (Button) findViewById(R.id.button1); mPlayBtn.setOnClickListener(this); mStopBtn = (Button) findViewById(R.id.button2); mStopBtn.setOnClickListener(this); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public void onClick(View arg0) { // TODO Auto-generated method stub int id; id = arg0.getId(); switch (id) { case R.id.button1: Thread playThread = new Thread(new PlayThread(), "play"); playThread.start(); break; case R.id.button2: stopPlay(); break; } } private void playInit() { mPlayBufferSize = AudioTrack.getMinBufferSize(mSampleRateInHz, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT); mPlayer = new AudioTrack(AudioManager.STREAM_MUSIC, mSampleRateInHz, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, mPlayBufferSize, AudioTrack.MODE_STREAM); mPlayer.play(); } private void playWav() { byte[] stream_buffer = new byte[44100]; int length = 0; /* * File mFile=new * File(Environment.getExternalStorageDirectory(),"yourwavname.wav"); * try { FileInputStream fis=new FileInputStream(mFile); try { * while((length=fis.read(stream_buffer, 0, length))!=-1){ * mPlayer.write(stream_buffer, 0, length); } } catch (IOException e) { * // TODO Auto-generated catch block e.printStackTrace(); } } catch * (FileNotFoundException e1) { // TODO Auto-generated catch block * e1.printStackTrace(); } */ InputStream is = this.getResources().openRawResource(R.raw.dialtone); try { while ((length = is.read(stream_buffer)) != -1) { mPlayer.write(stream_buffer, 0, length); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } private void stopPlay() { int status; if (mPlayer != null) { mPlayer.stop(); mPlayer.release(); mPlayer = null; } } private class PlayThread implements Runnable { @Override public void run() { // TODO Auto-generated method stub playInit(); playWav(); } } }
<6> : 将生命变量也放在线程中,即每次播放时重新创建新的播放器对象,可能对AudioTrack做事多余的,但是个人还是比较推荐这种方式.
推荐下面:
package com.example.audiodemo01; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import android.media.AudioFormat; import android.media.AudioManager; import android.media.AudioTrack; import android.os.Bundle; import android.os.Environment; import android.app.Activity; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class MainActivity extends Activity implements OnClickListener { private int mPlayBufferSize; private final int mSampleRateInHz = 44100; private Button mPlayBtn; private Button mStopBtn; private boolean mStopBool=false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mPlayBtn = (Button) findViewById(R.id.button1); mPlayBtn.setOnClickListener(this); mStopBtn = (Button) findViewById(R.id.button2); mStopBtn.setOnClickListener(this); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public void onClick(View arg0) { // TODO Auto-generated method stub int id; id = arg0.getId(); switch (id) { case R.id.button1: Thread playThread = new Thread(new PlayThread(), "play"); playThread.start(); break; case R.id.button2: stopPlay(); break; } } private void stopPlay(){ mStopBool=true; } private void playWav() { byte[] stream_buffer = new byte[44100]; int length = 0; mStopBool=false; AudioTrack mPlayer = null; mPlayBufferSize = AudioTrack.getMinBufferSize(mSampleRateInHz, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT); mPlayer = new AudioTrack(AudioManager.STREAM_MUSIC, mSampleRateInHz, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, mPlayBufferSize, AudioTrack.MODE_STREAM); mPlayer.play(); /* * File mFile=new * File(Environment.getExternalStorageDirectory(),"yourwavname.wav"); * try { FileInputStream fis=new FileInputStream(mFile); try { * while((length=fis.read(stream_buffer, 0, length))!=-1){ * mPlayer.write(stream_buffer, 0, length); } } catch (IOException e) { * // TODO Auto-generated catch block e.printStackTrace(); } } catch * (FileNotFoundException e1) { // TODO Auto-generated catch block * e1.printStackTrace(); } */ InputStream is = this.getResources().openRawResource(R.raw.dialtone); try { while ((length = is.read(stream_buffer)) != -1) { mPlayer.write(stream_buffer, 0, length); if(mStopBool){ if (mPlayer != null) { mPlayer.stop(); mPlayer.release(); mPlayer = null; } break; } } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } if (mPlayer != null) { mPlayer.stop(); mPlayer.release(); mPlayer = null; } } private class PlayThread implements Runnable { @Override public void run() { // TODO Auto-generated method stub playWav(); } } }
其中不涉及AudioTrack不组织了.
上面playWav()方法中文件流没关闭,添加上下面一句:
is.close();
<7> : 上面再Thread线程中实现播放音乐,在网上看到其他人采用AsyncTask,同样稍微将上面修改一下,demo如下:
package com.example.audiodemo01; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import android.media.AudioFormat; import android.media.AudioManager; import android.media.AudioTrack; import android.os.AsyncTask; import android.os.Bundle; import android.os.Environment; import android.app.Activity; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class MainActivity extends Activity implements OnClickListener { private int mPlayBufferSize; private final int mSampleRateInHz = 44100; private Button mPlayBtn; private Button mStopBtn; private boolean mStopBool=false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mPlayBtn = (Button) findViewById(R.id.button1); mPlayBtn.setOnClickListener(this); mStopBtn = (Button) findViewById(R.id.button2); mStopBtn.setOnClickListener(this); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public void onClick(View arg0) { // TODO Auto-generated method stub int id; id = arg0.getId(); switch (id) { case R.id.button1: // Thread playThread = new Thread(new PlayThread(), "play"); // playThread.start(); PlayTask task=new PlayTask(); task.execute(); break; case R.id.button2: stopPlay(); break; } } private void stopPlay(){ mStopBool=true; } private void playWav() { byte[] stream_buffer = new byte[44100]; int length = 0; mStopBool=false; AudioTrack mPlayer = null; mPlayBufferSize = AudioTrack.getMinBufferSize(mSampleRateInHz, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT); mPlayer = new AudioTrack(AudioManager.STREAM_MUSIC, mSampleRateInHz, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, mPlayBufferSize, AudioTrack.MODE_STREAM); mPlayer.play(); /* * File mFile=new * File(Environment.getExternalStorageDirectory(),"yourwavname.wav"); * try { FileInputStream fis=new FileInputStream(mFile); try { * while((length=fis.read(stream_buffer, 0, length))!=-1){ * mPlayer.write(stream_buffer, 0, length); } } catch (IOException e) { * // TODO Auto-generated catch block e.printStackTrace(); } } catch * (FileNotFoundException e1) { // TODO Auto-generated catch block * e1.printStackTrace(); } */ InputStream is = this.getResources().openRawResource(R.raw.dialtone); try { while ((length = is.read(stream_buffer)) != -1) { mPlayer.write(stream_buffer, 0, length); if(mStopBool){ if (mPlayer != null) { mPlayer.stop(); mPlayer.release(); mPlayer = null; } break; } } is.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } if (mPlayer != null) { mPlayer.stop(); mPlayer.release(); mPlayer = null; } } private class PlayThread implements Runnable { @Override public void run() { // TODO Auto-generated method stub playWav(); } } private class PlayTask extends AsyncTask<Void,Integer,Void>{ @Override protected Void doInBackground(Void... arg0) { // TODO Auto-generated method stub playWav(); return null; } } }
<8> : 在app应用中会在service中进行播放音乐,Activity向其发送广播,附带"命令"进行控制,不过这里不想去回忆一下service如何开发.

浙公网安备 33010602011771号