美文网首页
AudioRecoder 录音

AudioRecoder 录音

作者: 冉冉升起的小太阳 | 来源:发表于2017-02-23 12:01 被阅读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;

    }

    }

    }

    相关文章

      网友评论

          本文标题:AudioRecoder 录音

          本文链接:https://www.haomeiwen.com/subject/jsklwttx.html