WAV
即WAV
| Size | 4 Bytes |数值
,18则最后又附加信息 | 为16或18
| FormatTag | 2 Bytes | 编码方式,一般为0x0001 |
| Channels | 2 Bytes |声道数目,1--单声道;2--双声道 | |
| SamplesPerSec | 4 Bytes | 采样频率
| AvgBytesPerSec| 4 Bytes | 每秒所需字节数 | |===> WAVE_FORMAT
| BlockAlign | 2 Bytes |数据块对齐单位(每个采样需要的字节数) | |
| BitsPerSample | 2 Bytes | 每个采样需要的bit数 | |
| | 2 Bytes | 附加信息(可选,通过Size来判断有无) | |
图3 Format Chunk
以’fmt ‘作为标示。一般情况下Size为16,此时最后附加信息没有;如果为18
图3
则最后多了2个字节的附加信息。主要由一些软件制成的wav格式中含有该2
个字节的
附加信息。
结构定义如下:
struct WAVE_FORMAT
{
WORD wFormatTag;
WORD wChannels;
DWORD dwSamplesPerSec;
DWORD dwAvgBytesPerSec;
WORD wBlockAlign;
WORD wBitsPerSample;
};
struct FMT_BLOCK
{
char szFmtID[4]; // ‘f’,’m’,’t’,’ ‘
DWORD dwFmtSize;
WAVE_FORMAT wavFormat;
};
Fact Chunk
| |所占字节数| 具体内容 |
| ID | 4 Bytes | ‘fact’ |
|声道0 | 声道0 | 声道0 | 声道 | 16bit量化
0 |
| | (低位字节) | (高位字节) | (低位字节) | (高位字节) | | | 取样1 |
| 双声道|
| 16bit量化 |声道0(左) | 声道0(左) | 声道1(右) | 声道1(右) | | | (低位字节) | (高位字节) | (低位字节) | (高位字节) 图6 wav数据bit位置安排方式
Data Chunk头结构定义如下:
struct DATA_BLOCK {
char szDataID[4]; // ‘d’,’a’,’t’,’a’
DWORD dwDataSize;
};
//wave文件头
typedef struct WaveHeader
{
uint8 riff[4]; //资源交换文件标志
uint32 size; //从下个地址开始到文件结尾的字节数 uint8 wave_flag[4]; //wave文件标识
uint8 fmt[4]; //波形格式标识
uint32 fmt_len; //过滤字节(一般为00000010H)
uint16 tag; //格式种类,值为1时,表示PCM线性编码 uint16 channels; //通道数,单声道为1,双声道为2
uint32 samp_freq; //采样频率
uint32 byte_rate; //数据传输率 (每秒字节,采样频率×每个样本字节数) uint16 block_align; //块对齐字节数 = channles * bit_samp / 8
uint16 bit_samp; //bits per sample (又称量化位数)
} wave_header_t;
typedef struct WaveStruct
{
FILE *fp; //file pointer
wave_header_t header; //header
uint8 data_flag[4]; //数据标识符
uint32 length; //采样数据总数
uint32 *pData; //data
} wave_t;
wave_t wave;
1. [代码][C/C++]代码
001 #include "stdlib.h"
002 #include "stdio.h"
003
004 int main()
005 {
006 int i; //用作循环计数
007 unsigned char ch[100]; //用来存储wav文件的头信息 008 FILE *fp;
009
010 fp=fopen("1.wav","rb");//为读,打开一个wav文件
011
012 if((fp=fopen("1.wav","rb"))==NULL) //若打开文件失败,退出 013 {
014 printf("can’t open this file\n");
015 exit(0);
016 }
017
018 /**********输出wav文件的所有信息**********/
019 printf("该wav文件的所有信息:");
020 for(i=0;i<58;i++)
021 {
022 ch[i]=fgetc(fp); //每次读取一个字符,存在数组ch中 023
if(i%16==0) //每行输出16个字符对应的十六进制数 024
printf("\n");
if(ch[i]<16) //对小于16的数,在前面加0,使其用8bit025 显示出来
026 printf("0%x ",ch[i]);
027 else
028 printf("%x ",ch[i]);
029 }
030
031 /*********RIFF WAVE Chunk的输出*********/
032 printf("\n\nRIFF WAVE Chunk信息:");
033 //输出RIFF标志
034 printf("\nRIFF标志:");
035 for(i=0;i<4;i++)
036 {
037 printf("%x ",ch[i]);
038 }
039
040 //输出size大小
041 printf("\nsize:ox");
) //低字节表示数值低位,高字节表示数值高位 043 042 for(i=7;i>=4;i--
{
044 if(ch[i]<16)
045 printf("0%x",ch[i]);
046 else
047 printf("%x",ch[i]);
048 }
049
050 //输出WAVE标志
051 printf("\nWAVE标志:");
052 for(i=8;i<12;i++)
053 {
054 if(ch[i]<16)
055 printf("0%x ",ch[i]);
056 else
057 printf("%x ",ch[i]);
058 }
059
060 /*******Format Chunk的输出*******/
061 printf("\n\nFormat Chunk信息:");
062 //输出fmt 标志
063 printf("\nfmt 标志:");
064 for(i=12;i<16;i++)
065 {
066 if(ch[i]<16)
067 printf("0%x ",ch[i]);
068 else
069 printf("%x ",ch[i]);
070 }
071
072 //输出size段
073 printf("\nsize:ox");
074 for(i=19;i>15;i--)
075 {
076 if(ch[i]<16)
077 printf("0%x",ch[i]);
078 else
079 printf("%x",ch[i]);
080 }
081
082 //输出编码方式
:ox"); 083 printf("\n编码方式
084 for(i=21;i>19;i--)
085 {
086 if(ch[i]<16)
087 printf("0%x",ch[i]);
088 else
089 printf("%x",ch[i]);
090 }
091
092 //输出声道数目
093 printf("\n声道数目:ox");
) 094 for(i=23;i>21;i--
095 {
096 if(ch[i]<16)
097 printf("0%x",ch[i]);
098 else
099 printf("%x",ch[i]);
100 }
101
102 if(ch[i+1]==1) //1表示单声道,2表示双声道 103 printf(" 单声道");
104 else
105 printf(" 双声道");
106
107 //输出采样频率
108 printf("\n采样频率:ox");
109 for(i=27;i>23;i--)
110 {
111 if(ch[i]<16)
112 printf("0%x",ch[i]); 113 else
114 printf("%x",ch[i]);
115 }
116
117 //输出每秒所需字节数
118 printf("\n每秒所需字节数:ox"); 119 for(i=31;i>27;i--)
120 {
121 if(ch[i]<16)
122 printf("0%x",ch[i]); 123 else
124 printf("%x",ch[i]);
125 }
126
127 //输出数据块对齐单位
128 printf("\n数据块对齐单位:ox"); 129
) for(i=33;i>31;i--
130 {
131 if(ch[i]<16)
132 printf("0%x",ch[i]); 133 else
134 printf("%x",ch[i]);
135 }
136
137 //输出每个采样所需bit数
138 printf("\n每个采样所需bit数:ox"); 139 for(i=35;i>33;i--)
140 {
141 if(ch[i]<16)
142 printf("0%x",ch[i]); 143 else
144 printf("%x",ch[i]);
145 }
146
147 //输出附加信息
if(ch[16]==18) //若Format Chunk的size大小为18,则该模块的最148 后两
个字节为附加信息
149 { //若为16,则无附加信息
150 printf("\n附加信息:ox");
151 for(i=37;i>35;i--)
152 {
153 if(ch[i]<16)
154 printf("0%x",ch[i]);
155 else
156 printf("%x",ch[i]);
157 }
158 }
159
160 /*******Fact Chunk的输出*******/
161 printf("\n\nFact Chunk信息:");
162 //输出fact标志
163 printf("\nfact标志:");
164 for(i=38;i<42;i++)
165 {
166 if(ch[i]<16)
167 printf("0%x ",ch[i]);
168 else
169 printf("%x ",ch[i]);
170 }
171
172 //输出size
173 printf("\nsize:ox");
) 174 for(i=45;i>41;i--
175 {
176 if(ch[i]<16)
177 printf("0%x",ch[i]);
178 else
179 printf("%x",ch[i]);
180 }
181
182 //输出data段数据
183 printf("\ndata段数据:"); 184 for(i=46;i<50;i++)
185 {
186 if(ch[i]<16)
187 printf("0%x ",ch[i]); 188 else
189 printf("%x ",ch[i]); 190 }
191
192 /*******Data Chunk的输出*******/ 193 printf("\n\nData Chunk信息:"); 194 //输出data标志
195 printf("\ndata标志:"); 196 for(i=50;i<54;i++)
197 {
198 if(ch[i]<16)
199 printf("0%x ",ch[i]); 200 else
201 printf("%x ",ch[i]); 202 }
203
204 //输出数据大小
205 printf("\n数据大小:ox"); 206 for(i=57;i>53;i--)
207 {
208 if(ch[i]<16)
209 printf("0%x",ch[i]); 210 else
211 printf("%x",ch[i]); 212 }
213
214 printf("\n");
215
216 fclose(fp);
217 }