Android音频开发(2):使用AudioRecord录制pcm格式音频

Android 音频开发 目录
  1. Android音频开发(1):音频相关知识
  2. Android音频开发(2):使用AudioRecord录制pcm格式音频
  3. Android音频开发(3):使用AudioRecord实现录音的暂停和恢复
  4. Android音频开发(4):PCM转WAV格式音频
  5. Android音频开发(5):Mp3的录制 - 编译Lame源码
  6. Android音频开发(6):Mp3的录制 - 使用Lame实时录制MP3格式音频
  7. Android音频开发(7):音乐可视化-FFT频谱图
项目地址

https://github.com/zhaolewei/ZlwAudioRecorder


一、AudioRecord类的介绍
  1. 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)
    
  2. getMinBufferSize()
    /**
    * 获取AudioRecord所需的最小缓冲区大小
    * @param sampleRateInHz: 采样率
    * @param channelConfig:声道数  
    * @param audioFormat: 采样位数.
    */
    public static int getMinBufferSize (int sampleRateInHz, 
                int channelConfig, 
                int audioFormat)
    
  3. getRecordingState()
    /**
    * 获取AudioRecord当前的录音状态 
    *   @see AudioRecord#RECORDSTATE_STOPPED    
    *   @see AudioRecord#RECORDSTATE_RECORDING
    */
    public int getRecordingState()
    
  4. startRecording()
     /**
     * 开始录制
     */
     public int startRecording()
    
  5. startRecording()
     /**
     * 停止录制
     */
     public int stop()
    
  6. 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的功能,下一篇再继续完善。
  • 需要录音及文件处理的动态权限
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值