Android音频开发(3):使用AudioRecord实现录音的暂停和恢复
标签:
Android Studio
上一篇主要写了AudioRecord实现音频录制的开始和停止,AudioRecord并没有暂停和恢复播放功能的API,所以需要手动实现
一、解决办法
思路很简单,现在可以实现音频的文件录制和停止,并生成pcm文件,那么暂停时将这次文件先保存下来,恢复播放后开始新一轮的录制,那么最后会生成多个pcm音频,再将这些pcm文件进行合并,这样就实现了暂停/恢复的功能了。
二、实现
实现的重点在于如何控制录音的状态
/** * @author zhaolewei on 2018/7/10. */public class RecordHelper { private volatile RecordState state = RecordState.IDLE; private AudioRecordThread audioRecordThread; private File recordFile = null; private File tmpFile = null; private List<File> files = new ArrayList<>(); public void start(String filePath, RecordConfig config) { this.currentConfig = config; if (state != RecordState.IDLE) { Logger.e(TAG, "状态异常当前状态: %s", state.name()); return; } recordFile = new File(filePath); String tempFilePath = getTempFilePath(); Logger.i(TAG, "tmpPCM File: %s", tempFilePath); tmpFile = new File(tempFilePath); audioRecordThread = new AudioRecordThread(); audioRecordThread.start(); } public void stop() { if (state == RecordState.IDLE) { Logger.e(TAG, "状态异常当前状态: %s", state.name()); return; } //若在暂停中直接停止,则直接合并文件即可 if (state == RecordState.PAUSE) { makeFile(); state = RecordState.IDLE; } else { state = RecordState.STOP; } } public void pause() { if (state != RecordState.RECORDING) { Logger.e(TAG, "状态异常当前状态: %s", state.name()); return; } state = RecordState.PAUSE; } public void resume() { if (state != RecordState.PAUSE) { Logger.e(TAG, "状态异常当前状态: %s", state.name()); return; } String tempFilePath = getTempFilePath(); Logger.i(TAG, "tmpPCM File: %s", tempFilePath); tmpFile = new File(tempFilePath); audioRecordThread = new AudioRecordThread(); audioRecordThread.start(); } private class AudioRecordThread extends Thread { private AudioRecord audioRecord; private int bufferSize; AudioRecordThread() { bufferSize = AudioRecord.getMinBufferSize(currentConfig.getFrequency(), currentConfig.getChannel(), currentConfig.getEncoding()) * RECORD_AUDIO_BUFFER_TIMES; audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, currentConfig.getFrequency(), currentConfig.getChannel(), currentConfig.getEncoding(), bufferSize); } @Override public void run() { super.run(); state = RecordState.RECORDING; notifyState(); Logger.d(TAG, "开始录制"); FileOutputStream fos = null; try { fos = new FileOutputStream(tmpFile); audioRecord.startRecording(); byte[] byteBuffer = new byte[bufferSize]; while (state == RecordState.RECORDING) { int end = audioRecord.read(byteBuffer, 0, byteBuffer.length); fos.write(byteBuffer, 0, end); fos.flush(); } audioRecord.stop(); //1. 将本次录音的文件暂存下来,用于合并 files.add(tmpFile); //2. 再此判断终止循环的状态是暂停还是停止,并做相应处理 if (state == RecordState.STOP) { makeFile(); } else { Logger.i(TAG, "暂停!"); } } catch (Exception e) { Logger.e(e, TAG, e.getMessage()); } finally { try { if (fos != null) { fos.close(); } } catch (IOException e) { Logger.e(e, TAG, e.getMessage()); } } if (state != RecordState.PAUSE) { state = RecordState.IDLE; notifyState(); Logger.d(TAG, "录音结束"); } } } private void makeFile() { //合并文件 boolean mergeSuccess = mergePcmFiles(recordFile, files); //TODO:转换wav Logger.i(TAG, "录音完成! path: %s ; 大小:%s", recordFile.getAbsoluteFile(), recordFile.length()); } /** * 合并Pcm文件 * * @param recordFile 输出文件 * @param files 多个文件源 * @return 是否成功 */ private boolean mergePcmFiles(File recordFile, List<File> files) { if (recordFile == null || files == null || files.size() <= 0) { return false; } FileOutputStream fos = null; BufferedOutputStream outputStream = null; byte[] buffer = new byte[1024]; try { fos = new FileOutputStream(recordFile); outputStream = new BufferedOutputStream(fos); for (int i = 0; i < files.size(); i++) { BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(files.get(i))); int readCount; while ((readCount = inputStream.read(buffer)) > 0) { outputStream.write(buffer, 0, readCount); } inputStream.close(); } } catch (Exception e) { Logger.e(e, TAG, e.getMessage()); return false; } finally { try { if (fos != null) { fos.close(); } if (outputStream != null) { outputStream.close(); } } catch (IOException e) { e.printStackTrace(); } } //3. 合并后记得删除缓存文件并清除list for (int i = 0; i < files.size(); i++) { files.get(i).delete(); } files.clear(); return true; } }
其他
在此后如若需要添加录音状态回调,记得使用Handler做好线程切换。
作者:android_赵乐玮
链接:https://www.jianshu.com/p/a4a960635e40
点击查看更多内容
为 TA 点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦