2. 语音信号基础

硬件接口这块,说实话是联调中最容易出幺蛾子的地方。很多算法工程师觉得这是硬件的事,但等你拿着示波器在产线上一蹲就是半天的时候,你就明白了——不懂接口时序,你连问题出在哪都说不清楚。

我最早做 Codec 驱动的时候,就吃过一次大亏。板子回来,I2S 数据死活不对,声音全是噪声。查了三天,最后发现是 BCLK 极性配反了。嗯,从那以后,我拿到任何 Codec 的第一件事,就是先把接口时序图吃透。

2.1 I2S 接口:最通用的音频总线

I2S(Inter-IC Sound)是飞利浦在 80 年代定义的音频总线标准。说白了,它就是用来在芯片之间传数字音频的。你想想看,ADC 采集到的 PCM 数据,要通过 I2S 送给 DSP 或者 SoC;DSP 处理完,再通过 I2S 送给 DAC 播放。整个语音链路,I2S 就是那条最核心的马路。

I2S 总线有三根核心信号线:

  • SCK / BCLK(位时钟):每个时钟周期传输一个 bit 的数据。频率 = 采样率 × 位深 × 通道数。
  • WS / LRCLK(帧时钟 / 左右声道选择):高电平表示左声道,低电平表示右声道(或者反过来,看配置)。频率 = 采样率。
  • SD / DATA(串行数据):数据线,可以是输入(SDI)或输出(SDO)。

标准的 I2S 时序有个关键特征:数据在 BCLK 的下降沿变化,在上升沿被采样。而且,WS 切换后,数据会延迟一个 BCLK 周期才开始传输。这个延迟很多人会忽略,但我在调试时发现,有些非标的 Codec 并不遵守这个延迟规则,需要你在驱动里做调整。

关键参数速查表:

参数 典型值 说明
BCLK 频率 1.024 MHz ~ 24.576 MHz 取决于采样率和位深
LRCLK 频率 8 kHz ~ 192 kHz 等于采样率
数据格式 I2S / Left-Justified / Right-Justified 主流是 I2S 标准格式
位深 16 / 24 / 32 bit 注意有效位对齐方式

我的习惯:拿到 Codec 的 datasheet,先看时序图里的 BCLK 和 LRCLK 的相位关系。有些 Codec 要求 LRCLK 在 BCLK 的上升沿变化,有些要求下降沿。配错了,数据就全乱了。

2.2 TDM 接口:多通道音频的利器

TDM(Time Division Multiplexing)本质上就是 I2S 的扩展版。当你的系统需要同时处理 4 个、8 个甚至 16 个麦克风通道时,I2S 就不够用了——它只能传两个声道。TDM 通过在一个帧周期内划分多个时隙(Slot),每个时隙承载一个通道的数据,从而实现多通道传输。

TDM 的信号线和 I2S 一样,也是三根:BCLK、FS(帧同步,相当于 LRCLK)、DATA。但时序上有个重要区别:

  • FS 频率 = 采样率,但 FS 的脉冲宽度可以配置。常见的有 1-BCLK 宽度(短帧)和 1/2 帧宽度(长帧)。
  • 每个时隙通常占用 16、24 或 32 个 BCLK 周期。
  • 时隙数量 = 通道数。比如 8 通道 TDM,每个帧周期有 8 个时隙。

我在项目中遇到过最头疼的问题,就是 TDM 的时隙对齐。有一次,Codec 输出的数据总是偏移了一个时隙,导致通道 A 的数据跑到了通道 B 的位置。查了半天,发现是 Codec 的 TDM 配置寄存器里,时隙起始位置设错了。所以,我建议你在调试 TDM 时,先用示波器抓一下 FS 和 DATA 的波形,确认每个时隙的起始点。

我曾经踩过的坑:某款 Codec 的 TDM 模式要求 FS 在 BCLK 的上升沿有效,但 SoC 的 TDM 控制器默认是下降沿有效。两边各说各话,数据根本对不上。解决方案是在 SoC 的 DMA 配置里做数据重排,或者在 FPGA 里加一个 BCLK 反相器。我选了后者,因为改驱动太麻烦。

2.3 PDM 接口:数字麦克风的标配

PDM(Pulse Density Modulation)和 I2S/TDM 完全不同。它不是传 PCM 数据,而是传一种 1-bit 的脉冲密度调制信号。说白了,就是用一串 0 和 1 的密度来表示模拟信号的幅度。PDM 麦克风内部自带 Σ-Δ 调制器,直接输出这种脉冲流。

PDM 接口只有两根线:

  • PDM_CLK:时钟线,由主设备(SoC/DSP)提供。频率通常是 1.024 MHz ~ 4.8 MHz。
  • PDM_DATA:数据线,麦克风输出。一个时钟周期输出一个 bit。

PDM 数据需要经过 抽取滤波器(Decimation Filter) 才能转换成 PCM 数据。这个滤波器通常集成在 SoC 的 PDM 控制器里,或者由 DSP 软件实现。抽取率决定了最终的 PCM 采样率。比如,PDM_CLK = 2.048 MHz,抽取率 = 64,那么输出采样率 = 2.048 MHz / 64 = 32 kHz。

PDM 与 I2S 的对比:

特性 PDM I2S
数据格式 1-bit 脉冲密度 多 bit PCM
时钟频率 高(MHz 级) 较低(kHz ~ MHz)
通道数 通常单声道或立体声 立体声(TDM 可扩展)
抗干扰能力 强(数字信号) 中等
后处理 需要抽取滤波器 直接使用

PDM 接口的时序相对简单,但有一个容易忽略的点:建立时间(Setup Time)和保持时间(Hold Time)。PDM 麦克风对时钟的抖动比较敏感,如果时钟质量不好,会导致 SNR 下降。我建议你在 PCB 布局时,把 PDM_CLK 走线尽量短,远离电源和高速数字信号。

2.4 三种接口的选型与配置实战

在实际项目中,怎么选?我一般按这个逻辑来:

  1. 通道数 ≤ 2:优先用 I2S。简单、成熟、兼容性好。
  2. 通道数 ≥ 4:上 TDM。省引脚,一根数据线搞定所有通道。
  3. 麦克风是数字 MEMS 麦克风:用 PDM。但要注意 SoC 是否内置了 PDM 控制器和抽取滤波器。

配置的时候,我习惯先做一件事:核对时钟树。把 SoC 的主时钟、PLL 分频、Codec 的 MCLK 和 BCLK 的关系画出来。很多联调问题,根源就是时钟频率算错了。比如,你设了 48 kHz 采样率、24 bit 位深、2 通道,BCLK 应该是 48k × 24 × 2 = 2.304 MHz。但如果你 Codec 的 MCLK 是 12.288 MHz,分频比设成 4,得到 3.072 MHz,那就对不上了。

我的调试流程:

  • 第一步:用示波器抓 BCLK 和 LRCLK/FS,确认频率和相位正确。
  • 第二步:抓 DATA 线,看是否有数据跳变。如果 DATA 一直为高或低,说明 Codec 没输出数据。
  • 第三步:用逻辑分析仪解码 I2S/TDM/PDM 数据,确认数据格式和通道映射。
  • 第四步:如果数据有噪声,检查时钟抖动和电源纹波。

下面这张图,是我自己总结的接口选型与时钟配置流程,你可以参考一下:

音频接口选型与时钟配置流程 音频接口选型与时钟配置流程 确定音频需求 通道数? I2S 接口 立体声 TDM 接口 多通道 计算 BCLK = Fs × 位深 × 通道 配置 Codec 时钟与格式 示波器验证时序 注意:PDM 麦克风需额外 配置抽取滤波器参数

2.5 常见问题与避坑指南

最后,我把自己这些年遇到过的接口问题整理了一下,希望能帮你少走弯路:

  • BCLK 极性反了:数据在错误的时钟沿被采样。症状是声音全是噪声。解决方案:检查 Codec 的 BCLK 极性寄存器,或者 SoC 的 I2S 控制器配置。
  • LRCLK 相位不对:左右声道数据互换。症状是立体声听起来左右反了。解决方案:在驱动里交换左右声道数据,或者调整 LRCLK 的极性。
  • TDM 时隙偏移:通道数据错位。症状是多个麦克风的声音混在一起。解决方案:用逻辑分析仪抓出每个时隙的起始点,调整 Codec 的时隙偏移寄存器。
  • PDM 时钟抖动过大:SNR 下降,底噪升高。解决方案:优化 PCB 布局,给 PDM_CLK 加 RC 滤波,或者使用专用的时钟缓冲器。
  • MCLK 频率不匹配:Codec 无法锁定 PLL,导致无输出。解决方案:核对 Codec 支持的 MCLK 频率列表,选择 SoC 能提供的频率。

我曾经犯过的错:有一次,我为了省事,直接用 SoC 的 GPIO 模拟 I2S 时序。结果因为 GPIO 的翻转速度不够,BCLK 频率上不去,导致采样率只能跑到 16 kHz。后来还是老老实实用了硬件 I2S 控制器。所以,能用硬件 IP 就别用 GPIO 模拟,除非你只是做原型验证。

嗯,接口时序这块,说难不难,说简单也不简单。关键是要把 datasheet 吃透,把示波器用好。下次你遇到 Codec 不出声的问题,别急着怀疑芯片坏了,先看看 BCLK 有没有、LRCLK 对不对、数据线有没有跳变。八成问题就出在这三根线上。