3. 音频信号基础:采样率、位深、声道、奈奎斯特定理、音频格式(WAV/PCM)在车载环境下的选择

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

说实话,做车载语音唤醒,很多人一上来就调模型、搞算法。但我得泼盆冷水——音频信号基础不牢,后面全是坑。我自己就吃过这个亏,项目都快交付了,结果发现唤醒率死活上不去,最后排查了三天,问题出在采样率配置上。嗯,从那以后,我每次做新项目,第一件事就是先把音频链路捋一遍。

这一章,咱们就把采样率、位深、声道、奈奎斯特定理这些基础概念,结合车载环境,一次性讲透。

3.1 采样率:每秒“拍”多少张照片?

采样率,说白了就是每秒钟对模拟声音信号“拍照”的次数。单位是 Hz(赫兹)。

比如 16kHz 采样率,就是一秒钟拍了 16000 张“声音照片”。

那车载环境该选多少?

我个人习惯,车载语音唤醒用 16kHz 就够了。为什么?

  • 人声的主要能量集中在 4kHz 以下。16kHz 采样率能覆盖 8kHz 的音频带宽,完全够用。
  • 更高的采样率(比如 48kHz)会带来更大的数据量,增加传输和处理的负担。车载 MCU 资源本来就紧张,没必要。

核心结论:车载唤醒场景,16kHz 是黄金采样率。既能保证唤醒率,又不浪费算力。

3.2 奈奎斯特定理:为什么采样率不能太低?

这里有个定理,叫奈奎斯特定理。它说:采样率必须大于信号最高频率的两倍,否则就会发生混叠。

混叠是什么?我举个例子。

你想想看,一个 7kHz 的声音信号,你用 10kHz 去采样。根据奈奎斯特定理,10kHz 只能覆盖 5kHz 的信号。那 7kHz 的信号会怎么样?它会“伪装”成一个 3kHz 的信号混进来。这就是混叠。

我在项目中遇到过,有同事为了省带宽,把采样率降到 8kHz。结果唤醒词里明明有高频辅音(比如“s”、“sh”),全被混叠成了低频噪声,唤醒率直接掉到 30%。

避坑指南:我曾经在某个项目中,麦克风阵列的模拟前端没有做抗混叠滤波器,结果高频噪声全部折叠进了语音频带。后来加了硬件滤波器,问题才解决。所以,硬件抗混叠滤波器 + 合适的采样率,缺一不可。

3.3 位深:每个“像素”有多少种颜色?

采样率决定了“拍多少张照片”,位深决定了“每张照片有多少种颜色”。

位深,也叫量化精度。常见的有 16-bit、24-bit、32-bit。

16-bit 意味着每个采样点有 2^16 = 65536 种可能的取值。动态范围大约是 96dB。

车载环境选多少?

我个人建议,16-bit 足够了。为什么?

  • 车载环境的信噪比(SNR)通常只有 60-80dB。16-bit 的 96dB 动态范围完全够用。
  • 24-bit 或 32-bit 虽然动态范围更大,但数据量也更大。而且,车载的噪声底噪(发动机、胎噪、风噪)本身就很高,更高的位深带来的收益微乎其微。
位深 动态范围 数据量(16kHz 单声道) 车载适用性
16-bit 96 dB 32 kB/s ✅ 推荐
24-bit 144 dB 48 kB/s ⚠️ 非必要
32-bit 192 dB 64 kB/s ❌ 浪费

小技巧:如果你在做唤醒词模型训练,用 16-bit 数据训练出来的模型,直接部署到 16-bit 的硬件上,效果最好。用 24-bit 数据训练,再量化到 16-bit,反而可能损失精度。

3.4 声道:单声道还是立体声?

车载环境,我强烈建议用单声道

你可能会问:“立体声不是更高级吗?”

其实不是。车载唤醒的核心是语音活动检测(VAD)和关键词识别,这些算法都是基于单声道信号设计的。立体声不仅不会提升唤醒率,还会带来两个问题:

  1. 数据量翻倍:立体声是两个声道,数据量是单声道的两倍。对车载 MCU 的存储和传输都是负担。
  2. 相位问题:如果两个麦克风采集的立体声信号有相位差,反而会干扰唤醒算法的处理。

我记得有一次,供应商提供的音频数据是立体声的,我直接合并成单声道后,唤醒率反而提升了 2%。

结论:车载唤醒,单声道 + 16kHz + 16-bit 是标准配置。别搞花里胡哨的。

3.5 音频格式:WAV vs PCM

这两个格式,其实是一回事。

PCM(脉冲编码调制)是原始音频数据的编码方式。它就是把模拟信号采样、量化后得到的数字数据,没有任何压缩。

WAV 是微软开发的一种音频容器格式。它可以在文件头里描述采样率、位深、声道数等信息,然后后面跟着 PCM 数据。

说白了,WAV 就是给 PCM 数据加了个“包装盒”。

车载环境怎么选?

  • 在内存中处理:直接用 PCM 裸数据。没有文件头,解析快,省内存。
  • 在文件系统中存储:用 WAV 格式。方便管理,也方便调试时用工具播放。

我自己的习惯是:

  • 唤醒词模型训练时,用 WAV 文件。
  • 部署到车机时,把唤醒词模板转成 PCM 裸数据,直接烧录到 Flash 里。

代码示例:读取 WAV 文件头,提取 PCM 数据(C 语言伪代码)

// WAV 文件头结构体
typedef struct {
    char     riff[4];        // "RIFF"
    uint32_t fileSize;       // 文件总大小 - 8
    char     wave[4];        // "WAVE"
    char     fmt[4];         // "fmt "
    uint32_t fmtSize;        // 格式块大小 (16 for PCM)
    uint16_t audioFormat;    // 1 = PCM
    uint16_t numChannels;    // 声道数
    uint32_t sampleRate;     // 采样率
    uint32_t byteRate;       // 字节率 = sampleRate * numChannels * bitsPerSample/8
    uint16_t blockAlign;     // 块对齐 = numChannels * bitsPerSample/8
    uint16_t bitsPerSample;  // 位深
    char     data[4];        // "data"
    uint32_t dataSize;       // PCM 数据大小
} WAVHeader;

// 读取 WAV 文件
int read_wav(const char *filename, int16_t **pcm_data, uint32_t *data_size) {
    FILE *fp = fopen(filename, "rb");
    WAVHeader header;

    fread(&header, sizeof(WAVHeader), 1, fp);

    // 校验 WAV 格式
    if (header.audioFormat != 1) {
        printf("不是 PCM 格式!\n");
        return -1;
    }

    // 分配内存并读取 PCM 数据
    *pcm_data = (int16_t *)malloc(header.dataSize);
    fread(*pcm_data, header.dataSize, 1, fp);

    *data_size = header.dataSize / sizeof(int16_t);

    fclose(fp);
    return 0;
}

注意:车载环境下的 WAV 文件,一定要确保是 16-bit、单声道、16kHz 的 PCM 编码。有些工具导出的 WAV 可能是 32-bit 浮点或者多声道,直接喂给唤醒算法会出问题。

3.6 车载环境下的综合选择建议

好了,咱们把前面讲的串起来。在车载环境下,音频信号的选择可以总结为一张表:

参数 推荐值 原因
采样率 16 kHz 覆盖人声带宽,节省算力
位深 16-bit 动态范围足够,数据量适中
声道 单声道 避免数据冗余和相位问题
音频格式 WAV(文件) / PCM(内存) WAV 方便管理,PCM 高效

最后,我再啰嗦一句:音频链路的一致性。你训练模型用的音频参数,和部署到车机上的音频参数,必须完全一致。采样率、位深、声道数,一个都不能差。否则,模型在实验室里跑得再好,上车就翻车。

下一章,咱们聊聊麦克风阵列的选型和布局。那也是个容易踩坑的地方。