跳转至

WAV 文件格式详解

1、WAV 文件概述

WAV 是微软公司开发的一种音频格式文件,用于保存 Windows 平台的音频信息资源,它符合 资源互换文件格式(Resource Interchange File Format,RIFF)文件规范。

主要特点:

  • 高质量音频:标准格式化的 WAV 文件采用 44.1kHz 采样频率,16 位量化数字,音质与 CD 相差无几

  • 无损存储:通常用来保存 PCM 格式的原始音频数据,被称为无损音频

  • 格式灵活:也可以存储其它压缩格式的音频数据

2、WAV 文件格式结构

WAV 符合 RIFF 文件格式标准,其基本组成单元是 chunk(数据块)。

2.1 基本结构

一个 WAV 文件通常包含以下数据块(按顺序排列):

  1. RIFF chunk(必须)

  2. Format chunk(必须)

  3. Fact chunk(可选,附加块)

  4. Data chunk(必须)

2.2 整体结构图

┌─────────────────────────────────────────────────┐
│                  RIFF Chunk                      │
│  ID: "RIFF"    Size: 文件总大小-8  Type: "WAVE"  │
├─────────────────────────────────────────────────┤
│               Format Chunk (必须)                 │
│  ID: "fmt "    Size: 16/18/40  音频格式信息       │
├─────────────────────────────────────────────────┤
│               Fact Chunk (可选)                  │
│  ID: "fact"    Size: ≥4        采样总数          │
├─────────────────────────────────────────────────┤
│                Data Chunk (必须)                 │
│  ID: "data"    Size: N         音频数据          │
└─────────────────────────────────────────────────┘

3、各个 Chunk 的具体内容

3.1 RIFF Chunk(资源交换文件块)

字段 大小 值/含义 示例(十六进制)
ID 4 字节 "RIFF"(固定) 52 49 46 46
Size 4 字节 ChunkData 字段的大小(文件总大小 - 8) F4 FE 83 01
ChunkData - 包含 FormType 和其他 chunk -
FormType 4 字节 "WAVE"(固定) 57 41 56 45

3.2 Format Chunk(格式块)

字段 大小 含义 说明
ID 4 字节 "fmt "(注意最后的空格) 66 6D 74 20
Size 4 字节 Data 字段的大小 一般为 16(PCM)
Data 字段内容
audio_format 2 字节 音频数据格式 1 = PCM,其他见第 4 节
channels 2 字节 声道数 1 = 单声道,2 = 立体声
sample_rate 4 字节 采样频率(Hz) 如 44100 = 44 AC 00 00
bytes_per_sec 4 字节 音频码率 每秒字节数 = 声道数 × 采样率 × 位深度 / 8
block_align 2 字节 块对齐 每个采样点字节数 = 声道数 × 位深度 / 8
bits_per_sample 2 字节 量化位数 16, 24, 32 等
扩展字段
cbSize 2 字节 扩展块长度 0 或 22(可选)
cbContent 0/22 字节 扩展块内容 具体见第 5 节

3.3 Fact Chunk(可选)

字段 大小 含义 说明
ID 4 字节 "fact" 66 61 63 74
Size 4 字节 数据字段长度 最小为 4
Data 4 字节 采样总数 每个声道的采样总数

注意:采用压缩编码的 WAV 文件必须包含 Fact chunk。

3.4 Data Chunk(数据块)

字段 大小 含义 说明
ID 4 字节 "data" 64 61 74 61
Size 4 字节 音频数据长度 N 字节
Data N 字节 音频数据 具体的采样数据

4、音频数据格式类型

在 Format chunk 中的 audio_format 字段定义了音频编码方式:

值(十六进制) 名称 是否包含 Fact Chunk
0x0001 WAVE_FORMAT_PCM
0x0002 WAVE_FORMAT_ADPCM
0x0006 WAVE_FORMAT_ALAW
0x0007 WAVE_FORMAT_MULAW

最常见的是 0x0001(PCM 格式)。

5、Format Chunk 扩展块

当 WAV 文件使用非 PCM 编码时,需要扩展格式块:

扩展块结构:

┌─────────────┬─────────────┬────────────────────────┐
| cbSize      | cbContent                           |
| (2字节)     | (0或22字节)                         |
├─────────────┼─────────────┼────────────────────────┤
|             | valid_bits_per_sample (2字节)       |
|             | channel_mask (4字节)                |
|             | sub_format (16字节)                 |
└─────────────┴─────────────┴────────────────────────┘

字段说明:

  • cbSize:扩展块长度(0 或 22)

  • valid_bits_per_sample:有效采样位数

  • channel_mask:声道掩码(定义声道映射)

  • sub_format:16 字节的数据格式码

需要使用 WAVE_FORMAT_EXTENSIBLE 的情况:

  1. PCM 数据量化位数 > 16

  2. 音频采样声道数 > 2

  3. 实际量化位数不是 8 的倍数

  4. 需要指定声道顺序到声卡播放顺序的映射

6、声音数据存储格式

Data chunk 中的音频数据按以下规则存储:

6.1 字节序

  • 多字节样本采用小端模式(低位在前,高位在后)

6.2 声道排列

  • 多声道采用交叉存储方式

  • 立体声示例:L1, R1, L2, R2, L3, R3, ...

6.3 具体布局示例

(1) 8-bit 单声道

采样 1 采样 2
数据 1 数据 2

(2) 8-bit 双声道(立体声)

声道 1 采样 1 声道 2 采样 1 声道 1 采样 2 声道 2 采样 2
L1 R1 L2 R2

(3) 16-bit 单声道

采样 1 低字节 采样 1 高字节 采样 2 低字节 采样 2 高字节
L1_lo L1_hi L2_lo L2_hi

(4) 16-bit 双声道(立体声)

声道 1 采样 1       声道 2 采样 1
┌──────┬──────┐   ┌──────┬──────┐
│L1_lo │L1_hi │   │R1_lo │R1_hi │
└──────┴──────┘   └──────┴──────┘

声道 1 采样 2       声道 2 采样 2  
┌──────┬──────┐   ┌──────┬──────┐
│L2_lo │L2_hi │   │R2_lo │R2_hi │
└──────┴──────┘   └──────┴──────┘

7、WAV 文件实例分析

使用 WinHex 打开 WAV 文件的十六进制视图示例:

偏移地址 字节数 十六进制值 解析内容
00H 4 52 49 46 46 'RIFF' 标识符
04H 4 F4 FE 83 01 数据长度:0x0183FEF4(小端)
08H 4 57 41 56 45 'WAVE' 标识符
0CH 4 66 6D 74 20 'fmt '(注意末尾空格)
10H 4 10 00 00 00 Format chunk 大小:0x10(16 字节)
14H 2 01 00 编码格式:0x0001(PCM)
16H 2 02 00 声道数:0x0002(立体声)
18H 4 44 AC 00 00 采样率:0x0000AC44(44100 Hz)
1CH 4 10 B1 02 00 字节率:0x0002B110(176400 字节/秒)
20H 2 04 00 块对齐:0x0004(4 字节)
22H 2 10 00 位深度:0x0010(16 位)
24H 4 64 61 74 61 'data' 标识符
28H 4 48 FE 83 01 音频数据长度:0x0183FE48

从偏移量 2CH 开始就是实际的音频数据。

8、重要计算公式

8.1 关键参数计算

  • 字节率 = 采样率 × 声道数 × 位深度 / 8

  • 块对齐 = 声道数 × 位深度 / 8

  • 音频数据大小 = 采样数 × 声道数 × 位深度 / 8
  • 播放时长 = 音频数据大小 / 字节率

8.2 示例计算(44.1kHz 16-bit 立体声)

采样率:44100 Hz
声道数:2
位深度:16 bits

字节率 = 44100 × 2 × 16 / 8 = 176400 字节/秒
块对齐 = 2 × 16 / 8 = 4 字节
1分钟音频大小 = 60 × 176400 ≈ 10.1 MB

9、工具推荐

9.1 十六进制查看工具

  • WinHex(Windows)

  • Hex Fiend(macOS)

  • xxd(命令行,跨平台)

9.2 Python读取

import struct

with open('audio.wav', 'rb') as f:
    # 读取 RIFF 头
    riff = f.read(12)
    # 读取 fmt 块
    fmt_header = f.read(8)
    fmt_size = struct.unpack('<I', fmt_header[4:8])[0]
    fmt_data = f.read(fmt_size)