WAVE文件是非常简单的一种RIFF文件,它的格式类型为”WAVE”。RIFF块包含两个子块,这两个子块的ID分别是”fmt”和”data”,其中”fmt”子块由结构PCMWAVEFORMAT所组成,其子块的大小就是sizeofof(PCMWAVEFORMAT),数据组成就是PCMWAVEFORMAT结构中的数据。(详细介绍于http://blog.csdn.net/zhihu008/article/details/7854529中查看,这里只作简要介绍)
wav文件结构
PCMWAVEFORMAT结构定义如下:
typedef struct
{
WAVEFORMAT wf; // 波形格式;
WORD wBitsPerSample;//WAVE文件的采样大小;
} PCMWAVEFORMAT;
WAVEFORMAT结构定义如下:
typedef struct
{
WORD wFormatag;//编码格式,包括WAVE_FORMAT_PCM,WAVEFORMAT_ADPCM等
WORD nChannls;//声道数,单声道为1,双声道为2
DWORD nSamplesPerSec;//采样频率
DWORD nAvgBytesperSec;//每秒的数据量
WORD nBlockAlign;//块对齐(每个采样的字节长度)
} WAVEFORMAT;
WAV文件头结构:
typedef struct
{
char chRIFF[4];//"RIFF"
DWORD dwRIFFLen;//总长度-8
char chWAVE[4];//"WAVE"
char chFMT[4];//"fmt "
DWORD dwFMTLen;//sizeof(PCMWAVEFORMAT )
PCMWAVEFORMAT pwf;
char chDATA[4];//"data"
DWORD dwDATALen;//音频数据长度
}WaveHeader;
其中的字符数组都是固定格式。以下分别对应8、16比特单双通道的数据存储格式图:
8bit、单通道:
8bit、双通道:
16bit、单通道:
16bit、双通道:
wav头文件详解
参考
RIFF档案由一个简单的表头(header)跟随着多个 "chunks"所组。其格式完全跟IFF一样,除整数的储存方式不一样以外。
表头(Header)
4 字节(bytes):固定为"RIFF".
4 字节:little-endian 32-bit 正整数,整个档案的大小,扣掉辨识字符和长度,共8个字节。
4 字节:这个档案的型态字符,例如:"AVI " 或 "WAVE".
接下来是区块(Chunks),每个区块包含:
4 字节:此区块的ASCII识别字,例如:"fmt " 或 "data".
4 字节:little-endian 32-bit 正整数,表示本区块的长度(这个正整数本身和区块识别字的长度不算在内).
不固定长度字段:此区块的资料,大小等同前一栏之正整数。
假如区块的长度不为偶数,则填入一个 byte。
可以参考下表
偏移地址
|
大小
字节
|
数据块
类型
|
内容
|
00H~03H
|
4
|
4字符
|
资源交换文件标志(RIFF)
|
04H~07H
|
4
|
长整数
|
从下个地址开始到文件尾的总字节数
|
08H~0BH
|
4
|
4字符
|
WAV文件标志(WAVE)
|
0CH~0FH
|
4
|
4字符
|
波形格式标志(fmt ),最后一位空格。
|
10H~13H
|
4
|
整数
|
过滤字节(一般为00000010H)
|
14H~15H
|
2
|
整数
|
格式种类(值为1时,表示数据为线性PCM编码)
|
16H~17H
|
2
|
整数
|
通道数,单声道为1,双声道为2
|
18H~1BH
|
4
|
长整数
|
采样频率
|
1CH~1FH
|
4
|
长整数
|
波形数据传输速率(每秒平均字节数)
|
20H~21H
|
2
|
整数
| DATA数据块长度,字节。 |
22H~23H
|
2
|
整数
|
PCM位宽
|
24H~27H | 4 | 4字符 |
“fact”,该部分一下是可选部分,即可能有,可能没有,一般到WAV文件由某些软件转换而成时,包含这部分。
|
28H~2BH | 4 |
长整数
| size,数值为4 |
表2 WAV声音文件的
偏移地址
|
字节数
|
类型
|
内容
|
24H~27H
|
4
|
4字符
|
数据标志符(data)
|
28H~2BH
|
4
|
长整型
|
DATA总数据长度字节
|
2CH...
|
...
|
DATA数据块
|
他的三个最重要的参数是采样率,比特数,声道数。
我们使用UE打开这个音频文件
注意,我们的pc都是小端模式,所以注意读取数据的真实内容。
我们解读一下这个wav文件
00H ~ 03H 52 49 46 46 对应的是RIFF
04H ~ 07H 48 10 03 00 对应的是后面文件的大小,小端模式所以是00031048 ,换算为十进制的200776
08H ~ 0BH 57 41 56 45 对应的是标示符WAVE
0CH ~ 0FH 66 6d 74 20 对应是波形格式标示符fmt
10H ~ 13H 12 00 00 00 对应的是过滤字节,不知道是什么作用,由于本文件不是标准的采样率,所以可能和上面的不一致
14H ~ 15H 01 00 对应的十进制是1 线性的PCM编码,我们这里只探讨PCM编码
16H ~ 17H 01 00 对应的十进制是1 表示单声道,MONO
18H ~ 1BH 80 3E 00 00 对应的十进制是16000.表示采样率是16000的
1CH ~ 1FH 00 7D 00 00 对应的十进制是32000,波形数据传输率,每秒多少个字节,可以用(200776 -72)/32000 = 6.272s
20H ~ 21H 02 00 对应的十进制是2,数据的调整数
22H ~ 23H 10 00 对应的十进制是16,样本数据的位数,表示用16位表示一个样本
我们的和表二之间有一些差距,是ffmpeg转码的数据,所以中间夹着了一些ffmpeg的信息
48H ~ 4BH 64 61 74 71 对应的ACSCII码是data
4CH ~ 4FH 00 10 03 00 对应的十进制是200704,表示采样数据的总数
从50H开始就是真正的数据部分
在使用ffmpeg解包的时候总共是有49个包,每个包的大小为4096, 49*4096 =200704,
怎么计算出来包的大小,需要进一步的分析。