我用AudioTrack播放MP3 awr都是不成功的 隻會傳出一堆的噪聲,但是播放wav是沒有問題的,因為wav就相當於原生態的pcm
這時候 我有兩個選擇
1、從3gp網站上下載awr解碼算法 用jni調用 把awr解碼成pcm
2、可以用AudioRecord來錄制pcm 並用AudioTrack來播放
我用的時後者
Java代碼
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);
}
}
}
對瞭 別忘瞭權限
Java代碼
<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" />