2011.08.12(4)——— android AudioTrack 不能播放awr
http://blog.sina.com.cn/s/blog_7cb539590100qkcr.html
http://blog.csdn.net/chenjie19891104/article/details/6333553
http://blog.csdn.net/hellogv/article/details/6026455
我用AudioTrack播放MP3 awr都是不成功的 只会传出一堆的噪声,但是播放wav是没有问题的,因为wav就相当于原生态的pcm
这时候 我有两个选择
1、从3gp网站上下载awr解码算法 用jni调用 把awr解码成pcm
2、可以用AudioRecord来录制pcm 并用AudioTrack来播放
我用的时后者
package com.lp;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import android.app.Activity;import android.media.AudioFormat;import android.media.AudioManager;import android.media.AudioRecord;import android.media.AudioTrack;import android.media.MediaRecorder;import android.os.AsyncTask;import android.os.Bundle;import android.os.Environment;import android.util.Log;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.TextView;public class MainActivity extends Activity implements OnClickListener{ private TextView stateView; private Button btnStart,btnStop,btnPlay,btnFinish; private RecordTask recorder; private PlayTask player; private File audioFile; private boolean isRecording=true, isPlaying=false; private int frequence = 44100; private int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO; private int audioEncoding = AudioFormat.ENCODING_PCM_16BIT; public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main_pcm); stateView = (TextView)this.findViewById(R.id.view_state); stateView.setText("准备开始"); btnStart = (Button)this.findViewById(R.id.btn_start); btnStop = (Button)this.findViewById(R.id.btn_stop); btnPlay = (Button)this.findViewById(R.id.btn_play); btnFinish = (Button)this.findViewById(R.id.btn_finish); btnFinish.setText("停止播放"); btnPlay.setEnabled(false); btnFinish.setEnabled(false); btnStart.setOnClickListener(this); btnStop.setOnClickListener(this); btnPlay.setOnClickListener(this); btnFinish.setOnClickListener(this); // File fpath = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/11");// fpath.mkdirs(); try { //audioFile = File.createTempFile("test", ".pcm", fpath); audioFile = new File("/mnt/sdcard/1.pcm"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void onClick(View v){ int id = v.getId(); switch(id){ case R.id.btn_start: recorder = new RecordTask(); recorder.execute(); break; case R.id.btn_stop: this.isRecording = false; System.out.println(isRecording); break; case R.id.btn_play: player = new PlayTask(); player.execute(); break; case R.id.btn_finish: this.isPlaying = false; break; } } class RecordTask extends AsyncTask<Void, Integer, Void>{ @Override protected Void doInBackground(Void... arg0) { //isRecording = true; try { //开通输出流到指定的文件 DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(audioFile))); //FileOutputStream fos = new FileOutputStream(audioFile); //根据定义好的几个配置,来获取合适的缓冲大小 int bufferSize = AudioRecord.getMinBufferSize(frequence, channelConfig, audioEncoding); //实例化AudioRecord AudioRecord record = new AudioRecord(MediaRecorder.AudioSource.MIC, frequence, channelConfig, audioEncoding, bufferSize); //定义缓冲 short[] buffer = new short[bufferSize]; //byte[] buffer = new byte[bufferSize]; //开始录制 record.startRecording(); int r = 0; //存储录制进度 //定义循环,根据isRecording的值来判断是否继续录制 while(isRecording){ //从bufferSize中读取字节,返回读取的short个数 //这里老是出现buffer overflow,不知道是什么原因,试了好几个值,都没用,TODO:待解决 int bufferReadResult = record.read(buffer, 0, buffer.length); //循环将buffer中的音频数据写入到OutputStream中 for(int i=0; i<bufferReadResult; i++){ dos.writeShort(buffer[i]); } // byte[] tmpBuf = new byte[bufferReadResult]; // System.arraycopy(buffer, 0, tmpBuf, 0, bufferReadResult); // fos.write(tmpBuf, 0, bufferReadResult);// fos.flush(); publishProgress(new Integer(r)); //向UI线程报告当前进度 r++; //自增进度值 } //录制结束 record.stop(); System.out.println("The File length::"+audioFile.length()); dos.close(); //fos.close(); } catch (Exception e) { // TODO: handle exception } return null; } //当在上面方法中调用publishProgress时,该方法触发,该方法在UI线程中被执行 protected void onProgressUpdate(Integer...progress){ stateView.setText(progress[0].toString()); } protected void onPostExecute(Void result){ btnStop.setEnabled(false); btnStart.setEnabled(true); btnPlay.setEnabled(true); btnFinish.setEnabled(false); } protected void onPreExecute(){ //stateView.setText("正在录制"); btnStart.setEnabled(false); btnPlay.setEnabled(false); btnFinish.setEnabled(false); btnStop.setEnabled(true); } } class PlayTask extends AsyncTask<Void, Integer, Void>{ @Override protected Void doInBackground(Void... arg0) { isPlaying = true; int bufferSize = AudioTrack.getMinBufferSize(frequence, channelConfig, audioEncoding); short[] buffer = new short[bufferSize/4]; //byte[] buffer = new byte[bufferSize]; try { //定义输入流,将音频写入到AudioTrack类中,实现播放 DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream(audioFile))); //FileInputStream fis = new FileInputStream(audioFile); //实例AudioTrack AudioTrack track = new AudioTrack(AudioManager.STREAM_MUSIC, frequence, channelConfig, audioEncoding, bufferSize, AudioTrack.MODE_STREAM); //开始播放 track.play(); //由于AudioTrack播放的是流,所以,我们需要一边播放一边读取 while(isPlaying && dis.available()>0){ int i = 0; while(dis.available()>0 && i<buffer.length){ buffer[i] = dis.readShort(); i++; } //然后将数据写入到AudioTrack中 track.write(buffer, 0, buffer.length); } //播放结束 track.stop(); dis.close(); } catch (Exception e) { // TODO: handle exception } return null; } protected void onPostExecute(Void result){ btnPlay.setEnabled(true); btnFinish.setEnabled(false); btnStart.setEnabled(true); btnStop.setEnabled(false); } protected void onPreExecute(){ //stateView.setText("正在播放"); btnStart.setEnabled(false); btnStop.setEnabled(false); btnPlay.setEnabled(false); btnFinish.setEnabled(true); } }}
对了 别忘了权限
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.RECORD_AUDIO" />
注意:其实这种方法也是不可取的 因为保存的PCM原始音频 没有压缩 所以非常大,一般还是用awr来传输 所以还是需要解码的