前言
Android SDK 提供了两套 API 用于音频的采集,分别是 MediaRecorder 和 AudioRecord。
- MediaRecorder是一个更加上层一点的API,它可以直接把手机麦克风录入的音频数据进行编码压缩(如AMR、MP3等)并存成文件,
- AudioRecord 更接近底层,能够更加自由灵活地控制,可以得到原始的一帧帧PCM音频数据。
在这里我们主要了解 如何利用 AudioRecord 来采集音频数据
需要注意的是,AudioRecord 采集到的音频是原始的 PCM 格式,如果要压缩成mp3等格式的话,需要调用编码器进行编码
AudioRecord 工作流程
初始化AudioRecord对象
首先看一下AudioRecord 的构造函数
public AudioRecord(int audioSource, int sampleRateInHz, int channelConfig, int audioFormat,
int bufferSizeInBytes)
- audioSource:音频源。通过使用 MediaRecorder.AudioSource 类中的常量指定音频来源,一般音频录制使用的是 MediaRecorder.AudioSource.MIC,表示音频源为设备的内置麦克风。
- sampleRateInHz:采样率。指定音频数据每秒的采样次数。采样率越高,音质越好,但也会占用更多存储空间和计算资源。现在唯一能够保证在所有设备上使用的采样率是44100Hz, 但是其他的采样率(22050, 16000, 11025)在一些设备上也可以使用。
- channelConfig:声道配置。使用 AudioFormat 类中的常量指定声道数。
- AudioFormat.CHANNEL_IN_MONO 表示单声道,
- AudioFormat.CHANNEL_IN_STEREO表示立体声双声道。
- audioFormat:音频数据编码格式。使用 AudioFormat 类中的常量指定音频数据的编码格式,这个参数是用来配置 数据位宽 的
- ENCODING_PCM_16BIT(16bit)表示16位有符号PCM格式 (这个格式可以保证兼容所有Android手机)
- ENCODING_PCM_8BIT(8bit)表示8位无符号PCM格式
- bufferSizeInBytes:缓冲区大小。指定用于读取或写入音频数据的内部缓冲区大小。为了保证可以缓冲区的大小合适,通常我们使用 AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat) 方法来获取合适的最小缓冲区大小。
准备录音
调用 AudioRecord.startRecording() 方法开始从指定的音频源捕获声音数据。
读取音频数据
创建一个线程,通过循环调用 AudioRecord.read(byte[] audioData, int offsetInBytes, int sizeInBytes) 读取音频流中的数据 这个方法会将采集到的音频数据填充到传入的字节数组中,开发者可以根据需要处理这些数据,比如实时播放、压缩存储或传输等
处理音频数据
根据读取的数据类型,可能需要将原始字节数据转换成更易操作的形式,如 short 数组或其他音频处理所需的格式。
停止录音
当录音完成或者需要停止时,调用 AudioRecord.stop() 方法停止音频录制。
释放资源
在不需要 AudioRecord 对象后,必须调用 AudioRecord.release() 方法来释放相关的系统资源,否则可能会导致内存泄漏或其他资源问题。
简易代码示例:
int sampleRate = 44100;
int channelConfig = AudioFormat.CHANNEL_IN_MONO;
int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
int bufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);
AudioRecord audioRecord = new AudioRecord(
MediaRecorder.AudioSource.MIC,
sampleRate,
channelConfig,
audioFormat,
bufferSize);
audioRecord.startRecording();
byte[] audioData = new byte[bufferSize];
while (isRecording) {
int readResult = audioRecord.read(audioData, 0, bufferSize);
// 处理音频数据...
}
audioRecord.stop();
audioRecord.release();
此代码只是简单的说明一下录制流程,真正使用的时候还需要考虑权限等各种问题。