AudioRecoder 录音

2017-02-23  本文已影响190人  冉冉升起的小太阳

packagecom.ldm.mediarecorder.activity;

importandroid.Manifest;

importandroid.content.pm.PackageManager;

importandroid.media.AudioFormat;

importandroid.media.AudioManager;

importandroid.media.AudioRecord;

importandroid.media.AudioTrack;

importandroid.media.MediaRecorder;

importandroid.os.AsyncTask;

importandroid.os.Build;

importandroid.os.Environment;

importandroid.os.Handler;

importandroid.os.Message;

importandroid.support.annotation.NonNull;

importandroid.support.v4.app.ActivityCompat;

importandroid.support.v4.content.ContextCompat;

importandroid.util.Log;

importandroid.view.View;

importandroid.widget.AdapterView;

importandroid.widget.Button;

importandroid.widget.ListView;

importandroid.widget.Toast;

importcom.ldm.mediarecorder.R;

importcom.ldm.mediarecorder.adapter.AudioAdapter;

importcom.ldm.mediarecorder.base.BaseActivity;

importcom.ldm.mediarecorder.base.Constant;

importcom.ldm.mediarecorder.model.FileBean;

importjava.io.BufferedInputStream;

importjava.io.DataInputStream;

importjava.io.File;

importjava.io.FileInputStream;

importjava.io.FileOutputStream;

importjava.io.IOException;

importjava.util.ArrayList;

importjava.util.List;

importjava.util.concurrent.ExecutorService;

importjava.util.concurrent.Executors;

/**

* 该实例中,我们使用AudioRecord类来完成我们的音频录制程序

* AudioRecord类,我们可以使用三种不同的read方法来完成录制工作,

* 每种方法都有其实用的场合

* 一、实例化一个AudioRecord类我们需要传入几种参数

* 1、AudioSource:这里可以是MediaRecorder.AudioSource.MIC

* 2、SampleRateInHz:录制频率,可以为8000hz或者11025hz等,不同的硬件设备这个值不同

* 3、ChannelConfig:录制通道,可以为AudioFormat.CHANNEL_CONFIGURATION_MONO和AudioFormat.CHANNEL_CONFIGURATION_STEREO

* 4、AudioFormat:录制编码格式,可以为AudioFormat.ENCODING_16BIT和8BIT,其中16BIT的仿真性比8BIT好,但是需要消耗更多的电量和存储空间

* 5、BufferSize:录制缓冲大小:可以通过getMinBufferSize来获取

* 这样我们就可以实例化一个AudioRecord对象了

* 二、创建一个文件,用于保存录制的内容

* 同上篇

* 三、打开一个输出流,指向创建的文件

* DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file)))

* 四、现在就可以开始录制了,我们需要创建一个字节数组来存储从AudioRecorder中返回的音频数据,但是

* 注意,我们定义的数组要小于定义AudioRecord时指定的那个BufferSize

* short[]buffer = new short[BufferSize/4];

* startRecording();

* 然后一个循环,调用AudioRecord的read方法实现读取

* 另外使用MediaPlayer是无法播放使用AudioRecord录制的音频的,为了实现播放,我们需要

* 使用AudioTrack类来实现

* AudioTrack类允许我们播放原始的音频数据

*

*

* 一、实例化一个AudioTrack同样要传入几个参数

* 1、StreamType:在AudioManager中有几个常量,其中一个是STREAM_MUSIC;

* 2、SampleRateInHz:最好和AudioRecord使用的是同一个值

* 3、ChannelConfig:同上

* 4、AudioFormat:同上

* 5、BufferSize:通过AudioTrack的静态方法getMinBufferSize来获取

* 6、Mode:可以是AudioTrack.MODE_STREAM和MODE_STATIC,关于这两种不同之处,可以查阅文档

* 二、打开一个输入流,指向刚刚录制内容保存的文件,然后开始播放,边读取边播放

*

* 实现时,音频的录制和播放分别使用两个AsyncTask来完成

*/

public classAudioRecordActivityextendsBaseActivity {

privatePlayTaskplayer;

privateButtonstart_tv;

privateListViewlistView;

//线程操作

privateExecutorServicemExecutorService;

//当前是否正在录音

private volatile booleanisRecording;

//录音开始时间与结束时间

private longstartTime,endTime;

//录音所保存的文件

privateFilemAudioFile;

/**

* 文件列表数据

*/

privateListdataList;

privateAudioAdaptermAudioAdapter;

//private String mFilePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/audio/";

privateStringmFilePath= Environment.getExternalStorageDirectory().getAbsolutePath()+"/zhangxinaaaaa/";

private byte[]mBuffer;

privateFileOutputStreammFileOutPutStream;

//文件流录音API

privateAudioRecordmAudioRecord;

private volatile booleanisPlaying;

/**

* 配置AudioRecord

*/

private final intaudioSource= MediaRecorder.AudioSource.MIC;

private intfrequence=8000;//录制频率,单位hz.这里的值注意了,写的不好,可能实例化AudioRecord对象的时候,会出错。我开始写成11025就不行。这取决于硬件设备

private intchannelConfig= AudioFormat.CHANNEL_CONFIGURATION_MONO;

private intaudioEncoding= AudioFormat.ENCODING_PCM_16BIT;

//缓存大小

private static final intBUFFER_SIZE=2048;

//计算AudioRecord内部buffer大小

private final intminBufferSize= AudioRecord.getMinBufferSize(frequence,channelConfig,audioEncoding);

//更新UI线程的Handler

privateHandlermHandler=newHandler() {

@Override

public voidhandleMessage(Message msg) {

super.handleMessage(msg);

switch(msg.what) {

caseConstant.RECORD_SUCCESS:

//录音成功,展示数据

if(null==mAudioAdapter) {

mAudioAdapter=newAudioAdapter(AudioRecordActivity.this,dataList,R.layout.file_item_layout);

}

listView.setAdapter(mAudioAdapter);

break;

//录音失败

caseConstant.RECORD_FAIL:

showToastMsg(getString(R.string.record_fail));

break;

//录音时间太短

caseConstant.RECORD_TOO_SHORT:

showToastMsg(getString(R.string.time_too_short));

break;

caseConstant.PLAY_COMPLETION:

showToastMsg(getString(R.string.play_over));

break;

caseConstant.PLAY_ERROR:

showToastMsg(getString(R.string.play_error));

break;

}

}

};

@Override

protected voidsetWindowView() {

setContentView(R.layout.activity_record);

dataList=newArrayList<>();

mExecutorService= Executors.newSingleThreadExecutor();

mBuffer=new byte[BUFFER_SIZE];

}

@Override

protected voidinitViews() {

this.start_tv= (Button) findViewById(R.id.start_tv);

this.listView= (ListView) findViewById(R.id.listview);

}

@Override

protected voidinitEvents() {

this.start_tv.setOnClickListener(this);

//点击Item播放对应的声音文件

this.listView.setOnItemClickListener(newAdapterView.OnItemClickListener() {

@Override

public voidonItemClick(AdapterView adapterView,View view, inti, longl) {

//使用AudioTrack播放声音流文件

Toast.makeText(AudioRecordActivity.this,i +"",Toast.LENGTH_SHORT).show();

player=newPlayTask(dataList.get(i).getFile());

player.execute();

}

});

}

@Override

public voidonClick(View view) {

switch(view.getId()) {

//开始录音操作

caseR.id.start_tv:

//正在录音

if(isRecording) {

isRecording=false;

start_tv.setText(R.string.start_record);

//停止录音

mExecutorService.submit(newRunnable() {

@Override

public voidrun() {

stopRecord();

}

});

}else{

isRecording=true;

start_tv.setText(R.string.stop_record);

//录音操作

mExecutorService.submit(newRunnable() {

@Override

public voidrun() {

if(Build.VERSION.SDK_INT>22) {

//6.0以上权限管理

permissionForM();

}else{

//开始录音

startRecord();

}

}

});

}

break;

}

}

/**

* 开始录制

*/

private voidstartRecord() {

try{

//创建录音文件,.m4a为MPEG-4音频标准的文件的扩展名

mAudioFile=newFile(mFilePath+ System.currentTimeMillis() +".pcm");

//创建父文件夹

mAudioFile.getParentFile().mkdirs();

//创建文件

mAudioFile.createNewFile();

//创建文件输出流

mFileOutPutStream=newFileOutputStream(mAudioFile);

//根据上面的设置参数初始化AudioRecord

mAudioRecord=newAudioRecord(audioSource,frequence,channelConfig,audioEncoding,Math.max(minBufferSize,BUFFER_SIZE));

//开始录音

mAudioRecord.startRecording();

//记录开始时间

startTime= System.currentTimeMillis();

short[] buffer =new short[BUFFER_SIZE];

while(isRecording) {

//r是实际读取的数据长度,一般而言r会小于buffersize

intr =mAudioRecord.read(buffer,0,BUFFER_SIZE);

longv =0;

// 将 buffer 内容取出,进行平方和运算

for(inti =0;i < buffer.length;i++) {

v += buffer[i] * buffer[i];

}

// 平方和除以数据总长度,得到音量大小。

doublemean = v / (double) r;

doublevolume =10* Math.log10(mean);

Log.d("zhangxin","分贝值:"+ volume);

}

//写入数据到文件

while(isRecording) {

intread =mAudioRecord.read(mBuffer,0,BUFFER_SIZE);

if(read >0) {

//保存到指定文件

mFileOutPutStream.write(mBuffer,0,read);

}

}

}catch(IOException e) {

mHandler.sendEmptyMessage(Constant.RECORD_FAIL);

}finally{

//            if (null != mAudioRecord) {

//                //释放资源

//                mAudioRecord.release();

//            }

}

}

/**

*@description停止录音

*

*/

private voidstopRecord() {

try{

//停止录音

mAudioRecord.stop();

mAudioRecord.release();

mAudioRecord=null;

mFileOutPutStream.close();

//记录时长

endTime= System.currentTimeMillis();

//录音时间处理,比如只有大于2秒的录音才算成功

inttime = (int) ((endTime-startTime) /1000);

if(time >=3) {

//录音成功,添加数据

FileBean bean =newFileBean();

bean.setFile(mAudioFile);

bean.setFileLength(time);

dataList.add(bean);

//录音成功,发Message

mHandler.sendEmptyMessage(Constant.RECORD_SUCCESS);

}else{

mAudioFile=null;

mHandler.sendEmptyMessage(Constant.RECORD_TOO_SHORT);

}

}catch(Exception e) {

mHandler.sendEmptyMessage(Constant.RECORD_FAIL);

}

}

@Override

protected voidonDestroy() {

super.onDestroy();

if(null!=mExecutorService) {

mExecutorService.shutdownNow();

}

}

/**

* 6.0以上版本手机权限处理

*/

private voidpermissionForM() {

if(ContextCompat.checkSelfPermission(this,

Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED|| ContextCompat.checkSelfPermission(this,

Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {

ActivityCompat.requestPermissions(this,

newString[]{Manifest.permission.RECORD_AUDIO,Manifest.permission.WRITE_EXTERNAL_STORAGE},

Constant.PERMISSIONS_REQUEST_FOR_AUDIO);

}else{

startRecord();

}

}

@Override

public voidonRequestPermissionsResult(intrequestCode,@NonNullString[] permissions,@NonNullint[] grantResults) {

if(requestCode == Constant.PERMISSIONS_REQUEST_FOR_AUDIO) {

if(grantResults[0] == PackageManager.PERMISSION_GRANTED) {

startRecord();

}

return;

}

super.onRequestPermissionsResult(requestCode,permissions,grantResults);

}

/**

* 播放音频

*/

public classPlayTaskextendsAsyncTask {

FileaudioFile;

publicPlayTask(File audioFile) {

this.audioFile= audioFile;

}

@Override

protectedVoiddoInBackground(Void... arg0) {

isPlaying=true;

intbufferSize = AudioTrack.getMinBufferSize(frequence,channelConfig,audioEncoding);

short[] buffer =new short[bufferSize /4];

try{

//定义输入流,将音频写入到AudioTrack类中,实现播放

DataInputStream dis =newDataInputStream(newBufferedInputStream(newFileInputStream(audioFile)));

//实例AudioTrack

AudioTrack track =newAudioTrack(AudioManager.STREAM_MUSIC,frequence,channelConfig,audioEncoding,bufferSize,AudioTrack.MODE_STREAM);

//开始播放

track.play();

//由于AudioTrack播放的是流,所以,我们需要一边播放一边读取

while(isPlaying&& dis.available() >0) {

inti =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;

}

}

}

上一篇下一篇

猜你喜欢

热点阅读