2、数字音频基础:量化、编码、PCM与WAV格式解析
各位好,欢迎来到第二章。上一章我们聊了声音的物理本质和采样定理,算是把「模拟」那半边讲清楚了。这一章我们正式进入数字域,看看模拟信号是怎么变成一串串0和1的。
说白了,数字音频的核心就三件事:量化、编码、封装。我做了十几年音频处理,见过太多新手在这三个环节上踩坑。尤其是量化噪声和WAV头解析,几乎是每个入门者必过的坎。咱们一个一个来拆。
2.1 量化:从连续到离散的「舍入艺术」
采样把时间轴离散化了,但每个采样点的幅度还是连续的。量化要做的,就是把这种连续幅度值映射到有限个离散等级上。
举个例子。假设一个信号幅度范围是 -1V 到 +1V,我们用 3 bit 来量化。3 bit 能表示 2³ = 8 个等级。那么每个等级覆盖的电压范围就是 (1 - (-1)) / 8 = 0.25V。
实际信号落在哪个区间,我们就用该区间的代表值(通常是中点)来近似。这个过程,本质上就是舍入。
核心公式:
量化步长 Δ = (Vmax - Vmin) / 2^N
其中 N 是量化位数,Vmax 和 Vmin 是信号幅度的上下限。
量化位数越高,步长越小,精度越高。但代价是数据量成倍增长。我记得刚入行时做过一个项目,为了省存储空间,把 24 bit 的录音强行截成 8 bit。结果回放时底噪大得吓人,背景里全是「沙沙」声——那就是量化噪声。
2.1.1 量化噪声与信噪比
量化误差是不可避免的。你想想看,一个连续值被强行「挤」到最近的离散等级上,肯定有偏差。这个偏差就是量化噪声。
对于均匀量化(也就是等步长量化),量化噪声的功率可以近似为 Δ²/12。而信号的最大功率是 (Vmax - Vmin)² / 8。两者一除,就得到了理论上的最大信噪比:
SNR ≈ 6.02N + 1.76 dB
这个公式你肯定见过。每增加 1 bit,信噪比提升约 6 dB。CD 用的是 16 bit,理论 SNR 大约是 98 dB。人耳的动态范围大概在 120 dB 左右,所以 16 bit 对于消费级音乐来说基本够用,但专业录音棚通常用 24 bit,就是为了留足余量。
我的经验: 实际量化噪声往往比理论值大 3-6 dB。原因很简单——信号不是理想的正弦波,量化器也不是理想的。做降噪滤波器设计时,我习惯把量化噪声当作一个平坦的底噪来处理,但要注意它其实和信号是相关的,不是纯白噪声。
2.2 编码:把量化值变成二进制
量化完的数值,得用二进制表示出来。这个过程就是编码。最常见的编码方式是脉冲编码调制(PCM)。
PCM 编码其实很简单:每个采样点的量化值,直接转换成对应的二进制数。比如量化值是 127(假设是 8 bit 无符号),二进制就是 01111111。
但这里有个坑——有符号 vs 无符号。音频信号是交流信号,有正有负。如果用无符号整数表示,就得加一个直流偏置。CD 用的就是有符号 16 bit 整数,范围是 -32768 到 +32767。0 值对应静音。
我见过不少新手在写 WAV 解析器时,把有符号数当无符号读,结果波形全偏了,听起来像加了直流偏移的「噗噗」声。嗯,这个坑我年轻时也踩过。
2.2.1 常见的 PCM 编码格式
| 格式 | 位数 | 表示方式 | 典型应用 |
|---|---|---|---|
| 整数 PCM | 8 / 16 / 24 / 32 | 有符号或无符号整数 | WAV、AIFF、CD |
| 浮点 PCM | 32 / 64 | IEEE 754 浮点数 | 专业音频软件内部处理 |
| A-law / μ-law | 8 | 非线性量化 | 电话语音(G.711) |
浮点 PCM 在 DSP 处理中非常常见。它的动态范围极大,几乎不用担心溢出问题。但要注意,浮点运算的精度损失和整数不同,做定点化时得小心。
避坑指南: 我曾经在移植一个浮点降噪算法到嵌入式平台时,直接用了 16 bit 整数。结果算法完全失效——因为浮点滤波器系数需要很高的精度,16 bit 根本不够。后来改用 32 bit 定点数,才勉强跑起来。所以,编码格式的选择直接影响算法性能,别想当然。
2.3 PCM 与 WAV 格式解析
PCM 是编码方式,WAV 是文件容器。WAV 基于 RIFF(Resource Interchange File Format)结构,说白了就是一块一块的数据拼在一起。
一个标准的 WAV 文件包含三个主要块:
- RIFF 头:标识文件类型,总文件大小。
- fmt 块:描述音频格式信息(采样率、位数、声道数等)。
- data 块:实际的 PCM 采样数据。
下面是一个典型的 WAV 文件头结构(44 字节):
偏移量 长度 内容 说明
0 4 "RIFF" RIFF 标识
4 4 文件大小 - 8 整个文件减去前8字节
8 4 "WAVE" WAVE 标识
12 4 "fmt " fmt 块标识(注意有空格)
16 4 16 fmt 块大小(PCM 格式固定为16)
20 2 1 音频格式(1 = PCM)
22 2 2 声道数(1=单声道,2=立体声)
24 4 44100 采样率
28 4 176400 字节率 = 采样率 × 声道数 × 位深/8
32 2 4 块对齐 = 声道数 × 位深/8
34 2 16 位深
36 4 "data" data 块标识
40 4 数据大小 PCM 数据的总字节数
44 ... 数据开始 PCM 采样数据
这个结构我背得滚瓜烂熟。为什么?因为当年写一个实时音频播放器时,WAV 头解析错了,导致播放出来的声音全是「吱吱」的噪声。查了一整天,最后发现是 fmt 块大小字段读错了——有些软件写的不是 16,而是 18 或 40(扩展格式)。从那以后,我写解析器都会先检查 fmt 块大小,再做相应处理。
实用技巧: 解析 WAV 时,不要硬编码偏移量。应该按块结构来读:先读 4 字节块标识,再读 4 字节块大小,然后根据块大小读取块内容。这样即使遇到非标准 WAV 文件,也能正确解析。
2.4 本章知识体系
下面这张图把量化、编码、PCM 和 WAV 的关系串起来了。建议你多看几遍,理解每个环节的输入输出是什么。
2.5 小结
这一章我们走完了从模拟到数字的完整链路:采样 → 量化 → 编码 → 封装。量化决定了精度和噪声,编码决定了表示方式,WAV 则是我们最常接触的容器格式。
我个人建议,初学者最好亲手写一个 WAV 解析器。不用多复杂,能读出采样率、位深、声道数,然后把 PCM 数据打印成波形图就行。这个过程会让你对数字音频的理解深一个层次。