二、音频的录制

383 阅读3分钟

前言

Android SDK 提供了两套 API 用于音频的采集,分别是 MediaRecorder 和 AudioRecord。

  1. MediaRecorder是一个更加上层一点的API,它可以直接把手机麦克风录入的音频数据进行编码压缩(如AMR、MP3等)并存成文件,
  2. AudioRecord 更接近底层,能够更加自由灵活地控制,可以得到原始的一帧帧PCM音频数据。

在这里我们主要了解 如何利用 AudioRecord 来采集音频数据

需要注意的是,AudioRecord 采集到的音频是原始的 PCM 格式,如果要压缩成mp3等格式的话,需要调用编码器进行编码

AudioRecord 工作流程

初始化AudioRecord对象

首先看一下AudioRecord 的构造函数

 public AudioRecord(int audioSource, int sampleRateInHz, int channelConfig, int audioFormat,
            int bufferSizeInBytes)
  1. audioSource:音频源。通过使用 MediaRecorder.AudioSource 类中的常量指定音频来源,一般音频录制使用的是 MediaRecorder.AudioSource.MIC,表示音频源为设备的内置麦克风。
  2. sampleRateInHz:采样率。指定音频数据每秒的采样次数。采样率越高,音质越好,但也会占用更多存储空间和计算资源。现在唯一能够保证在所有设备上使用的采样率是44100Hz, 但是其他的采样率(22050, 16000, 11025)在一些设备上也可以使用。
  3. channelConfig:声道配置。使用 AudioFormat 类中的常量指定声道数。
    1. AudioFormat.CHANNEL_IN_MONO 表示单声道,
    2. AudioFormat.CHANNEL_IN_STEREO表示立体声双声道。
  4. audioFormat:音频数据编码格式。使用 AudioFormat 类中的常量指定音频数据的编码格式,这个参数是用来配置 数据位宽 的
    1. ENCODING_PCM_16BIT(16bit)表示16位有符号PCM格式 (这个格式可以保证兼容所有Android手机)
    2. ENCODING_PCM_8BIT(8bit)表示8位无符号PCM格式
  5. 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();

此代码只是简单的说明一下录制流程,真正使用的时候还需要考虑权限等各种问题。