昨天在研究录音问题,看到了android自带的MediaRecorder,不难(对比speex,给speex跪哭了),吃下来了,跟大家分享一下。
从android API上扣了一张概要图,这张图清晰的说明了MediaRecorder类的用法以及流程。
MediaRecorder recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(PATH_NAME);
recorder.prepare();
recorder.start(); // Recording is now started
...
recorder.stop();
recorder.reset(); // You can reuse the object by going back to setAudioSource() step
recorder.release(); // Now the object cannot be reused
对以上的流程进行个总结,
MediaRecorder首先实例化个对象后,首先初始化从麦克风采集声音
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
然后,初始化内容输出格式、音频编码方式、音频存放地点
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(PATH_NAME);
最后开始预期准备,录制。
recorder.prepare();
recorder.start(); // Recording is now started
用例子来把这个流程走一遍吧。实现了按住按钮录音,松开结束录音功能,语音保存至sd卡。
package demo.com;
import java.io.File;
import java.io.IOException;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.media.MediaRecorder;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.view.WindowManager.LayoutParams;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
public class RecordButton extends Button {
public RecordButton(Context context) {
super(context);
init();
}
public RecordButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public RecordButton(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public void setSavePath(String path) {
mFileName = path;
}
public void setOnFinishedRecordListener(OnFinishedRecordListener listener) {
finishedListener = listener;
}
private String mFileName = null;
private OnFinishedRecordListener finishedListener;
private static final int MIN_INTERVAL_TIME = 2000;// 2s
private long startTime;
private Dialog recordIndicator;
private static int[] res = { R.drawable.mic_2, R.drawable.mic_3,
R.drawable.mic_4, R.drawable.mic_5 };
private static ImageView view;
private MediaRecorder recorder;
private ObtainDecibelThread thread;
private Handler volumeHandler;
private void init() {
volumeHandler = new ShowVolumeHandler();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (mFileName == null)
return false;
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
initDialogAndStartRecord();
break;
case MotionEvent.ACTION_UP:
finishRecord();
break;
case MotionEvent.ACTION_CANCEL:// 当手指移动到view外面,会cancel
cancelRecord();
break;
}
return true;
}
private void initDialogAndStartRecord() {
startTime = System.currentTimeMillis();
recordIndicator = new Dialog(getContext(),
R.style.like_toast_dialog_style);
view = new ImageView(getContext());
view.setImageResource(R.drawable.mic_2);
recordIndicator.setContentView(view, new LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
recordIndicator.setOnDismissListener(onDismiss);
LayoutParams lp = recordIndicator.getWindow().getAttributes();
lp.gravity = Gravity.CENTER;
startRecording();
recordIndicator.show();
}
private void finishRecord() {
stopRecording();
recordIndicator.dismiss();
long intervalTime = System.currentTimeMillis() - startTime;
if (intervalTime < MIN_INTERVAL_TIME) {
Toast.makeText(getContext(), "时间太短!", Toast.LENGTH_SHORT).show();
File file = new File(mFileName);
file.delete();
return;
}
if (finishedListener != null)
finishedListener.onFinishedRecord(mFileName);
}
private void cancelRecord() {
stopRecording();
recordIndicator.dismiss();
Toast.makeText(getContext(), "取消录音!", Toast.LENGTH_SHORT).show();
File file = new File(mFileName);
file.delete();
}
private void startRecording() {
recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(mFileName);
try {
recorder.prepare();
} catch (IOException e) {
e.printStackTrace();
}
recorder.start();
thread = new ObtainDecibelThread();
thread.start();
}
private void stopRecording() {
if (thread != null) {
thread.exit();
thread = null;
}
if (recorder != null) {
recorder.stop();
recorder.release();
recorder = null;
}
}
private class ObtainDecibelThread extends Thread {
private volatile boolean running = true;
public void exit() {
running = false;
}
@Override
public void run() {
while (running) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (recorder == null || !running) {
break;
}
int x = recorder.getMaxAmplitude();
if (x != 0) {
int f = (int) (10 * Math.log(x) / Math.log(10));
if (f < 26)
volumeHandler.sendEmptyMessage(0);
else if (f < 32)
volumeHandler.sendEmptyMessage(1);
else if (f < 38)
volumeHandler.sendEmptyMessage(2);
else
volumeHandler.sendEmptyMessage(3);
}
}
}
}
private OnDismissListener onDismiss = new OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
stopRecording();
}
};
static class ShowVolumeHandler extends Handler {
@Override
public void handleMessage(Message msg) {
view.setImageResource(res[msg.what]);
}
}
public interface OnFinishedRecordListener {
public void onFinishedRecord(String audioPath);
}
}<pre name="code" class="java">package demo.com;
import demo.com.RecordButton.OnFinishedRecordListener;
import demo.com.R;
import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
public class RecordingActivity extends Activity {
private RecordButton mRecordButton = null;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
mRecordButton = (RecordButton) findViewById(R.id.record_button);
String path = Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/recordtest";
path += "/hsj.amr";
mRecordButton.setSavePath(path);
mRecordButton
.setOnFinishedRecordListener(new OnFinishedRecordListener() {
@Override
public void onFinishedRecord(String audioPath) {
Log.i("RECORD!!!", "finished!!!!!!!!!! save to "
+ audioPath);
}
});
}
}
<uses-permission android:name="android.permission.RECORD_AUDIO" >
</uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" >
</uses-permission>
源码地址:http://download.csdn.net/detail/u011693137/8132157