3、音频信号采集与回放:采样率与位深选择、ADC/DAC校准、数字音频接口(I2S/TDM)配置
好,咱们进入第三个核心环节。音频信号采集与回放,说白了就是助听器的“耳朵”和“嘴巴”。这部分要是搞砸了,后面算法再牛也白搭。我这些年调试过的板子,至少有一半的怪问题都出在这一块——要么是时钟没配好,要么是接口时序差了一点点。
3.1 采样率与位深:别盲目追求高参数
先聊聊采样率和位深。很多刚入行的工程师喜欢把参数往高了设,觉得这样“音质好”。其实在助听器这种低功耗、实时性要求高的场景里,选对参数比选高参数重要得多。
采样率怎么选?
助听器处理的音频范围,主要是人的语音区,大概在100Hz到8kHz之间。根据奈奎斯特定理,采样率至少得是最高频率的两倍。但实际工程中,我们通常会留点余量。
- 16kHz采样率:这是助听器行业最常用的。覆盖8kHz带宽,够用。而且16kHz是2的整数次幂,做FFT分析时特别方便。
- 24kHz或32kHz:如果产品定位高端,想保留更多高频细节(比如音乐模式),可以考虑。但代价是功耗和计算量都会上升。
- 48kHz:我个人不建议在助听器上用。功耗翻倍,但人耳根本听不出那点高频差异。除非你做的不是助听器,而是监听耳机。
位深选多少?
位深决定了动态范围。每增加1位,理论上动态范围提升约6dB。
- 16位:动态范围96dB。对于轻度到中度听力损失患者,够用了。很多老款助听器芯片内部就是16位处理。
- 24位:动态范围144dB。这是目前主流的选择。为什么?因为助听器里要做大量数字增益和压缩,位深不够的话,处理过程中会产生量化噪声,听起来就是“嘶嘶”声。
- 32位:除非你的ADC/DAC硬件原生支持32位,否则别用。软件模拟32位只会增加无谓的开销。
我的经验之谈: 量产测试时,我建议固定使用16kHz/24位。16kHz保证实时性,24位保证处理余量。别在生产线上用16位测试,然后指望用户用24位听——测试环境必须和真实使用环境一致。
3.2 ADC/DAC校准:不校准就是给自己挖坑
ADC和DAC芯片出厂时都有误差。增益误差、直流偏置、通道间失配……这些误差在助听器这种高精度设备里,会被放大得很明显。我曾经遇到过一批板子,左耳和右耳听到的音量不一样,查了三天,最后发现是ADC的增益校准没做。
校准什么?
- 直流偏置校准:输入为零时,ADC输出应该也是零。但实际会有几毫伏到几十毫伏的偏移。这个偏移会被后续的增益级放大,变成可闻的底噪。
- 增益校准:输入一个已知幅度的正弦波,测量ADC输出,计算出实际增益与理想增益的偏差。然后通过软件补偿。
- 相位校准:多通道系统(比如双麦克风阵列)里,每个通道的相位响应可能不同。这会影响波束成形的效果。
怎么校准?
生产测试时,我们会用一个高精度的音频分析仪(比如Audio Precision)作为信号源。流程大概是:
- 给ADC输入1kHz、-20dBFS的正弦波。
- 读取ADC输出的数字码流。
- 计算实际幅度与理论幅度的比值,得到增益误差。
- 计算直流分量,得到偏置误差。
- 将这两个误差值写入芯片的校准寄存器,或者存入Flash,上电时加载。
避坑指南: 我曾经在批量生产时发现,同一批次的ADC芯片,校准值差异很大。后来查了芯片手册才发现,校准值跟供电电压和温度都有关。所以我的建议是:在校准前,先让板子预热5分钟,等温度稳定了再测。否则你校准出来的值,到了用户耳朵里可能就不准了。
3.3 数字音频接口(I2S/TDM)配置
ADC和DAC跟主控芯片之间怎么传数据?最常用的就是I2S和TDM。这两个接口看着简单,但配置错了,声音要么是噪声,要么是静音。
I2S接口
I2S有三根线:位时钟(BCLK)、帧时钟(LRCK,也叫WS)、数据线(SD)。标准I2S协议里,数据在BCLK的下降沿变化,在上升沿采样。LRCK为低时传左声道,为高时传右声道。
配置时要注意几个参数:
- BCLK频率:BCLK = 采样率 × 位深 × 通道数 × 2(因为I2S每帧传两个通道)。比如16kHz、24位、立体声:BCLK = 16000 × 24 × 2 = 768kHz。
- 数据对齐方式:I2S标准是左对齐(MSB先传),但有些芯片支持右对齐或DSP模式。务必看芯片手册。
- 主从模式:谁提供时钟?通常主控做主机,ADC/DAC做从机。但有些Codec芯片也可以做主,这时候要小心时钟同步问题。
TDM接口
TDM其实就是I2S的“多通道版”。一根数据线上可以传4、8、16个通道。助听器里如果用了多麦克风阵列,或者要做双耳通信,TDM就派上用场了。
TDM配置比I2S复杂一点:
- 时隙分配:每个通道占用固定的时隙。比如8通道TDM,每个时隙传24位数据,那一个帧就是8×24=192个BCLK周期。
- 帧同步信号:TDM的帧同步信号(FSYNC)频率等于采样率。但它的脉冲宽度可以配置,有的芯片要求一个BCLK周期宽,有的要求一个帧周期宽。
- 数据延迟:有些TDM协议允许数据在帧同步信号之后延迟1个或2个BCLK周期再开始传。这个细节很容易被忽略。
警告: 配置TDM时,一定要确认所有通道的位深一致。我曾经见过一个项目,麦克风阵列用24位,但参考信号用16位,结果TDM总线上数据错位,整个系统出来的声音像“机器人说话”。
3.4 代码示例:I2S初始化配置(基于STM32 HAL库)
下面给一段实际项目中用过的I2S初始化代码。注意,这不是让你直接复制粘贴,而是理解配置思路。
// I2S配置结构体
I2S_HandleTypeDef hi2s3;
hi2s3.Instance = SPI3; // STM32上I2S复用SPI外设
hi2s3.Init.Mode = I2S_MODE_MASTER_TX; // 主控发送模式
hi2s3.Init.Standard = I2S_STANDARD_PHILIPS; // 飞利浦标准(即标准I2S)
hi2s3.Init.DataFormat = I2S_DATAFORMAT_24B; // 24位数据
hi2s3.Init.MCLKOutput = I2S_MCLKOUTPUT_DISABLE; // 主时钟输出,助听器里通常不用
hi2s3.Init.AudioFreq = I2S_AUDIOFREQ_16K; // 16kHz采样率
hi2s3.Init.CPOL = I2S_CPOL_LOW; // 时钟极性,低电平空闲
hi2s3.Init.ClockSource = I2S_CLOCK_PLL; // 使用PLL产生精确时钟
hi2s3.Init.FirstBit = I2S_FIRSTBIT_MSB; // MSB先传
if (HAL_I2S_Init(&hi2s3) != HAL_OK)
{
Error_Handler(); // 初始化失败,检查硬件连接和时钟配置
}
这段代码里,最容易被忽略的是AudioFreq和ClockSource。STM32的I2S时钟来自系统PLL,如果PLL配置不对,生成的BCLK频率会有偏差。比如你设16kHz,实际可能出来16.1kHz,人耳听不出,但做双耳同步时就会出问题。
调试小技巧: 用示波器量BCLK和LRCK的波形。BCLK应该是等宽的方波,LRCK应该是采样率频率的方波(比如16kHz)。如果波形上有毛刺或者占空比不对,先查时钟树配置,再查PCB走线。我遇到过好几次,都是因为BCLK走线太长,被其他信号串扰了。
3.5 生产测试中的关键检查项
最后,总结一下生产测试时,音频采集与回放部分必须检查的项目:
| 测试项 | 测试方法 | 合格标准 |
|---|---|---|
| 采样率精度 | 用频率计测LRCK | 误差 < ±0.1% |
| ADC直流偏置 | 输入端短路,读ADC输出 | 偏移 < ±5mV(折算到模拟输入) |
| ADC增益误差 | 输入1kHz正弦波,测输出幅度 | 误差 < ±0.5dB |
| DAC输出幅度 | 输出1kHz数字正弦波,测模拟输出 | 误差 < ±0.5dB |
| 通道间串扰 | 左声道输入信号,测右声道输出 | 串扰 < -80dB |
| I2S/TDM时序 | 示波器测BCLK、LRCK、SD | 建立时间/保持时间满足芯片手册 |
嗯,这一章内容不少。采样率、位深、校准、接口配置,每一个点都值得你花时间吃透。下一章我们会聊更具体的——助听器里的数字滤波器和增益控制。到时候你会发现,今天讲的这些采样和接口知识,是后面所有算法的基础。