目录
- WAV文件概述
- WAV文件格式
- 一、案例分析
- 二、代码分析
- 1.建立结构体
- 2.读取数据段长度
- 3.结果
- 参考
WAV文件概述
WAV文件是在PC机上常见且最经典的多媒体音频文件,文件扩展名为WAV,是WAVEFOM的简写,也称为波形文件,可以直接存储声音波形。
它符合RIFF文件规范,且每个WAVE文件的头四个字节便是“RIFF”。
WAV文件格式
每个Chunk有各自的ID,位于Chunk最开始位置,以该数据块ID的ASCII表示,均为4个字节。在ID后面的是该Chunk大小:去除ID和Size所占的字节数后剩下的其他字节数目。
数据块ID | 数据块大小 |
---|
一、案例分析
打开一个WAV文件:
读取分析内容可知其数据长度为4022444字节,其中WAV的数据信息占4022272字节。
WAV属性中显示WAV文件大小一共是4022456字节,是将“ RIFF,数据大小字段,WAVE ”这几个字符所占的12字节算入。
偏移地址 | 数值 | 含义 |
---|---|---|
00H | 52 49 46 46 | 表示“RIFF”标识,是RIFF的ASCII码 |
04H | B0 60 3D 00 | 表示除去RIFF标识和自身4个字节后面部分的长度;其后四位为高位,前四位为低位,因此数据段长度应为:00 3D 60 B0=4022448,加上前8个字节为4022456。 |
08H | 57 41 56 45 | 是WAVE的ASCII码 |
0CH | 66 6D 74 20 | 是fmt的ASCII码,下面是fmt数据块的信息 |
10H | 10 00 00 00 | 后四位为高位,应看作00 00 00 10,表示是16PCM,16bit数据表示一个量化结果 |
14H | 01 00 | 后两位是高位,应看作00 01,为1时表示线性PCM编码,大于1时表示有压缩的编码,这里是PCM编码。 |
16H | 02 00 | 应看作00 02,1为单声道,2为双声道,这里是双声道 |
18H | 44 AC 00 00 | 00 00 AC 44=44100表示采样频率是44100HZ |
1CH | 10 B1 02 00 | Byte率=采样频率音频通道数每次采样得到的样本位数/8,00 02 B1 10=176400,采样频率为44100HZ,是双声道,样本位数为16,则176400是44100216/8的结果。 |
20H | 04 00 | 块对齐=通道数每次采样得到的样本位数/8,0004H,也就是4=216/8。 |
22H | 10 00 | 样本数据位数,00 10=16,一个量化样本占2字节。 |
24H | 4C 49 53 54 | 是LIST的ASCII码值 |
28H | 84 00 00 00 | 表示LIST数据块的长度为00 00 00 84=132字节 |
2CH | 49 4E 46 4F | 为“INFO”的ASCII码值 |
30H | ![]() | 该数据块是IART数据块,49 41 52 54是“IART”的ASCII码,00 00 00 18=24字节是该数据块数据部分长度 |
50H | ![]() | 49 47 4E 52是IGNR数据块的ASCII码表示,00 00 00 06=6字节是该部分数据部分的长度 |
5EH | ![]() | 49 4E 41 4D为“INAM”的ASCII码值,00 00 00 0A=10字节为该数据块数据部分长度 |
70H | ![]() | 49 50 52 44为"IPRD"的ASCII码值,00 00 00 16=22字节是该部分数据字段长度 |
8EH | ![]() | 49 50 52 54是IPRT的ASCII码,00 00 00 03=3字节,该部分数据长3字节不足4字节用0补全 |
9AH | ![]() | 49 53 46 54是ISFT的ASCII码,00 00 00 0E=14字节表示该数据段的长度 |
B0H | 64 61 74 61 | 表示data的ASCII码 |
B4H | 00 60 3D 00 | 应看作00 3D 60 00=4022272是数据data数据段的大小 |
二、代码分析
1.建立结构体
代码如下:
struct WAV_struct
{unsigned long FILEsize; //文件大小unsigned short Channel; //通道数unsigned long FS; //采样频率unsigned long BPS; //Byte率unsigned short sample_bit; //一个样本的位数unsigned long DATAsize; //数据大小unsigned char* data; //音频数据 };
2.读取数据段长度
利用函数seekg(偏移地址);可以从文件数据中获取文件大小
seekg()是对输入文件定位,它有两个参数:第一个参数是偏移量,第二个参数是基地址。
对于第一个参数,可以是正负数值,正的表示向后偏移,负的表示向前偏移。而第二个参数可以是:
iOS::beg:表示输入流的开始位置
ios::cur:表示输入流的当前位置
ios::end:表示输入流的结束位置
tellg()函数不需要带参数,它返回当前定位指针的位置,也代表着输入流的大小。
代码如下:
fs.seekg(0, ios::end); WAV.FILEsize = fs.tellg();fs.seekg(0x16);fs.read((char*)&WAV.Channel, sizeof(WAV.Channel));fs.seekg(0x18);fs.read((char*)&WAV.FS, sizeof(WAV.FS));fs.seekg(0x1c);fs.read((char*)&WAV.BPS, sizeof(WAV.BPS));fs.seekg(0x22);fs.read((char*)&WAV.sample_bit, sizeof(WAV.sample_bit));fs.seekg(0xB4);fs.read((char*)&WAV.DATAsize, sizeof(WAV.DATAsize));WAV.data = new unsigned char[WAV.DATAsize];fs.seekg(0xB8);fs.read((char*)WAV.data, sizeof(char) * WAV.DATAsize);
3.结果
(最后一行为最末尾20个字符)
参考
https://blog.csdn.net/angeljing521/article/details/51701179
https://blog.csdn.net/u013521296/article/details/90598169
https://www.cnblogs.com/ranson7zop/p/7657874.html
https://zhuanlan.zhihu.com/p/45518641
http://blog.sina.com.cn/s/blog_6da4642d0100rw4g.html