wav文件格式分析
2012-12-06 10:24
211 查看
一、综述
W***E文件作为多媒体中使用的声波文件格式之一,它是以RIFF格式为标准的。
RIFF是英文Resource Interchange File Format的缩写,每个W***E文件的头四个
字节便是“RIFF”。
W***E文件是由若干个Chunk组成的。按照在文件中的出现位置包括:RIFF W***E
Chunk, Format Chunk, Fact Chunk(可选), Data Chunk。具体见下图:
------------------------------------------------
| RIFF W***E Chunk |
| ID = 'RIFF' |
| RiffType = 'W***E' |
------------------------------------------------
| Format Chunk |
| ID = 'fmt ' |
------------------------------------------------
| Fact Chunk(optional) |
| ID = 'fact' |
------------------------------------------------
| Data Chunk |
| ID = 'data' |
------------------------------------------------
图1 Wav格式包含Chunk示例
其中除了Fact Chunk外,其他三个Chunk是必须的。每个Chunk有各自的ID,位
于Chunk最开始位置,作为标示,而且均为4个字节。并且紧跟在ID后面的是Chunk大
小(去除ID和Size所占的字节数后剩下的其他字节数目),4个字节表示,低字节
表示数值低位,高字节表示数值高位。下***体介绍各个Chunk内容。
PS:
所有数值表示均为低字节表示低位,高字节表示高位。
用表格说明一下文件的格式:
W***E文件作为多媒体中使用的声波文件格式之一,它是以RIFF格式为标准的。
RIFF是英文Resource Interchange File Format的缩写,每个W***E文件的头四个
字节便是“RIFF”。
W***E文件是由若干个Chunk组成的。按照在文件中的出现位置包括:RIFF W***E
Chunk, Format Chunk, Fact Chunk(可选), Data Chunk。具体见下图:
------------------------------------------------
| RIFF W***E Chunk |
| ID = 'RIFF' |
| RiffType = 'W***E' |
------------------------------------------------
| Format Chunk |
| ID = 'fmt ' |
------------------------------------------------
| Fact Chunk(optional) |
| ID = 'fact' |
------------------------------------------------
| Data Chunk |
| ID = 'data' |
------------------------------------------------
图1 Wav格式包含Chunk示例
其中除了Fact Chunk外,其他三个Chunk是必须的。每个Chunk有各自的ID,位
于Chunk最开始位置,作为标示,而且均为4个字节。并且紧跟在ID后面的是Chunk大
小(去除ID和Size所占的字节数后剩下的其他字节数目),4个字节表示,低字节
表示数值低位,高字节表示数值高位。下***体介绍各个Chunk内容。
PS:
所有数值表示均为低字节表示低位,高字节表示高位。
用表格说明一下文件的格式:
起始地址 | 占用空间 | 本地址数字的含义 |
00H | 4byte | RIFF,资源交换文件标志。 |
04H | 4byte | 从下一个地址开始到文件尾的总字节数。高位字节在后面,这里就是001437ECH,换成十进制是1325036byte,算上这之前的8byte就正好1325044byte了。 |
08H | 4byte | W***E,代表wav文件格式。 |
0CH | 4byte | FMT ,波形格式标志 |
10H | 4byte | 00000010H,16PCM,我的理解是用16bit的数据表示一个量化结果。 |
14H | 2byte | 为1时表示线性PCM编码,大于1时表示有压缩的编码。这里是0001H。 |
16H | 2byte | 1为单声道,2为双声道,这里是0001H。 |
18H | 4byte | 采样频率,这里是00002B11H,也就是11025Hz。 |
1CH | 4byte | Byte率=采样频率*音频通道数*每次采样得到的样本位数/8,00005622H,也就是22050Byte/s=11025*1*16/2。 |
20H | 2byte | 块对齐=通道数*每次采样得到的样本位数/8,0002H,也就是2=1*16/8。 |
22H | 2byte | 样本数据位数,0010H即16,一个量化样本占2byte。 |
24H | 4byte | data,一个标志而已。 |
28H | 4byte | Wav文件实际音频数据所占的大小,这里是001437C8H即1325000,再加上2CH就正好是1325044,整个文件的大小。 |
2CH | 不定 | 量化数据。 |
#include <iostream> #include <fstream> using namespace std; struct wav_struct { unsigned long file_size; //文件大小 unsigned short channel; //通道数 unsigned long frequency; //采样频率 unsigned long Bps; //Byte率 unsigned short sample_num_bit; //一个样本的位数 unsigned long data_size; //数据大小 unsigned char *data; //音频数据 ,这里要定义什么就看样本位数了,我这里只是单纯的复制数据 }; int main(int argc,char **argv) { fstream fs; wav_struct W***; fs.open("B:\\output.wav",ios::binary|ios::in); // fs.seekg(0x04); //从文件数据中获取文件大小 // fs.read((char*)&W***.file_size,sizeof(W***.file_size)); // W***.file_size+=8; fs.seekg(0,ios::end); //用c++常用方法获得文件大小 W***.file_size=fs.tellg(); fs.seekg(0x14); fs.read((char*)&W***.channel,sizeof(W***.channel)); fs.seekg(0x18); fs.read((char*)&W***.frequency,sizeof(W***.frequency)); fs.seekg(0x1c); fs.read((char*)&W***.Bps,sizeof(W***.Bps)); fs.seekg(0x22); fs.read((char*)&W***.sample_num_bit,sizeof(W***.sample_num_bit)); fs.seekg(0x28); fs.read((char*)&W***.data_size,sizeof(W***.data_size)); W***.data=new unsigned char[W***.data_size]; fs.seekg(0x2c); fs.read((char *)W***.data,sizeof(char)*W***.data_size); cout<<"文件大小为 :"<<W***.file_size<<endl; cout<<"音频通道数 :"<<W***.channel<<endl; cout<<"采样频率 :"<<W***.frequency<<endl; cout<<"Byte率 :"<<W***.Bps<<endl; cout<<"样本位数 :"<<W***.sample_num_bit<<endl; cout<<"音频数据大小:"<<W***.data_size<<endl; cout<<"最后20个数据:"<<endl; for (unsigned long i=W***.data_size-20;i<W***.data_size;i++) { printf("%x ",W***.data[i]); } fs.close(); delete[] W***.data; system("pause"); }