WAVE、RIFF 与 PCM

理解 WAV 文件头、chunk 结构和常见编码方式

Posted by Yvain Zhang on October 28, 2021 主题:技术

WAV 经常被直接理解成“无损音频文件”。这个说法不算错,但不够完整。更准确一点:

  • WAV 是文件格式
  • PCM 是最常见的其中一种音频数据表示

很多人调音频时,真正绕晕的地方不是采样率,而是没把“容器”和“编码”分开。WAVE 这一类格式正好很适合把这个问题讲清楚。

1. WAV 到底是什么

WAV 对应的是 WAVEform Audio File Format。它本质上是 RIFF 文件结构在音频场景下的一种具体使用方式。

所以一个 WAV 文件,先是一个 RIFF 文件,然后它的 Form Type 被指定成 WAVE

这句话的实际含义是:

  • WAV 不是单纯一段 PCM 裸数据
  • 它外面还有一层有结构的文件壳

2. 为什么很多人把 WAV 和 PCM 混在一起

因为工程里最常见的 WAV,确实就是“RIFF + WAVE + PCM 数据”。

于是大家很容易把两件事说成一件事:

  • WAV:描述文件怎么组织
  • PCM:描述样本怎么编码

在多数播放器和工具里,你看到一个 .wav 文件,默认猜它里面是 PCM,通常没问题;但严格说,WAV 也可以放别的音频编码。

3. RIFF 是什么

RIFF 可以先理解成一套块结构文件格式。它的基本单位叫 chunk

每个 chunk 都大体长这样:

  • 4 字节标识
  • 4 字节长度
  • 后面跟具体数据

这种结构的好处很明显:

  • 可扩展
  • 容易跳过不认识的块
  • 适合不同类型的数据共存

也正因为这样,RIFF 不只用在 WAV,还用在别的多媒体格式里。

4. WAV 文件里最常见的几个 chunk

一个常见 WAV 文件,通常会有这几个部分:

  • RIFF
  • fmt
  • data
  • 可能还有 fact

RIFF chunk

它是整个文件的总入口,告诉你:

  • 这是一个 RIFF 文件
  • 它里面装的是 WAVE

fmt chunk

这是最关键的描述块之一。播放器、解码器能否正确解释音频数据,主要看这里。

它通常包含:

  • 编码格式
  • 声道数
  • 采样率
  • 每秒字节率
  • 块对齐
  • 位深

data chunk

真正的音频样本一般就在这里。

fact chunk

当 WAV 里装的是压缩格式时,常会需要 fact 块补充信息,比如采样总数。

5. PCM 在这里扮演什么角色

PCM 是最基础的数字音频表示方式之一。可以把它看成:

  • 模拟信号被采样
  • 采样值被量化
  • 量化结果按固定方式编码存下来

它的优点就是简单直接,解码成本低;缺点也很明显,体积大。

所以一个典型的 PCM WAV 文件,本质上就是:

RIFF 容器 + WAVE 标识 + fmt 参数 + data 区中的 PCM 样本

6. WAV 一定是未压缩的吗

不一定。

虽然最常见的 WAV 是 PCM,但 WAV 这个容器也可以装:

  • PCM
  • IEEE float
  • A-law
  • Mu-law
  • 其他扩展格式

这也是为什么有时候你看到两个 .wav 文件,播放器都能播,但它们对接不同软件时兼容性不一样。问题不在后缀,而在 fmt 里写的编码方式。

7. 需要重点理解的几个字段

SampleRate

采样率,决定每秒取多少个样本。

NumChannels

声道数,单声道、双声道、多声道都靠这个字段区分。

BitsPerSample

位深,决定每个采样值占多少位。

ByteRate

它能帮助你快速估算流速和缓存大小,通常等于:

SampleRate * NumChannels * BitsPerSample / 8

BlockAlign

它描述一次样本对齐的最小单位。多声道场景里,这个值很重要,因为音频数据不是单个样本孤立存放,而是按帧对齐交错排列。

8. 多声道 PCM 在 data 里怎么存

多声道 PCM 一般是交错存放的。

如果是双声道,常见顺序就是:

  • 左声道第 1 个样本
  • 右声道第 1 个样本
  • 左声道第 2 个样本
  • 右声道第 2 个样本

这件事在做裸数据提取、声道拆分或自己写解析器时很容易踩坑。因为如果你把整段字节流当成“某一个声道连续存储”,结果一定不对。

9. 扩展格式块为什么存在

当简单的 fmt 信息不够表达实际格式时,就会用到扩展块,例如:

  • 声道更多
  • 位深不是常规场景
  • 实际有效位数和存储位数不完全一致
  • 需要更明确地表达声道布局

这也是为什么同样叫 WAV,有的文件头特别短,有的文件头更复杂。

10. 工程里最常见的几个问题

明明是 .wav,结果播放器不认

通常先看:

  • fmt 里是不是标准 PCM
  • 是否用了某些扩展格式
  • fact 等附加块是否齐全

时长算不对

优先核对:

  • data 区大小
  • ByteRate
  • 声道数和位深是否一致

采样听起来有杂音

常见方向有:

  • 采样率解释错了
  • 位深解析错了
  • 有符号 / 无符号理解错了
  • 多声道交错顺序处理错了

11. 总结

理解 WAV 最重要的不是背结构体,而是先把三层关系分开:

  • RIFF:文件块结构
  • WAVE:这是音频文件实例
  • PCM:最常见的样本编码方式

这层关系一清楚,后面再去看 fmtdatafact 这些块,就不容易混乱。做播放器、转码、录音链路或者问题排查时,也更容易知道自己是在处理“容器问题”还是“编码问题”。