## WAV音频编程 [TOC] #### wav概述 WAV为微软公司(Microsoft)开发的一种声音文件格式,它符合`RIFF`(`Resource Interchange File Format`)文件规范,用于保存Windows平台的[音频](http://baike.baidu.com/view/66105.htm)信息资源,被Windows平台及其应用程序所广泛支持,该格式也支持`MSADPCM`,`CCITT A LAW`等多种压缩运算法,支持多种音频数字,取样频率和声道,标准格式化的WAV文件和CD格式一样,也是44.1K的取样频率,16位量化数字,因此在声音文件质量和CD相差无几! 通常使用三个参数来表示声音,量化位数,取样频率和[采样点](http://baike.baidu.com/view/984096.htm)振幅。量化位数分为8位,16位,24位三种,声道有单声道和[立体声](http://baike.baidu.com/view/106153.htm)之分,单声道振幅数据为n*1矩阵点,立体声为n*2矩阵点,取样频率一般有11025Hz(11kHz) ,22050Hz(22kHz)和44100Hz(44kHz) 三种,不过尽管[音质](http://baike.baidu.com/view/3021.htm)出色,但在压缩后的文件体积过大!相对其他音频格式而言是一个缺点,其文件大小的计算方式为:[WAV格式](http://baike.baidu.com/view/14471.htm)文件所占容量(B) = (取样频率 ×[量化位数](http://baike.baidu.com/view/189745.htm)×声道) ×时间 / 8 ([字节](http://baike.baidu.com/view/60408.htm)= 8bit) 每一分钟WAV格式的音频文件的大小为10MB,其大小不随音量大小及清晰度的变化而变化。 #### 格式解析 WAVE文件是非常简单的一种RIFF文件,它的格式类型为"WAVE"。RIFF块包含两个子块,这两个子块的ID分别是"fmt"和"data",其中"fmt"子块由结构PCMWAVEFORMAT所组成,其子块的大小就是sizeofof(PCMWAVEFORMAT),数据组成就是PCMWAVEFORMAT结构中的数据。 ![WAV音频格式的结构](http://img.dnbcw.net/2009112/2009112214656.png) ###### RIFF块(RIFF-Chunk) | 偏移地址 | 字节数 | 数据类型 | 内 容 | | ---- | ---- | -------- | -------- | | 00H | 4 | uint32_t | "RIFF"标志 | | 04H | 4 | uint32_t | 文件长度 | | 08H | 4 | uint32_t | "WAVE"标志 | ###### 格式化块(Format-Chunk) | 偏移地址 | 字节数 | 数据类型 | 内 容 | | ---- | ---- | -------- | ---------------------------------------- | | 0CH | 4 | uint32_t | "fmt"标志 | | 10H | 4 | uint32_t | 过渡字节(不定) | | 14H | 2 | uint16_t | 格式类别(10H为PCM形式的声音数据) | | 16H | 2 | uint16_t | 通道数,单声道为1,双声道为2 | | 18H | 4 | uint32_t | 采样率(每秒样本数),表示每个通道的播放速度, | | 1CH | 4 | uint32_t | 波形音频数据传送速率,其值为通道数×每秒数据位数×每样本的数据位数/8。播放软件利用此值可以估计缓冲区的大小。 | | 20H | 2 | uint16_t | 数据块的调整数(按字节算的),其值为通道数×每样本的数据位值/8。播放软件需要一次处理多个该值大小的字节数据,以便将其值用于缓冲区的调整。 | | 22H | 2 | uint16_t | 每样本的数据位数,表示每个声道中各个样本的数据位数。如果有多个声道,对每个声道而言,样本大小都一样。 | ###### 数据块(Data-Chunk) | 偏移地址 | 字节数 | 数据类型 | 内 容 | | ---- | :--- | :------- | ----------- | | 24H | 4 | uint32_t | 数据标记符"data" | | 28H | 4 | uint32_t | 语音数据的长度 | #### C语言结构体表示WAV格式头 ###### RIFF块(RIFF-Chunk) ```c struct wav_header { uint32_t id; // 固定为'RIFF' uint32_t size; // 除了id和size之外,整个WAV文件的大小 uint32_t format; // fmt chunk的格式,此处为'WAVE' }; ``` ###### 格式化块(Format-Chunk) ```c struct wav_fmt { uint32_t fmt_id; // 固定为'fmt ' uint32_t fmt_size; // 在fmt chunk中除了fmt_id和fmt_size之外的大小,固定为16字节 uint16_t fmt; // data chunk中数据的格式代码,PCM的代码是0x0001 uint16_t channels; // 声道数目,由用户设置:1为单声道,2为立体声 uint32_t sample_rate; // 采样频率,由用户设置:典型值是11025Hz、22050Hz和44100Hz uint32_t byte_rate; // 码率 = 采样率 * 帧大小 uint16_t block_align; // 帧大小 = 声道数 * 量化级/8 uint16_t bits_per_sample; // 量化位数,由用户设置:典型值是8、16、32 }; ``` ###### 数据块(Data-Chunk) ```c struct wav_data { uint32_t data_id; // 固定为'data' uint32_t data_size; // 除了WAV格式头之外的音频数据大小 }; ``` ###### 将各个头封装在一起,wav_format就代表了WAV格式头 ```c typedef struct { struct wav_header head; struct wav_fmt format; struct wav_data data; }wav_format; ``` 部分参考自[wav音频文件头解析](http://blog.csdn.net/u013286409/article/details/47414273)