第三章 数字信号处理基础:采样定理、量化、FFT与频谱分析、数字滤波器基础

各位同学,欢迎来到第三章。

这一章,是咱们整个ANC降噪算法的数学根基。说白了,你后面写的所有代码,都是在跟采样、量化、频谱、滤波器打交道。如果这章没吃透,后面调试ANC的时候,你会感觉像在迷雾里开车——完全不知道问题出在哪。

我个人习惯,在讲任何算法之前,先把这个“数字世界”和“模拟世界”的边界搞清楚。咱们开始。

3.1 采样定理:别让你的信号“说谎”

先问一个问题:麦克风采集到的模拟信号,怎么变成芯片能处理的0和1?

第一步就是采样。每隔一段时间,抓一个点的电压值。

那问题来了:抓多快才够?

奈奎斯特采样定理:采样频率 fs 必须大于信号最高频率 fmax 的两倍。

公式:fs > 2 * fmax

我在项目中遇到过一件事。有一次调试前馈ANC,低频降噪效果很好,但到了1kHz以上,不仅没降噪,反而把噪声放大了。查了半天,发现是采样率设成了48kHz,但ADC前端的抗混叠滤波器没做好,导致高频噪声折叠进了低频段。嗯,这就是典型的“混叠”现象。

避坑指南:我曾经因为省成本,用了便宜的RC低通滤波器做抗混叠,结果高频噪声折叠后,ANC算法把折叠后的假信号当成了真实噪声去抵消,反而引入了新的噪声。记住:抗混叠滤波器不是摆设,它是采样定理的第一道防线。

在TWS耳机里,ANC通常处理20Hz到2kHz的噪声。所以采样率一般用48kHz或96kHz。48kHz已经能覆盖到24kHz,绰绰有余。但为什么有人用96kHz?为了给数字滤波器留出更多的过渡带空间,这个后面会讲。

3.2 量化:精度和成本的博弈

采样是把时间离散化,量化是把幅度离散化。

你想想看,一个模拟电压,比如1.2345V,你用8位ADC去量化,只能表示256个等级。那1.2345V就只能近似成1.23V或者1.24V。这个误差,就是量化噪声。

量化位数 量化等级数 动态范围(理论) 典型应用
16-bit 65536 96 dB CD音质、ANC参考麦克风
24-bit 16777216 144 dB 高端音频ADC、专业录音
32-bit 约43亿 192 dB 浮点DSP内部处理

在TWS耳机里,ADC和DAC通常是16-bit或24-bit。我个人建议,如果芯片算力允许,尽量用24-bit。为什么?因为ANC算法对相位非常敏感,量化噪声虽然听起来不大,但经过反馈环路之后,可能会被放大。

小技巧:我曾经在调试一款低功耗芯片时,发现ANC底噪偏大。后来把ADC从16-bit换成24-bit,底噪立刻降了6dB。代价是功耗多了0.5mA,但效果值得。所以,量化位数不是越高越好,但也不能太低,16-bit是底线。

3.3 FFT与频谱分析:把时间信号“翻译”成频率

时域信号你看不出噪声的分布。比如一个嗡嗡声,你只知道它在响,但不知道是100Hz还是200Hz。FFT就是干这个的——把信号从时域变到频域。

FFT的核心公式其实不复杂,但咱们做工程的不需要死磕数学推导。你只需要记住几个关键参数:

  • FFT点数(N): 决定了频率分辨率。分辨率 = fs / N。比如48kHz采样,1024点FFT,分辨率就是46.875Hz。
  • 频率范围: 0 到 fs/2。超过fs/2的部分是镜像,没用。
  • 窗函数: 直接做FFT会有频谱泄露。加窗可以抑制旁瓣。

我给你们看一段我在ANC调试中常用的频谱分析代码。这段代码我用了很多年,简单实用:

// 简单的FFT频谱分析,用于ANC调试
// 输入:时域数据指针,FFT点数
// 输出:频谱幅度数组

void calc_spectrum(float *time_data, float *mag_spectrum, int fft_size) {
    // 1. 加汉宁窗,减少频谱泄露
    for (int i = 0; i < fft_size; i++) {
        float window = 0.5f * (1.0f - cosf(2 * M_PI * i / (fft_size - 1)));
        time_data[i] *= window;
    }

    // 2. 执行FFT(这里调用芯片厂商提供的FFT库)
    arm_rfft_fast_instance_f32 fft_inst;
    arm_rfft_fast_init_f32(&fft_inst, fft_size);
    arm_rfft_fast_f32(&fft_inst, time_data, fft_output, 0); // 0表示正变换

    // 3. 计算幅度谱
    for (int i = 0; i < fft_size / 2; i++) {
        float real = fft_output[2 * i];
        float imag = fft_output[2 * i + 1];
        mag_spectrum[i] = sqrtf(real * real + imag * imag);
    }
}

重点:在ANC调试中,我习惯用频谱分析仪看三个信号:参考噪声、误差麦克风信号、以及扬声器输出。通过对比这三个频谱,你能直观地看到ANC在哪些频率生效,哪些频率反而被放大。这就是所谓的“频域调试法”。

3.4 数字滤波器基础:FIR与IIR

滤波器是ANC的核心。没有滤波器,你没法对噪声做精确的相位和幅度调整。

3.4.1 FIR滤波器:稳定,但计算量大

FIR的全称是有限脉冲响应。它的特点是:

  • 绝对稳定: 没有反馈,不会发散。
  • 线性相位: 所有频率的延迟时间一样,不会造成相位失真。
  • 计算量大: 阶数越高,需要的乘加运算越多。

在ANC中,FIR常用于参考路径的建模。比如,你需要知道噪声从参考麦克风到扬声器的声学路径,这个路径通常用FIR滤波器来模拟。

// FIR滤波器实现(直接型)
// 输入:新样本x[n],滤波器系数b[0..N-1],状态缓冲区
// 输出:滤波结果y[n]

float fir_filter(float x, float *b, float *state, int N) {
    float y = 0.0f;

    // 更新状态缓冲区
    for (int i = N - 1; i > 0; i--) {
        state[i] = state[i - 1];
    }
    state[0] = x;

    // 计算卷积
    for (int i = 0; i < N; i++) {
        y += b[i] * state[i];
    }

    return y;
}

个人经验:我曾经在一个项目里,用128阶的FIR做路径建模。结果芯片算力不够,跑完一个样本需要200个时钟周期,而采样间隔只有20.8微秒(48kHz)。最后不得不把阶数降到64阶,牺牲了一点精度,换来了实时性。所以,选FIR阶数时,一定要先算算你的MIPS预算。

3.4.2 IIR滤波器:高效,但小心不稳定

IIR的全称是无限脉冲响应。它引入了反馈,所以:

  • 效率高: 同样的滤波效果,IIR的阶数只有FIR的十分之一甚至更少。
  • 可能不稳定: 反馈系数如果设计不当,滤波器会自激振荡。
  • 非线性相位: 不同频率的延迟不一样,这在ANC中需要特别小心。

在ANC中,IIR常用于均衡器和陷波器。比如,你想在某个特定频率(如200Hz的引擎轰鸣)做深度衰减,用IIR陷波器最合适。

// 二阶IIR滤波器(双二阶滤波器)
// 系数:b0, b1, b2, a1, a2
// 状态:w0, w1, w2

float biquad_filter(float x, float *coeff, float *state) {
    float b0 = coeff[0], b1 = coeff[1], b2 = coeff[2];
    float a1 = coeff[3], a2 = coeff[4];

    float w = x - a1 * state[0] - a2 * state[1];
    float y = b0 * w + b1 * state[0] + b2 * state[1];

    // 更新状态
    state[1] = state[0];
    state[0] = w;

    return y;
}

避坑指南:我曾经在调试反馈ANC时,用了IIR滤波器做相位补偿。结果因为系数计算时舍入误差,导致滤波器在1.2kHz处产生了自激振荡。耳机里直接发出了刺耳的啸叫声,把测试工程师吓了一跳。从那以后,我每次用IIR,都会在定点仿真时检查极点是否在单位圆内。记住:IIR的稳定性是头等大事。

3.5 本章小结

好了,这一章的内容就这些。我帮你理一下重点:

  • 采样定理: 采样率至少是信号最高频率的两倍。别忘了抗混叠滤波器。
  • 量化: 16-bit是底线,24-bit更安全。量化噪声会影响ANC的底噪。
  • FFT: 频谱分析是ANC调试的“眼睛”。学会看频谱,你就能找到噪声的精确位置。
  • FIR vs IIR: FIR稳定但计算量大,IIR高效但要注意稳定性。ANC中两者都会用到,看场景选择。

下一章,我们会进入ANC的核心——自适应滤波算法。你会看到,LMS、NLMS这些算法是怎么一步步把噪声“吃掉”的。到时候,你会感谢今天打下的数字信号处理基础。

咱们下章见。