Android 音频开发 目录
- Android音频开发(1):音频相关知识
- Android音频开发(2):使用AudioRecord录制pcm格式音频
- Android音频开发(3):使用AudioRecord实现录音的暂停和恢复
- Android音频开发(4):PCM转WAV格式音频
- Android音频开发(5):Mp3的录制 - 编译Lame源码
- Android音频开发(6):Mp3的录制 - 使用Lame实时录制MP3格式音频
- Android音频开发(7):音乐可视化-FFT频谱图
项目地址
https://github.com/zhaolewei/ZlwAudioRecorder
一、AudioRecord类的介绍
- AudioRecord构造函数:
/** * @param audioSource :录音源 * 这里选择使用麦克风:MediaRecorder.AudioSource.MIC * @param sampleRateInHz: 采样率 * @param channelConfig:声道数 * @param audioFormat: 采样位数. * See {@link AudioFormat#ENCODING_PCM_8BIT}, {@link AudioFormat#ENCODING_PCM_16BIT}, * and {@link AudioFormat#ENCODING_PCM_FLOAT}. * @param bufferSizeInBytes: 音频录制的缓冲区大小 * See {@link #getMinBufferSize(int, int, int)} */ public AudioRecord(int audioSource, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes)
- getMinBufferSize()
/** * 获取AudioRecord所需的最小缓冲区大小 * @param sampleRateInHz: 采样率 * @param channelConfig:声道数 * @param audioFormat: 采样位数. */ public static int getMinBufferSize (int sampleRateInHz, int channelConfig, int audioFormat)
- getRecordingState()
/** * 获取AudioRecord当前的录音状态 * @see AudioRecord#RECORDSTATE_STOPPED * @see AudioRecord#RECORDSTATE_RECORDING */ public int getRecordingState()
- startRecording()
/** * 开始录制 */ public int startRecording()
- startRecording()
/** * 停止录制 */ public int stop()
- read()
/** * 从录音设备中读取音频数据 * @param audioData 音频数据写入的byte[]缓冲区 * @param offsetInBytes 偏移量 * @param sizeInBytes 读取大小 * @return 返回负数则表示读取失败 * see {@link #ERROR_INVALID_OPERATION} -3 : 初始化错误 {@link #ERROR_BAD_VALUE} -3: 参数错误 {@link #ERROR_DEAD_OBJECT} -6: {@link #ERROR} */ public int read(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes)
二、实现
- 实现过程就是调用上面的API的方法,构造AudioRecord实例后再调用startRecording(),开始录音,并通过read()方法不断获取录音数据记录下来,生成PCM文件。涉及耗时操作,所以最好在子线程中进行。
/**
* @author zhaolewei on 2018/7/10.
*/
public class RecordHelper {
//0.此状态用于控制线程中的循环操作,应用volatile修饰,保持数据的一致性
private volatile RecordState state = RecordState.IDLE;
private AudioRecordThread audioRecordThread;
private File tmpFile = null;
public void start(String filePath, RecordConfig 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);
//1.开启录音线程并准备录音
audioRecordThread = new AudioRecordThread();
audioRecordThread.start();
}
public void stop() {
if (state == RecordState.IDLE) {
Logger.e(TAG, "状态异常当前状态: %s", state.name());
return;
}
state = RecordState.STOP;
}
private class AudioRecordThread extends Thread {
private AudioRecord audioRecord;
private int bufferSize;
AudioRecordThread() {
//2.根据录音参数构造AudioRecord实体对象
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;
Logger.d(TAG, "开始录制");
FileOutputStream fos = null;
try {
fos = new FileOutputStream(tmpFile);
audioRecord.startRecording();
byte[] byteBuffer = new byte[bufferSize];
while (state == RecordState.RECORDING) {
//3.不断读取录音数据并保存至文件中
int end = audioRecord.read(byteBuffer, 0, byteBuffer.length);
fos.write(byteBuffer, 0, end);
fos.flush();
}
//4.当执行stop()方法后state != RecordState.RECORDING,终止循环,停止录音
audioRecord.stop();
} 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());
}
}
state = RecordState.IDLE;
Logger.d(TAG, "录音结束");
}
}
}
三、其他
- 这里实现了PCM音频的录制,AudioRecord API中只有开始和停止的方法,在实际开发中可能还需要暂停/恢复的操作,以及PCM转WAV的功能,下一篇再继续完善。
- 需要录音及文件处理的动态权限