在 Android 上录制和播放 PCM 音频

in Program with 0 comment
昨天学习了图片的绘制,今天轮到了音频的采集和播放。

Android 在音频的采集上有提供相应的 API,就是 AudioRecord。

录音部分

AudioRecord 是什么?

AudioRecord 是为 Java 应用程序提供管理音频资源功能的类,使应用程序可能通过此类能够获取声音相关硬件所收集的声音。

录音是 Input 行为,所以这个功能的实现就是通过读取硬件的数据来完成录音的过程。

实现录音的流程

  1. 构造一个 AudioRecord 对象,并指定需要的最小的缓存 buffer 大小。

    这个缓存是用来存储未读取的声音数据的,他表明声音数据没有被读取前,能录多久的音(即一次可以录制的声音容量)。

  2. 初始化一个 buffer,这个 buffer 和 上一步指定的 buffer 不同,这是用来表示每次读取声音数据读取多少的。
  3. 开始录音。
  4. 创建一个数据流,将从 AudioRecord 读取到声音数据存储在数据流中。
  5. 关闭数据流。
  6. 停止录音。

从上面的步骤就可以看出录音其实和普通的文件 I/O 的思想是一致的。说到这里,其实计算机里就是计算和 I/O,掌握这个模型后,大部分的逻辑都能理通。

AudioRecord 参数详解

AudioRecord 需要的参数有以下几个:

接下来对各个参数进行详细说明:

音频源

音频源指的是从哪里采集音频,也就是指定硬件设备。下面是 Android 所支持的音频源,在 MediaRecorder.AudioSource 中定义:

/**默认声音**/
public static final int DEFAULT = 0;

/**麦克风声音*/
public static final int MIC = 1;

/**通话上行声音*/
public static final int VOICE_UPLINK = 2;

/**通话下行声音*/
public static final int VOICE_DOWNLINK = 3;

/**通话上下行声音*/
public static final int VOICE_CALL = 4;

/**根据摄像头转向选择麦克风*/
public static final int CAMCORDER = 5;

/**对麦克风声音进行声音识别,然后进行录制*/
public static final int VOICE_RECOGNITION = 6;

/**对麦克风中类似ip通话的交流声音进行识别,默认会开启回声消除和自动增益*/
public static final int VOICE_COMMUNICATION = 7;

/**录制系统内置声音*/
public static final int REMOTE_SUBMIX = 8;

采样率

采样率指的是音频的采样率,每秒钟能够采样的次数,采样率越高,音质越高。此处推荐的采样率是 44100、22050、11025,但是并不局限于这几个。

声道

Android 支持双声道立体声单声道,这部分在 AudioFormat 中定义

public static final int CHANNEL_IN_MONO = CHANNEL_IN_FRONT;
public static final int CHANNEL_IN_STEREO = (CHANNEL_IN_LEFT | CHANNEL_IN_RIGHT);

采样位数

通过 AudioRecoder 采集到的声音数据是 PCM 格式的,在计算机中采样位数一般有 8 位和 16 位之分。这个参数是用来衡量声音波动变化的一个参数,类似于分辨率的概念,他的数值越大,录制的颗粒度越细,声音就更精细。

需要注意的是: 8 位不是说将纵轴分割成 8 份,而是分成 2 的 8 次方,即 256 份。同理,16 位是把纵轴分割成 2 的 16 次方 65536 份。

存储量

在录制的时候并不需要存储量这个参数,但是已经知道了这些参数,就可以计算出录制文件的存储大小了。声音最重要的三个参数就是:声道、采样位数、采样频率,所以由以下公式可以计算出录制文件的大小:

存储量= (采样频率 · 采样位数 · 声道 · 时间)/8 (单位:字节数)

播放部分

上半部分讲了怎么录制声音,下半部分聊一下怎么把录制的声音播放出来。

播放录制的声音需要用到 AudioTrack 这个类。

AudioTrack

其实和录制几乎一样,只是流程是相反的。毕竟一个是 input,一个是 output。还是标准的 I/O 思路,参数也一致。

最后

最后肯定要放代码的,代码太长了,就不在文章中贴出来了。感兴趣的可以去 GitHub 仓库看看。

仓库地址:https://github.com/T-Oner/MediaPractice

Responses