搜索
您的当前位置:首页正文

WAV格式即WAV

来源:易榕旅网
WAV格式即WAV。

WAV为微软公司(Microsoft)开发的一种声音文件格式,它符合RIFF(Resource Interchange File Format)文件规范,用于保存Windows平台的音频信息资源,被Windows平台及其应用程序所广泛支持,该格式也支持MSADPCM,CCITT A LAW等多种压缩运算法,支持多种音频数字,取样频率和声道,标准格式化的WAV文件和CD格式一样,也是44.1K的取样频率,16位量化数字,因此在声音文件质量和CD相差无几! WAV打开工具是WINDOWS的媒体播放器。 WAVE是录音时用的标准的WINDOWS文件格式,文件的扩展名为“WAV”,数据本身的格式为PCM或压缩型,属于无损音乐[1]格式的一种。 符合 RIFF(Resource Interchange File Format)规范。所有的WAV都有一个文件头,这个文件头音频流的编码参数。数据块的记录方式是little-endian字节顺序,标志符并不是字符串而是单独的符号。 表1 WAV文件的文件头 , 偏移地址 00H~03H 04H~07H 08H~0B4 4字符 WAV文件标志(WAVE) 4 长整数 从下个地址开始到文件尾的总字节数 4 4字符 资源交换文件标志(RIFF) 大小 字节 数据块 类型 内容 H 0CH~0FH 10H~13H 14H~15H 16H~17H 18H~1BH 14 长整数 波形数据传输速率(每秒平均字节数) 4 长整数 采样频率 2 整数 通道数,单声道为1,双声道为2 2 整数 格式种类(值为1时,表示数据为线性PCM编码) 4 整数 过滤字节(一般为00000010H) 4 4字符 波形格式标志(fmt ),最后一位空格。 CH~1FH 20H~21H 22H~23H 24H~27H 28H~2BH 4 长整数 size,数值为4 4 4字符 “fact”,该部分一下是可选部分,即可能有,可能没有,一般到WAV文件由某些软件转换而成时,包含这部分。 2 整数 PCM位宽 2 整数 DATA数据块长度,字节。 表2 WAV声音文件的数据块 偏移地址 24H~27H 28H~2BH 字节数 4 4 类型 4字符 长整型 内容 数据标志符(data) DATA总数据长度字节 2CH... ... DATA数据块 WAV文件作为最经典的Windows多媒体音频格式,应用非常广泛,它使用三个参数来表示声音:采样位数、采样频率和声道数。 3声道编辑 声道有单声道和立体声之分,采样频率一般有11025Hz(11kHz)、22050Hz(22kHz)和44100Hz(44kHz)三种。WAV文件所占容量=(采样频率×采样位数×声道)×时间/8(1字节=8bit)。 WAV对音频流的编码没有硬性规定,除了PCM之外,还有几乎所有支持ACM规范的编码都可以为WAV的音频流进行编码。 4音频编辑 音频视频交错格式数据(.AVI) 、波形格式数据(.WAV) 、位图格式数据(.RDI) 、MIDI格式数据(.RMI) 、调色板格式(.PAL) 、多媒体电影(.RMN) 、动画光标(.ANI) 、其它RIFF文件(.BND)。 WAVE文件可以存储大量格式的。 RIFF是英文Resource Interchange File Format的缩写,每个WAVE文件的头四个字节便是“RIFF”。WAVE文件由文件头和数据体两大部分组成。其中文件头又分为RIFF/WAV文件标识段和声音数据格式说明段两部分。WAVE文件各部分内容及格式见附表。 常见的声音文件主要有两种,分别对应于单声道(11.025KHz采样率、8Bit的采样值)和双声道(44.1KHz采样率、16Bit的采样值)。采样率是指:声音信号在“模→数”转换过程中单位时间内采样的次数。采样值是指每一次采样周期内声音模拟信号的积分值。 对于单声道声音文件,采样数据为八位的短整数(short int 00H-FFH);而对于双声道立体声声音文件,每次采样数据为一个16位的整数(int),高八位和低八位分别代表左右两个声道。 WAVE文件数据块包含以脉冲编码调制(PCM)格式表示的样本。WAVE文件是由样本组织而成的。在单声道WAVE文件中,声道0代表左声道,声道1代表右声道。在多声道WAVE文件中,样本是交替出现的。 WAVE文件的每个样本值包含在一个整数i中,i的长度为容纳指定样本长度所需的最小字节数。首先存储低有效字节,表示样本幅度的位放在i的高有效位上,剩下的位置为0,这样8位和16位的PCM波形样本的数据格式。 RIFF是英文Resource Interchange File Format的缩写,每个WAVE文件的头四个 字节便是“RIFF”。 WAVE文件是由若干个Chunk组成的。按照在文件中的出现位置包括:RIFF WAVE Chunk,Format Chunk,Fact Chunk(可选),Data Chunk。具体见下图: | RIFF WAVE Chunk | | ID = 'RIFF' | | RiffType = 'WAVE' | | Format Chunk | | ID = 'fmt ' | Fact Chunk(optional) | | ID = 'fact' | | Data Chunk | | ID = 'data' | 图1 Wav格式包含Chunk示例 RIFF WAVE Chunk 图1 | |所占字节数| 具体内容 | | ID | 4 Bytes | 'RIFF' | | Size | 4 Bytes | | | Type | 4 Bytes | 'WAVE' | 图2 RIFF WAVE Chunk 以'RIFF'作为标示,然后紧跟着为size字段,该size是整个wav文件大小减去ID 和Size所占用的字节数,即FileLen - 8 = Size。然后是Type字段,为'WAVE',表 图2 示是wav文件。 结构定义如下: struct RIFF_HEADER { char szRiffID[4]; // 'R','I','F','F' DWORD dwRiffSize; char szRiffFormat[4]; // 'W','A','V','E' }; Format Chunk | |字节数 | 具体内容 | | ID | 4 Bytes | 'fmt ' | | Size | 4 Bytes |数值为16或18,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' |

| Size | 4 Bytes | 数值为4 | | data | 4 Bytes | | 图4 Fact Chunk Fact Chunk是可选字段,一般当wav文件由某些软件转化而成,则包含该Chunk。 结构定义如下: 图4 struct FACT_BLOCK { char szFactID[4]; // 'f','a','c','t' DWORD dwFactSize; }; Data Chunk | |所占字节数| 具体内容 | | ID | 4 Bytes | 'data' | | Size | 4 Bytes | | | data | | | 图5 Data Chunk Data Chunk是真正保存wav数据的地方,以'data'作为该Chunk的标示。然后是 数据的大小。紧接着就是wav数据。根据Format Chunk中的声道数以及采样bit数, wav数据的bit位置可以分成以下几种形式: 对于8位单声道,每个样本数据由8位(bit)表示; 对于8位立体声,每个声道的数据由一个8位(bit)数据表示,且第一个8位(bit) 数据表示0声道(左)数据,紧随其后的8位(bit)数据表示1声道(右)数据; 对于16位单声道,每个样本数据由16位(bit)表示;其中低字节存放高位,高字节存放低位 对于16位立体声,每个声道的数据由一个16位(bit)数据表示,且第一个16位(bit) 数据表示0声道(左)数据,紧随其后的16位(bit)数据表示1声道(右)数据。 |单声道| 取样1 | 取样2 | 取样3 | 取样4 | | 8bit量化 |声道0 | 声道0 | 声道0 | 声道0 | | 双声道| 取样1 | 取样2 | 8bit量化 |声道0(左) | 声道1(右) | 声道0(左) | 声道1(右) | | | 取样1 | 取样2 | |单声道| | 16bit量化 |声道0 | 声道0 | 声道0 | 声道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\为读,打开一个wav文件 011

if((fp=fopen(\"1.wav\//若打开文件失败,退012

出 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 {

ch[i]=fgetc(fp); //每次读取一个字符,存在数组ch022

中 if(i%16==0) //每行输出16个字符对应的023

十六进制数 024 printf(\"\\n\");

if(ch[i]<16) //对小于16的数,在前面加025

0,使其用8bit显示出来 026 printf(\"0%x \ 027 else

028 printf(\"%x \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 \038 } 039

040 //输出size大小

041 printf(\"\\nsize:ox\");

for(i=7;i>=4;i--) //低字节表示数值低位,高字节表示数值042

高位 043 {

044 if(ch[i]<16)

045 printf(\"0%x\046 else

047 printf(\"%x\048 } 049

050 //输出WAVE标志

051 printf(\"\\nWAVE标志:\"); 052 for(i=8;i<12;i++) 053 {

054 if(ch[i]<16)

055 printf(\"0%x \056 else

057 printf(\"%x \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 \068 else

069 printf(\"%x \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\078 else

079 printf(\"%x\080 } 081

082 //输出编码方式

083 printf(\"\\n编码方式:ox\"); 084 for(i=21;i>19;i--) 085 {

086 if(ch[i]<16)

087 printf(\"0%x\088 else

089 printf(\"%x\090 } 091

092 //输出声道数目

093 printf(\"\\n声道数目:ox\"); 094 for(i=23;i>21;i--) 095 {

096 if(ch[i]<16)

097 printf(\"0%x\098 else

099 printf(\"%x\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\113 else

114 printf(\"%x\115 } 116

117 //输出每秒所需字节数

118 printf(\"\\n每秒所需字节数:ox\"); 119 for(i=31;i>27;i--) 120 {

121 if(ch[i]<16)

122 printf(\"0%x\123 else

124 printf(\"%x\125 } 126

127 //输出数据块对齐单位

128 printf(\"\\n数据块对齐单位:ox\"); 129 for(i=33;i>31;i--) 130 {

131 if(ch[i]<16)

132 printf(\"0%x\133 else

134 printf(\"%x\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\

143 else

144 printf(\"%x\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\155 else

156 printf(\"%x\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 \168 else

169 printf(\"%x \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\

178 else

179 printf(\"%x\180 } 181

182 //输出data段数据

183 printf(\"\\ndata段数据:\"); 184 for(i=46;i<50;i++) 185 {

186 if(ch[i]<16)

187 printf(\"0%x \188 else

189 printf(\"%x \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 \200 else

201 printf(\"%x \202 } 203

204 //输出数据大小

205 printf(\"\\n数据大小:ox\"); 206 for(i=57;i>53;i--) 207 {

208 if(ch[i]<16)

209 printf(\"0%x\210 else

211 printf(\"%x\212 } 213

214 printf(\"\\n\"); 215

216 fclose(fp); 217 }

因篇幅问题不能全部显示,请点此查看更多更全内容

Top