2、音频硬件基础:了解声卡、编解码器、DAC/ADC、采样率、位深度等基本概念

好,咱们正式开始聊硬件。很多做音频开发的朋友,上来就怼 ALSA 的 API,结果遇到杂音、延迟、设备不识别,一脸懵。说白了,就是底层硬件没搞明白。

我个人习惯,在写任何音频代码之前,先搞清楚板子上到底有哪些家伙在干活。这一章,咱们就把声卡、Codec、DAC/ADC 这些硬件的底裤扒干净。

2.1 声卡:不只是个“卡”

你想想看,现在的电脑、手机、开发板,哪个没声卡?但声卡早不是当年插在 PCI 槽里的大板子了。

在 Linux 系统里,声卡是一个逻辑概念。它可能是一颗独立的芯片,也可能集成在 CPU 里。我见过不少新手,在开发板上用 aplay -l 看到好几个声卡,就慌了。其实,每个声卡对应一个音频设备实例。

举个例子,我手头这块板子:

card 0: sunxi-CODEC [sunxi-CODEC], device 0: 2030000.codec-sunxi-snd-codec-aif1 sunxi-snd-codec-aif1-0 []
card 1: sndhdmi [sndhdmi], device 0: 2030000.daudio-sndhdmi-hdmi sndhdmi-hdmi-0 []

看到了吗?card 0 是板载的模拟音频接口,card 1 是 HDMI 数字音频。它们共用同一个物理芯片,但在 Linux 里是两个独立的声卡。

核心要点:在 ALSA 的世界里,声卡就是 card X,设备就是 device Y。操作音频流,你得先锁定 hw:X,Y。

2.2 编解码器(Codec):音频的翻译官

Codec 这个词,是 Coder/Decoder 的缩写。它干的事很简单:把数字信号转成模拟信号(播放),或者把模拟信号转成数字信号(录音)。

嗯,这里要注意。Codec 和声卡不是一回事。声卡是“管理者”,Codec 是“执行者”。声卡通过 I2C 或 SPI 总线去控制 Codec,告诉它:“哥们,现在音量调到 80%,采样率设成 48kHz。”

我在项目中遇到过最坑的事,就是 Codec 的寄存器没初始化。板子能出声,但声音小得跟蚊子似的。后来一查,是 Codec 的电源管理寄存器默认把输出衰减了 20dB。

避坑指南:调试音频时,先用 amixer 看看 Codec 的控件状态。我曾经花了一下午,最后发现是 “Headphone Playback Volume” 被静音了。

2.3 DAC 与 ADC:模拟世界的桥梁

DAC(数模转换器)和 ADC(模数转换器),是 Codec 内部最核心的模块。

  • DAC:把 0101 的数字流,变成耳朵能听的电压波形。
  • ADC:把麦克风捕捉的声波,变成计算机能处理的数字信号。

说白了,没有它们,音频就是一堆冰冷的数字。DAC 的精度直接决定了音质。我见过一些低端 Codec,DAC 只有 16bit,底噪大得吓人。而高端一点的,比如 PCM5122,能做到 32bit 384kHz,动态范围轻松超过 110dB。

为什么会这样?因为 DAC 的位数决定了它能表示的最小电压变化。16bit 有 65536 个台阶,24bit 有 1677 万个台阶。台阶越多,波形越平滑,失真越小。

2.4 采样率:时间轴上的精度

采样率,就是每秒钟对模拟信号“拍照”的次数。单位是 Hz。

常见的采样率有:

采样率 常见用途
8 kHz 电话语音
44.1 kHz CD 音质
48 kHz DVD、专业音频
96 kHz 高清音频
192 kHz 发烧级录音

根据奈奎斯特定理,采样率必须大于信号最高频率的两倍。人耳能听到 20kHz,所以 44.1kHz 是底线。我个人习惯,做语音产品用 16kHz 就够了,做音乐播放器至少 48kHz。

注意:采样率不匹配是音频开发中最常见的 bug。ALSA 驱动会尝试自动重采样,但会引入延迟和失真。我建议你在代码里显式设置采样率,别指望驱动帮你兜底。

2.5 位深度:动态范围的标尺

位深度,也叫采样精度。它决定了每个采样点能记录多少细节。

  • 8bit:256 级,噪音大,基本淘汰。
  • 16bit:65536 级,CD 标准,动态范围 96dB。
  • 24bit:1677 万级,动态范围 144dB,专业录音标配。
  • 32bit:浮点或定点,常用于内部处理。

你想想看,16bit 的音频,最响和最轻的声音之间只有 96dB 的差距。而 24bit 有 144dB,这意味着你可以录下更微弱的声音,同时保留更大的动态余量。

我记得有一次调试一个录音设备,发现录出来的声音总是有“沙沙”声。查了半天,发现是 ALSA 配置里把位深度设成了 S16_LE,而 Codec 硬件实际支持的是 S24_LE。数据被截断了,底噪自然就上来了。

2.6 硬件链路:数据怎么跑起来的?

最后,咱们串一下整个链路。从应用程序到喇叭,数据流是这样的:

  1. 应用程序:生成 PCM 数据(比如播放一个 WAV 文件)。
  2. ALSA 库:把数据传给内核驱动。
  3. DMA 控制器:从内存搬运数据到 Codec 的 FIFO 缓冲区。
  4. Codec 的 DAC:把数字信号转成模拟电压。
  5. 功放:放大信号,驱动喇叭或耳机。

反过来,录音就是逆过程:麦克风 → ADC → DMA → 内存 → 应用程序。

这里有个关键点:DMA 的缓冲区大小。缓冲区太小,CPU 频繁中断,容易产生 XRUN(欠载或溢出)。缓冲区太大,延迟就高。我一般做实时通话时,缓冲区设成 10ms 左右;做音乐播放,可以放宽到 50ms。

总结一下:声卡是逻辑设备,Codec 是物理芯片,DAC/ADC 是核心转换器。采样率和位深度决定了音质的天花板。搞懂这些,你再看 ALSA 的配置,就不会觉得那是天书了。

下一章,咱们就动手操作 ALSA 的 API,让这些硬件真正跑起来。