音视频编程: 简单分析 WAV 文件
最近在看人工智能相关的知识,无意中发现了一个巨牛的 人工智能教程,分享一下给大家。
教程不仅是零基础,通俗易懂,而且非常风趣幽默,像看小说一样!觉得太牛了,所以分享给大家。点 这里 可以直接看教程。
这篇分享是下篇 音视频编程: iOS 使用 faad2 的预备知识, 如果要解码 WAV 文件, 首先需要了解一下 WAV 音频文件的格式。
今天说的是 线性 PCM
对应的 WAV 格式的数据。
PCM 的种类
- 线性化 PCM
- A律量化的 PCM
- U律量化的 PCM
- AD PCM
- GSM
该系列博文:
WAV 简介
WAV 只是该音频文件的后缀名, 其完整名称缩写是 WAVE,WAVE(Waveform Audio File Format), 采用RIFF(Resource Interchange File Format)文件格式结构。
WAV 格式的音频文件通常用来保存 PCM 格式的原始音频数据,通常被称之为无损音频。
WAV 音频文件, 粗略来说是 WAV 数据头 + PCM 数据组成的. 裸数据 PCM 外面包了一层文件头,WAV 实质为一个 RIFF 文件.
WAV 数据头
关于 WAV 音频文件的数据头定义如下图所示:
最前面的4个字节用来标示是 RIFF 字符串。
可以看出, 一般的 WAV 文件的数据头为 44 个字节, 其后面跟的是 PCM 数据。
分析 WAV 数据头
使用 hexdump
来看一下 WAV 文件的数据头。
在当前路径下, 有个 wav 格式的音频文件 m.wav
, 使用 hexdump
分析一下.
1 | hexdump -n 44 m.wav |
其中, -n 44
表示查看前 44 个字节.
按字节分组的图, 如下所示:
1 | 52 49 46 46 |
分别是 RIFF 的 ASCII 码.
跟在 RIFF 后面的四个字节是文件的大小信息, 我们先使用 ls
命令看一下该文件的大小。
1 | ls -al |
输出文件大小为(字节数): 1080808
1 | staff 1080808 Jan 25 15:44 m.wav |
RIFF 后面的四个字节分别是: e0 7d 10 00, 由于该存储使用了小端序(Little-Endian 存储,也就是说对其中的数据,低位字节在前,高位字节在后), 所以16进制表示为: 0x00107de0, 对应的字节大小是 1080808
.
上面说到, 线性 PCM, 其实在该文件头中, 第17到第第22个字节(上图红色的5和6组合)标示了 PCM 的类型, 即:
1 | 10 00 00 00 01 00 |
其他类型的 PCM 类型定义为:
A律量化的PCM: 12 00 00 0006 00
U律量化的PCM: 12 00 00 00 07 00
AD PCM: 32 00 00 00 02 00
GSM: 14 00 00 00 31 00
最后4个字节表示真正 PCM 数据的文件大小, 即: 0x00107dbc, 其10进制大小为: 1080764, 用总文件大小减去 1080764, 就是文件头的大小, 如下:
1 | 1080808 - 1080764 = 44 |
其他对应的数据, 大家可以对照表自行分析。
定义数据头
数据类型
- char 占用 1 个字节
- uint32_t 占用 4 个字节
- uint16_t 占用 2 个字节
这里使用结构体定义 WAV 文件头, 其定义如下:
1 | struct MZWavAudioFileHeader |
可以使用下面代码来计算该结构体所占的字节数(结果是44):
1 | int wav_header_size = sizeof(struct MZWavAudioFileHeader); |