Android录音上————AudioRecord实现录音功能

Android多媒体1————AudioRecord实现录音功能

一.前言

在百度实习的时候,导师让我负责语音助手SDK相关的东西,所以就一直想对其进行整理总结,就先从最基础,最简单AudioRecord类开始。

二.官方文档中的AudioRecord

想要了解一个类的具体说明,首先要看看官方文档:

1.概述

AndioRecordlei类的主要功能是让各种JAVA应用管理音频资源,方便从平台的音频输入硬件录制音频。此功能的实现是通过“pulling”(读取)AndioRecord对象的声音数据来完成。在录制过程中,应用所需要的是通过后面三个类方法中的一个区及时获取AudioRecord对象的录音数据。
开始录音时,AudioRecord需要一个初始化相关联的声音buffer,这个buffer主要用来存储新的声音数据,这个buffer的大小,我们可以在对象的构造期间去指定,它表明一个AudioRecord对象还没用被读取(同步)声音数据前能录多长的音。声音数据从音频硬件被读取出来,数据大小不超过整个录音数据的大小(可以分多次读取),即每次读取初始化buffer容量的数据。

2.实现Android录音的流程

  • 构造一个AudioRecord对象,其中需要的最小录音缓存buffer大小通过getMinBufferSize得到,如果buffer容量过小,将导致对象构造的失败
  • 初始化一个buffer,该buffer大于等于AudioRecord对象用于声音数据的buffer大小
  • 开始录音
  • 创建一个数据流,一边从AudioRecord中读取数据初始化的buffer,一边将buffer中的数据导入数据流中
  • 关闭数据流
  • 停止录音

三.相关的API

1.构造方法

AudioRecord(int audioSource, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes)

参数简介:

  • audioSource:指的是从哪里采集音频。这里我们当然是从麦克风采集音频,所以此参数的值为MIC
  • sampleRateInHz:音频的采样频率,每秒钟能够采样的次数,采样率越高,音质越高。给出的实例是44100、22050、11025但不限于这几个参数。例如要采集低质量的音频就可以使用4000、8000等低采样率。
  • channelConfig:android支持双声道和单道声,MONO单声道,STEREO立体声
  • audioFormat:采集来的数据使用PCM编码,Android支持的采用大小为16bit或者8bit。采样越大,信息量越多,音质也越高可以在getMinBufferSize()查看。
  • bufferSizeInBytes:采集数据需要缓存区的大小,如果不知道最小需要的大小

2.公共方法

  • int getAudioFormat():返回配置的音频数据格式
  • int getAudioSessionId():返回音频会话 id。
  • int getAudioSource():返回音频录制源。
  • int getChannelConfiguration():返回配置的通道配置。
  • int getChannelCount():返回配置的通道数。
  • static int getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat):返回成功创建 audio 记录对象所需的最小缓冲区大小 (以字节为单位)。
  • int getNotificationMarkerPosition():返回以框架表示的通知标记位置。
  • int getPositionNotificationPeriod():返回以框架表示的通知更新期间。
  • int getRecordingState():返回音频记录实例的录制状态。
  • int getSampleRate():返回以 hz 为单位的配置音频数据采样率
  • int getState():返回音频记录实例的状态。
  • int read(short[] audioData, int offsetInShorts, int sizeInShorts):从音频硬件读取音频数据, 以便录制到缓冲区中。
  • int read(byte[] audioData, int offsetInBytes, int sizeInBytes):从音频硬件读取音频数据, 以便录制到缓冲区中。
  • int read(ByteBuffer audioBuffer, int sizeInBytes):从音频硬件读取音频数据, 以便录制到缓冲区中。
  • void release():释放本机AudioRecord资源
  • int setNotificationMarkerPosition(int markerInFrames)
  • int setPositionNotificationPeriod(int periodInFrames)
  • void setRecordPositionUpdateListener(AudioRecord.OnRecordPositionUpdateListener listener, Handler handler):设置AudioRecord通知的侦听器,当达到先前设置的标记时,或每次定期记录头位置更新时。
  • void startRecording():从AudioRecord实例开始记录。
  • void startRecording(MediaSyncEvent syncEvent):当指定的同步事件在指定的音频会话上发生时,从AudioRecord实例开始记录。
  • void stop():停止记录

四.使用示例

public class AudioRecordImpl {
    private static final String TAG = "AudioRecordImpl";

    // 采样率
    private static final int SAMPLE_RATE_HZ = 16000;

    private static final int BUFFER_SIZE = 640;
    private AudioRecord audioRecord;
    private Thread recordThread;

    //采样频率
    private int mAudioSampleRate = SAMPLE_RATE_HZ;
    //音频源
    private int mAudioSource = MediaRecorder.AudioSource.MIC;
    //编码大小
    private int mAudioFormat = AudioFormat.ENCODING_PCM_16BIT;
    //选择声道
    private int mAudioChannel = AudioFormat.CHANNEL_IN_MONO;

    // 用于数据统计
    private volatile boolean isQueryLog;
    private volatile boolean isStartRecord = false;

    public AudioRecordImpl() {
        setAudio(SAMPLE_RATE_HZ, MediaRecorder.AudioSource.MIC, AudioFormat.ENCODING_PCM_16BIT,
                AudioFormat.CHANNEL_IN_MONO);
    }

   //默认设置
    public void setAudio(int sampleRate, int source, int format, int channel) {
        mAudioSampleRate = sampleRate;
        mAudioSource = source;
        mAudioFormat = format;
        mAudioChannel = channel;
    }

    //开始录音

    public v startRecord() {
        stopRecord();
        if (recordThread != null) {
            try {
                //t.join()方法阻塞调用此方法的线程(calling thread),
                // 直到线程t完成,此线程再继续
                recordThread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //设置线程优先级,android.os.Process.THREAD_PRIORITY_AUDIO-标准音乐播放使用的线程优先级
        android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_AUDIO);

        //获取最小buffer
        final int bufferSize = AudioRecord.getMinBufferSize(
                mAudioSampleRate, mAudioChannel, mAudioFormat);

        try {
            // 防止某些手机崩溃
            //创建audioRecord对象
            audioRecord = new AudioRecord(mAudioSource, mAudioSampleRate,
                    mAudioChannel, mAudioFormat, bufferSize * 10);
        } catch (Exception e) {
            e.printStackTrace();
            LogUtil.dcf(TAG, "new AudioRecord() IllegalStateException ", e);
        }
        isStartRecord = true;

        recordThread = new Thread() {
            @Override
            public void run() {
                super.run();

                try {
                    // 防止某些手机崩溃
                    if (audioRecord != null) {
                        audioRecord.startRecording();
                    }
                } catch (IllegalStateException e) {
                    e.printStackTrace();
                    LogUtil.dcf(TAG, "startRecording IllegalStateException ", e);
                    isStartRecord = false;
                }

                isQueryLog = true;
                while (isStartRecord) {
                    try {
                        //读取语音数据
                        byte[] buffer = new byte[BUFFER_SIZE];
                        int readBytes = audioRecord.read(buffer, 0, buffer.length);
                        if (readBytes > 0) {
                            //处理语音数据
                            fireData(buffer);
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        LogUtil.ecf(TAG, "audio recorder exception," + e);
                        isStartRecord = false;
                    }

                }

                // 释放资源
                try {
                    if (audioRecord != null) {
                        audioRecord.release();
                        LogUtil.ic(TAG, "audioRecorder release ");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    LogUtil.wcf(TAG, "stop and release IllegalStateException ", e);
                } finally {
                    audioRecord = null;
                }
            }
        };

        recordThread.start();
    }

    //停止录音

    public void stopRecord() {
        LogUtil.dc(TAG, "stopRecord");
        isStartRecord = false;
    }

    //释放资源

    public void release() {
 		//释放资源
        LogUtil.dc(TAG, "release");
        stopRecord();
    }
}

五.参考资料

官方文档
Android 音视频开发(二):使用 AudioRecord 采集音频PCM并保存到文件

发布了120 篇原创文章 · 获赞 478 · 访问量 16万+

猜你喜欢

转载自blog.csdn.net/qq_38499859/article/details/87862370