目录
概念
信号都是模拟信号,不管是声音还是光线,这些模拟信号需要被 A/D 转换器转换成数字信号,才能被存储在计算机中,从概念上讲,可以将 A/D 转换视为三步完成的过程:采样、量化和编码
采样
用采样器每隔一段时间读取一次模拟信号,用这些离散的值来代表整个模拟信号的过程。单位时间内的采样值个数被称为采样频率。常用的采样频率是 11025Hz、22050Hz 和 44100Hz。当然,也可以是其他更高或者更低的频率
量化
对于每次采样得到的值,考虑使用多少个 bit 来存储它。如果使用 8 个 bit (即一个字节)来描述采样值,那么能表达的值的范围是 256,如果使用 16 个 bit 来描述, 范围就被扩展为 65536,描述一个采样值所使用的位数,也被称为分辨率。常用的量化步 长为 8 位、16 位或者 32 位。
编码
脉冲编码 调制就是把一个时间连续,取值连续的模拟信号变换成时间离散,取值离散的数字信号后在 信道中传输。脉冲编码调制就是对模拟信号先抽样,再对样值幅度量化,编码的过程
音频文件wav 格式
wav 是一种符合 RIFF 文档规范的文件格式,这种文档规范是一种以树形结构组织 数据的标准,以 wav 格式为例子,文档必须先包含“RIFF 数据块”,也就是下图左边部分的区域,其中 ID 固定为 RIFF 四个字符,而且是大端序。而 SIZE 是除了 ID 和 SIZE 之外本文档的总大小,FMT 则是 RIFF 规范下 DATA 的具体数据格式,wav 对应的是 WAVE。 剩下的 DATA 就是 RIFF 文档的内容,RIFF 文档的内容又可以由多个“数据块”组成,对于 wav 格式而言,它的组成如下图 中右边部分所示:包含两块,一个是 fmt 块,一个 data 块
标准音频接口 ALSA
安装 ALSA 库
- 下载最新版alsa源码
- 解压缩,进入源码目录中并依次执行./configure、make 和 make install
- 将安装之后的 ALSA 库所在路径(缺省是/usr/lib/i386-Linux-gnu/)添加到环境 变量 LD_LIBRARY_PATH 中
- 编译音频程序的时候,包含头文件,并且链接 alsa 库: 比如: gcc example.c -o example -lasound
- 如果要将 ALSA 库安装到基于 ARM 平台的开发板上时,除了第 2 步中的./configure 需要增加指定交叉工具链前缀(例如--host=arm-none-linux-gnueabi)的参数外,还 需要将编译好的 ALSA 库的全部文件放到开发板中,并且保持绝对路径完全一致。
录制音频
步骤
- 取得 PCM 设备的句柄
- snd_pcm_t *handle;
- 设置 PCM 流的方向(录制)
- snd_pcm_stream_t stream = SND_PCM_STREAM_CAPTURE;
- 设置诸如数据 buffer 大小、采样频率、 量化级等
- snd_pcm_hw_params_t *hwparams;
api
获取pcm设备句柄
在 ALSA 中,可以使用 plughw 或者 hw 来代表 PCM 设备接口,使用 plughw 时我们 不需要关心所设置的各种 params 是否被声卡支持,因为如果不支持的话会自动使用默认 的值,如果使用 hw 的话就必须仔细检查声卡硬件的信息,确保设置的每一项都被支持。一 般而言使用 plughw 就可以了,具体而言,使用如下函数获得 PCM 设备句柄
snd_pcm_open(&handle, “plughw:0,0”, stream,0);
0,0 中的第一个 0 是系统中声卡的编号,第二个 0 是设备的 编号,而最后一个 0 代表标准打开模式,除此之外还可以是 SND_PCM_NONBLOCK 或者 SND_PCM_ASYNC,前者代表非阻塞读写 PCM 设备,后者代表声卡系统以异步方式工作: 每当一个周期(period)结束时,将触发一个
设置 PCM 设备参数
- 首先,给参数配置分配相应的空间,并且根据当前的 PCM 设备的具体情况初始化:
- snd_pcm_hw_params_t *hwparams;
- snd_pcm_hw_params_alloca(&hwparams);
- snd_pcm_hw_params_any(handle, hwparams);
- 设置访问模式为交错模式,这意味着采样点是帧连续的,而不是通道连续的
- snd_pcm_hw_params_set_access(handle,SND_PCM_ACCESS_RW_INTERLEAVED);
- SND_PCM_ACCESS_MMAP_INTERLEAVED:内存映射方式下的交错模式 SND_PCM_ACCESS_MMAP_NONINTERLEAVED:内存映射方式下的非交错模式 SND_PCM_ACCESS_RW_INTERLEAVED:直接 IO 方式下的交错模式 SND_PCM_ACCESS_RW_NONINTERLEAVED:直接 IO 方式下的非交错模
- snd_pcm_hw_params_set_access(handle,SND_PCM_ACCESS_RW_INTERLEAVED);
- 设置量化参数
- snd_pcm_format_t pcm_format =SND_PCM_FORMAT_S16_LE;
- SND_PCM_FORMAT_S8 有符号 8 位
SND_PCM_FORMAT_U8 无符号 8 位
SND_PCM_FORMAT_S16_LE 有符号 16 位,小端序 SND_PCM_FORMAT_S16_BE 有符号 16 位,大端序 SND_PCM_FORMAT_U16_LE 无符号 16 位,小端序 SND_PCM_FORMAT_U16_BE 无符号 16 位,大端序
SND_PCM_FORMAT_S24_LE 有符号 24 位,小端序 SND_PCM_FORMAT_S24_BE 有符号 24 位,大端序 SND_PCM_FORMAT_U24_LE 无符号 24 位,小端序 SND_PCM_FORMAT_U24_BE 无符号 24 位,大端序 SND_PCM_FORMAT_S32_LE 有符号 32 位,小端序 SND_PCM_FORMAT_S32_BE 有符号 32 位,大端序 SND_PCM_FORMAT_U32_LE 无符号 32 位,小端序 SND_PCM_FORMAT_U32_BE 无符号 32 位,大端序
- SND_PCM_FORMAT_S8 有符号 8 位
- snd_pcm_hw_params_set_format(handle, hwparams, pcm_format);
- snd_pcm_format_t pcm_format =SND_PCM_FORMAT_S16_LE;
- 设置音轨数目(本例中设置为双音轨,即立体声,1 为单音轨)
- uint16_t channels = 2;
- snd_pcm_hw_params_set_channels(handle, hwparams, channels);
- 设置采样频率,设备所支持的采用频率有规定的数值,本例中以 exact_rate 为基准,设置一个尽量接近该值的频率
- uint32_t exact_rate = 44100;
- snd_pcm_hw_params_set_rate_near(handle, hwparams, &exact_rate, 0);
- 采样频率的设置函数名字为 snd_pcm_h