1. Codec 基础与选型:先搞懂芯片再动手

做语音算法移植,第一步不是写代码,而是读懂你手里的 Codec 芯片。我见过太多人上来就调 I2C 寄存器,结果声音出不来,折腾半天发现是时钟配错了。说白了,Codec 就是个模拟和数字之间的翻译官——你得知道它怎么听、怎么说、怎么传话。

1.1 Codec 核心架构:信号从哪进,从哪出

不管你是用 WM8960、ES8311 还是 TLV320AIC 系列,内部骨架都差不多。我习惯把 Codec 拆成三块来看:

  • 模拟输入路径:麦克风或 Line-in 进来的微弱信号,经过 PGA(可编程增益放大器)、混音器、再到 ADC。
  • 数字处理核心:ADC 把模拟信号转成数字流,DAC 把数字流转回模拟。中间可能插着数字滤波器、音量控制、EQ 等。
  • 模拟输出路径:DAC 出来的信号经过混音、音量调节、功放,最后驱动耳机或喇叭。

关键认知:语音算法移植时,你关心的其实是数字域和模拟域的接口——ADC 采出来的数据长什么样?DAC 要吃什么样的数据?中间的时钟怎么对齐?这些搞清楚了,移植就成功了一半。

拿 WM8960 举例,它内部有 3 路模拟输入、2 路模拟输出,还带个 D 类功放。ES8311 则更精简,适合低功耗场景。TLV320AIC 系列(比如 AIC3106)在工业设备里很常见,输入输出通道更灵活。选型时我一般先看项目需要几路麦克风、几路输出,再决定。

1.2 ADC/DAC 路径:信号链上的每个环节

ADC 路径说白了就是:模拟信号 → 抗混叠滤波 → 采样保持 → 量化编码 → 数字输出。DAC 路径反过来:数字输入 → 插值滤波 → 数模转换 → 重建滤波 → 模拟输出。

嗯,这里有个坑。我在项目里遇到过,ADC 的采样率设成 48kHz,但数字接口的 BCLK 算错了,导致数据对不齐。你想想看,ADC 采了 48k 个样本,但 I2S 总线每帧只传 32 位,BCLK 频率不够,数据就丢了。

我的习惯:拿到 Codec 数据手册,先看 ADC 和 DAC 的采样率范围,再看它们是否支持同步或异步模式。异步模式意味着 ADC 和 DAC 可以用不同的时钟,这在某些双工场景下很有用。

1.3 I2S/PCM 接口:数字音频的运输通道

I2S 和 PCM 是 Codec 和主控(MCU/DSP)之间传音频数据的标准接口。I2S 最常见,它用三根线:

  • BCLK(位时钟):每个 bit 跳一次,频率 = 采样率 × 位深 × 通道数。
  • LRCK(帧时钟):左右声道切换,频率 = 采样率。
  • DIN/DOUT(数据线):串行传输音频数据。

举个例子,48kHz 采样率、16bit 位深、双声道:BCLK = 48k × 16 × 2 = 1.536MHz。LRCK 就是 48kHz。这个关系必须算对,否则 Codec 和主控各说各话。

我曾经踩过的坑:WM8960 的 BCLK 极性可以配置,默认是上升沿采样。但我用的主控 SPI 接口是下降沿输出数据,结果两边相位反了,声音全是噪声。后来我加了个逻辑分析仪才抓到问题。所以,I2S 的极性和延迟参数一定要核对。

PCM 接口和 I2S 类似,但时序略有不同。PCM 通常用于多通道(比如 8 通道 TDM),每个帧里传多个 slot。TLV320AIC 系列就支持这种模式,适合阵列麦克风。

1.4 MCLK/BCLK/LRCK 时钟关系:三角恋要理清

Codec 通常需要三个时钟:

时钟 全称 典型频率 作用
MCLK 主时钟 12.288MHz / 24.576MHz 驱动 ADC/DAC 内部逻辑,通常由外部晶振或主控提供
BCLK 位时钟 1.536MHz / 3.072MHz 控制数据线上的 bit 传输节奏
LRCK 帧时钟 48kHz / 44.1kHz 区分左右声道,频率等于采样率

它们之间的关系是:MCLK 必须是 LRCK 的整数倍,通常是 256 倍或 512 倍。比如 48kHz 采样率,MCLK 用 12.288MHz(256×48k)。BCLK 则等于 LRCK × 位深 × 通道数。

避坑指南:有些 Codec(比如 ES8311)支持自动时钟分频,你只要给个 MCLK,它内部能自己生成 BCLK 和 LRCK。但 WM8960 需要你手动配分频系数。我建议你画个时钟树,把每个时钟的源和分频比写清楚,调试时一目了然。

1.5 模拟输入输出通道配置:别让信号走错路

Codec 的模拟通道通常有多个输入源(麦克风、Line-in、AUX)和多个输出目标(耳机、喇叭、Line-out)。配置时要注意:

  • 输入选择:通过寄存器选择哪个引脚接入 PGA。比如 WM8960 的 IN1 可以接麦克风或 Line-in,但偏置电压不同。
  • 增益控制:PGA 增益范围一般是 -12dB 到 +35dB,步进 0.5dB 或 1dB。麦克风信号弱,需要加增益;Line-in 信号强,可能得衰减。
  • 混音器:多个输入可以混合到同一个 ADC 通道,或者多个输出源混合到同一个输出引脚。这在做回声消除时特别有用——你需要把参考信号混入输出路径。
  • 输出驱动:耳机输出需要驱动 32Ω 负载,喇叭输出可能需要 D 类功放。TLV320AIC 系列有专门的耳机检测引脚,可以自动切换输出模式。

我的经验:配置模拟通道时,先把所有输入静音,然后逐个打开,用示波器看波形。这样能快速定位是哪个环节出了问题。别一次性把所有通道都打开,否则噪声从哪来的你都找不到。

1.6 一张图看懂 Codec 核心结构

下面这张图是我自己总结的,把 Codec 的核心模块和信号流画清楚了。你移植算法时,脑子里要有这张图。

Codec 核心架构图 Codec 核心架构与信号流 模拟输入 MIC / Line-in PGA 增益控制 ADC 模数转换 I2S / PCM 数字输出 I2S / PCM 数字输入 DAC 数模转换 混音器 音量 / 混合 模拟输出 耳机 / 喇叭 时钟管理:MCLK / BCLK / LRCK 控制接口:I2C / SPI 说明 ADC 路径:模拟→数字 DAC 路径:数字→模拟

1.7 选型时我关注的几个点

最后聊聊选型。不是最贵的 Codec 就最好,关键看匹配:

  1. 采样率和位深:语音算法通常用 16kHz/16bit 或 48kHz/24bit。如果要做高清语音,选支持 24bit 的 Codec。
  2. 信噪比(SNR):ADC 的 SNR 最好在 90dB 以上,否则底噪会吃掉小信号。ES8311 的 SNR 是 93dB,够用。
  3. 电源和功耗:电池供电的设备,选低功耗模式。WM8960 有省电模式,但切换时会有 pop 声,需要软件处理。
  4. 封装和引脚:QFN 封装小,但焊接麻烦。TSSOP 好焊,但占面积。看你的 PCB 空间。
  5. 驱动和文档:我吃过亏——选了颗小众 Codec,结果 Linux 驱动不完善,自己写了三天。现在优先选有现成驱动的。

一句话总结:Codec 选型就是平衡性能、功耗、成本和开发难度。先把时钟和接口搞明白,后面移植算法时你会感谢自己的。