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

  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
Android实现录音功能,可以使用 `MediaRecorder` 类或 `AudioRecord` 类。这里给出 `AudioRecord` 的实现示例。 首先,在 AndroidManifest.xml 文件中添加录音权限: ```xml <uses-permission android:name="android.permission.RECORD_AUDIO" /> ``` 然后,创建一个 `AudioRecord` 对象并开始录音: ```java import android.media.AudioFormat; import android.media.AudioRecord; import android.media.MediaRecorder; import android.os.Handler; import android.os.Looper; import android.util.Log; public class AudioRecorder { private static final String TAG = AudioRecorder.class.getSimpleName(); private static final int SAMPLE_RATE = 16000; private static final int CHANNEL_CONFIG = AudioFormat.CHANNEL_IN_MONO; private static final int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT; private static final int BUFFER_SIZE = AudioRecord.getMinBufferSize(SAMPLE_RATE, CHANNEL_CONFIG, AUDIO_FORMAT); private AudioRecord audioRecord; private byte[] buffer; private boolean isRecording; private Handler handler; private Callback callback; public AudioRecorder() { audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, SAMPLE_RATE, CHANNEL_CONFIG, AUDIO_FORMAT, BUFFER_SIZE); buffer = new byte[BUFFER_SIZE]; handler = new Handler(Looper.getMainLooper()); } public void setCallback(Callback callback) { this.callback = callback; } public void start() { if (isRecording) { return; } audioRecord.startRecording(); isRecording = true; new Thread(() -> { while (isRecording) { int bytes = audioRecord.read(buffer, 0, buffer.length); if (bytes > 0 && callback != null) { handler.post(() -> callback.onAudioDataReceived(buffer, bytes)); } } audioRecord.stop(); audioRecord.release(); audioRecord = null; }).start(); } public void stop() { isRecording = false; } public interface Callback { void onAudioDataReceived(byte[] data, int size); } } ``` 在此示例中,我们首先创建一个 `AudioRecord` 对象,并使用 `MediaRecorder.AudioSource.MIC` 作为录音源。然后,我们在一个新线程中读取录音数据,并调用回调函数将数据传递给主线程。最后,我们在 `stop` 方法中停止录音。 使用示例: ```java AudioRecorder recorder = new AudioRecorder(); recorder.setCallback((data, size) -> { // 处理录音数据 }); recorder.start(); // 录音中... recorder.stop(); ``` 请注意,此示例中的 `Callback` 接口仅用于演示目的,您应该将其替换为您自己的接口,并在其中处理录音数据。另外,如果您需要将录音保存到文件中,可以使用 `AudioRecord` 的 `read` 方法读取录音数据,并将其写入文件中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值