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并保存到文件

更多相关文章

  1. “罗永浩抖音首秀”销售数据的可视化大屏是怎么做出来的呢?
  2. Nginx系列教程(三)| 一文带你读懂Nginx的负载均衡
  3. 不吹不黑!GitHub 上帮助人们学习编码的 12 个资源,错过血亏...
  4. Android去除TextView文本中的默认内边距
  5. android wear端数据和手机端数据
  6. 五步学会Android的ListView控件
  7. Android(安卓)PopupWindow with ListView的一些问题
  8. Android(安卓)重要数据目录
  9. understand and use android mvc(理解及使用android mvc)

随机推荐

  1. MySQL update set 和 and的区别
  2. MySQL DDL 引发的同步延迟该如何解决
  3. MySQL查询学习之基础查询操作
  4. MySQL 丢失数据的原因及解决
  5. 详解Mysql order by与limit混用陷阱
  6. android webview不支持input type=file
  7. 使用Android(安卓)Studio搭建Android集成
  8. 解决:Unable to connect to repository ht
  9. Android屏幕自适应的问题
  10. java.lang.ClassCastException: android.