当前位置:文档之家› 详解wave头格式(尽可能详细并附代码)

详解wave头格式(尽可能详细并附代码)

整理网上和读书时的资料,结合自己的实际经验,给出wav头格式的解释和源代码,既是对自己的总结,同时又服务大家。

另外在给出几个实际例子,如果看了这篇文档还不能正确写出wave文件,那就要吊起来打了^_^。

——flywen 2010-10-13参考网址一:/sshcx/archive/2007/05/01/1593923.aspx参考网址二:/share/detail/15909594WAVE 文件作为多媒体中使用的声波文件格式之一,它是以RIFF格式为标准的。

RIFF是英文Resource Interchange File Format的缩写,每个WAVE文件的头四个字节便是"RIFF"。

WAVE 文件由文件头和数据体两大部分组成。

其中文件头又分为RIFF/WAV文件 标识段和声音数据格式说明段两部分。

常见的声音文件主要有两种,分别对应于单声道(11.025KHz 采样率、8Bit的采样值)和双声道(44.1KHz采样率、16Bit的采样值)。

采样率是指:声音信号在"模→数"转换过程中单位时间内采样的次数。

采样值是指每一次采样周期内声音模拟信号的积分值。

[!21ki@][@21ki!]对于单声道声音文件,采样数据为八位的短整数(short int 00H-FFH);而对于双声道立体声声音文件,每次采样数据为一个16位的整数(int),高八位和低八位分别代表左右两个声道。

WAVE文件数据块包含以脉冲编码调制(PCM)格式表示的样本。

WAVE文件是由样本组织而成的。

在单声道WAVE文件中,声道0代表左声道,声道1代表右声道。

在多声道WAVE文件中,样本是交替出现的。

参考网址一和二中都给出了wav的头定义,但有一个小区别,一中将这个44个字节作为一个大的头,给定在一个结构体中,而二中则是按照四个不同的chunk处理的,所以就给了四个结构体,后面我的代码也是根据二来写的,个人觉得这样比较清晰,不过这纯属个人感觉。

下面就是根据四个结构体写的代码,注意FACT不是必须的,可以不用写入头,不写的话就是44个字节,写的话wave的头是56个字节。

一:源代码(参考二中也有比较详细的读wave头的代码)#if !defined(_WAV_INFO_)#define _WAV_INFO_// 一些和声音数据相关的宏#define SAMPLE_RATE 22050 // sample rate,每秒22050个采样点 #define QUANTIZATION 0x10 // 16bit量化,#define BYTES_EACH_SAMPLE 0x2 // QUANTIZATION / 8, 所以每个采样点、// 是short,占个2个字节#define CHANNEL_NUN 0x1 // 单声道#define FORMAT_TAG 0x1 // 线性PCM// 一个wave file包括四个CHUNK,除了FACT之外,其它是必须的,并且第一个RIFF是整个文件的头,// 所以别名为WAV_HEADER,而不是RIFF/*------------------------Wave File Structure ------------------------------------ */ typedef struct RIFF_CHUNK{char fccID[4]; // must be "RIFF"unsigned long dwSize; // all bytes of the wave file subtracting 8,// which is the size of fccID and dwSize char fccType[4]; // must be "WAVE"}WAVE_HEADER;// 12 bytestypedef struct FORMAT_CHUNK{char fccID[4]; // must be "fmt "unsigned long dwSize; // size of this struct, subtracting 8, which// is the sizeof fccID and dwSize unsigned short wFormatTag; // one of these: 1: linear,6: a law,7:u-law unsigned short wChannels; // channel numberunsigned long dwSamplesPerSec; // sampling rateunsigned long dwAvgBytesPerSec; // bytes number per secondunsigned short wBlockAlign; // 每样本的数据位数(按字节算), 其值为:通道// 数*每样本的数据位值/8,播放软件需要一次处// 理多个该值大小的字节数据, 以便将其值用于// 缓冲区的调整每样本占几个字节:// NumChannels * uiBitsPerSample/8unsigned short uiBitsPerSample; // quantization}FORMAT;// 24 bytes// The fact chunk is required for all new WAVE formats.// and is not required for the standard WAVE_FORMAT_PCM files// 也就是说,这个结构体目前不是必须的,一般当wav文件由某些软件转化而成,则包含该Chunk// 但如果这里写了,则必须是如下的结构,并且在四个结构体中的位置也要放在第三typedef struct {char fccID[4]; // must be "fact"unsigned long id; // must be 0x4unsigned long dwSize; // 暂时没发现有啥用}FACT;// 12 bytes// 数据结构typedef struct {char fccID[4]; // must be "data"unsigned long dwSize; // byte_number of PCM data in byte}DATA;// 8 bytes/*------------------------Wave File Structure ------------------------------------ */void WriteWaveHeader(FILE *fpwav,long length){WAVE_HEADER WaveHeader;FORMAT WaveFMT;DATA WaveData;FACT WaveFact;memset(&WaveHeader, 0, sizeof(WAVE_HEADER));memcpy(WaveHeader.fccID, "RIFF", 4);memcpy(WaveHeader.fccType, "WAVE", 4);// dwSize 是整个wave文件的大小(字节数,但不包括不包括HEADER中的前面两个结构:// HEADER.fccID和HEAD.dwSize)// WaveHeader.dwSize = length + 0x24; // 如果不写入fact,就是36个字节,// 44- 8 = 36个 WaveHeader.dwSize = length + 0x30; // 如果写入fact,就是48 个bytesmemset(&WaveFMT, 0, sizeof(FORMAT));memcpy(WaveFMT.fccID, "fmt ", 4);WaveFMT.dwSize = 0x10;WaveFMT.dwSamplesPerSec = SAMPLE_RATE;WaveFMT.dwAvgBytesPerSec = CHANNEL_NUN * SAMPLE_RATE * BYTES_EACH_SAMPLE;WaveFMT.wChannels = CHANNEL_NUN;WaveFMT.uiBitsPerSample = QUANTIZATION;WaveFMT.wFormatTag = FORMAT_TAG;WaveFMT.wBlockAlign = BYTES_EACH_SAMPLE;memset(&WaveFact, 0, sizeof(FACT));memcpy(WaveFact.fccID, "fact", 4);WaveFact.dwSize = length; // 这个值不知道什么意思WaveFact.id = 0x4;memset(&WaveData, 0, sizeof(DATA));memcpy(WaveData.fccID, "data", 4);WaveData.dwSize = length;fwrite(&WaveHeader, sizeof(WAVE_HEADER), 1, fpwav);fwrite(&WaveFMT, sizeof(FORMAT), 1, fpwav);fwrite(&WaveFact, sizeof(FACT), 1, fpwav); // fact不是必须的fwrite(&WaveData, sizeof(DATA), 1, fpwav);}void WriteWavfile(FILE *fp, short *pSpeechData, int length){//write the header of wavWriteWaveHeader(fp, length * BYTES_EACH_SAMPLE);//write the datafwrite(pSpeechData, sizeof(short), length, fp);}#endif二:数据存储结构:根据声音文件的声道和量化数的不同,在头之后的数据存储有不同的格式,如下面:/share/detail/15909594---------------------------------------------------------------------| 单声道| 取样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(右) || | (低位字节) | (高位字节) | (低位字节) | (高位字节) |---------------------------------------------------------------------图:Wav的data数据的bit位置可能的几种形式三:各种头示例常用语音编码的WAVE文件头格式剖析--各种编码/content/10/0812/10/722458_45443101.shtml表18KHz采样、16比特量化的线性PCM语音信号的WAVE文件头格式表(共44字节)偏移地址字节数数据类型内容文件头定义为00H 4 char "RIFF" char riff_id[4]="RIFF"04H 4 long int 文件总长-8 long int size0=文总长-808H 8 char "WAVEfmt " char wave_fmt[8]10H 4 long int 10 00 00 00H(PCM) long int size1=0x1014H 2 int 01 00H int fmttag=0x0116H 2 int int channel=1 或218H 4 long int 采样率long int samplespersec1CH 4 long int 每秒播放字节数long int bytepersec20H 2 int 采样一次占字节数int blockalign=声道数*量化数/822H 2 int 量化数int bitpersamples=8或1624H 4 char "data" char data_id="data"28H 4 long int 采样数据字节数long int size2=文长-442CH 到文尾char 采样数据表28KHz采样、8比特A律量化的PCM语音信号的WAVE文件头格式表(共58字节)偏移地址字节数数据类型内容文件头定义为00H 4 char "RIFF" char riff_id[4]="RIFF"04H 4 long int 文件总长-8 long int size0=文总长-808H 8 char "WAVEfmt " char wave_fmt[8]10H 4 long int 12000000H(ALAW) long int size1=0x1214H 2 int 06 00H int fmttag=0x0616H 2 int 声道数int channel=1 或218H 4 long int 采样率long int samplespersec1CH 4 long int 每秒播放字节数long int bytepersec20H 2 int 采样一次占字节数int blockalign=0x0122H 4 long int 量化数long int bitpersamples=826H 4 char "fact" char wave_fact="fact"2AH 8 char 0400000000530700H定char temp32H 4 char "data" char wave_data="data"36H 4 long int 采样数据字节数lont int size2=文长-58表38KHz采样、8比特U律量化的PCM语音信号的WAVE文件头格式表(共58字节)偏移地址字节数数据类型内容文件头定义为00H 4 char "RIFF" char riff_id[4]="RIFF"04H 4 long int 文件总长-8 long int size0=文总长-808H 8 char "WAVEfmt " char wave_fmt[8]10H 4 long int 12000000H(ULAW) long int size1=0x1214H 2 int 07 00H int fmttag=0x0716H 2 int 声道数int channel=1 或218H 4 long int 采样率long int samplespersec1CH 4 long int 每秒播放字节数long int bytepersec20H 2 int 采样一次占字节数int blockalign=0x0122H 4 long int 量化数long int bitpersamples=826H 4 char "fact" char wave_fact="fact"2AH 8 char 0400000000530700H定char temp32H 4 char "data" char wave_data="data"36H 4 long int 采样数据字节数lont int size2=文长-58表4ADPCM语音编码后的WAVE文件头格式表(共90字节)偏移地址字节数数据类型内容文件头定义为00H 4 char "RIFF" char riff_id[4]="RIFF"04H 4 long int 文件总长-8 long int size0=文总长-808H 8 char "WAVEfmt " char wave_fmt[8]10H 4 long int 32000000H(ADPCM) long int size1=0x3214H 2 int 02 00H int fmttag=0x0216H 2 int 声道数int channel=1 或218H 4 long int 采样率long int samplespersec1CH 4 long int 每秒播放字节数long int bytepersec20H 2 int 采样一次占字节数int blockalign=声道数*量化数/822H 2 int 量化数int bitpersamples=424H 34 char 固定字节char temp146H 4 char "fact" char wave_fact="fact"4AH 8 char 0400000004930600H定char temp252H 4 char "data" char wave_data="data"56H 4 long int 采样数据字节数lont int size2=文长-905AH 到文尾采样数据表5GSM语音编码后的WAVE文件头格式表(共60字节)偏移地址字节数数据类型内容文件头定义为00H 4 char "RIFF" char riff_id[4]="RIFF"04H 4 long int 文件总长-8 long int size0=文总长-808H 8 char "WAVEfmt " char wave_fmt[8]10H 4 long int 14000000H(GSM) long int size1=0x1414H 2 int 31 00H int fmttag=0x3116H 2 int 声道数int channel=1 或218H 4 long int 采样率long int samplespersec1CH 4 long int 每秒播放字节数long int bytepersec20H 8 char 4100000002004001H定char temp128H 8 char 6661637404000000H定char temp230H 4 char 40 E2 05 00H定char temp334H 4 char "data" char wave_data="data"38H 4 long int 采样数据字节数lont int size2=文长-603CH 到文尾采样数据表6SBC语音编码后的WAVE文件头格式表(共58字节)偏移地址字节数数据类型内容文件头定义为00H 4 char "RIFF" char riff_id[4]="RIFF"04H 4 long int 文件总长-8 long int size0=文总长-808H 8 char "WAVEfmt " char wave_fmt[8]10H 4 long int 12000000H(SBC) long int size1=0x1214H 2 int 71 00H int fmttag=0x7116H 2 int 声道数int channel=1 或218H 4 long int 采样率long int samplespersec1CH 4 long int 每秒播放字节数long int bytepersec20H 2 int 采样一次占字节数int blockalign=0x2522H 4 long int 量化数long int bitpersamples=1626H 4 char "fact" char wave_fact="fact"2AH 8 char 0400000076280400H定char temp32H 4 char "data" char wave_data="data"36H 4 long int 采样数据字节数lont int size2=文长-59表7CELP语音编码后的WAVE文件头格式表(共58字节)偏移地址字节数数据类型内容文件头定义为00H 4 char "RIFF" char riff_id[4]="RIFF"04H 4 long int 文件总长-8 long int size0=文总长-808H 8 char "WAVEfmt " char wave_fmt[8]10H 4 long int 12000000H(CELP) long int size1=0x1214H 2 int 70 00H int fmttag=0x7016H 2 int 声道数int channel=1 或218H 4 long int 采样率long int samplespersec1CH 4 long int 每秒播放字节数long int bytepersec20H 2 int 采样一次占字节数int blockalign=0x0C22H 4 long int 量化数long int bitpersamples=1626H 4 char "fact" char wave_fact="fact"2AH 8 char 0400000060520700H定char temp32H 4 char "data" char wave_data="data"36H 4 long int 采样数据字节数lont int size2=文长-58WAVEFORMATEXtypedef struct{WORD wFormatTag; WORD nChannels; DWORD nSamplesPerSec; DWORD nAvgBytesPerSec; WORD nBlockAlign; WORD wBitsPerSample; WORD cbSize; } WAVEFORMATEX;具体参数解释如下:wFormatTag:波形数据的格式,定义在MMREG.H文件中nChannels:波形数据的通道数:单声道或立体声nSamplesPerSec:采样率,对于PCM格式的波形数据,采样率有8.0 kHz,11.025kHz,22.05 kHz,44.1 kHz等nAvgBytesPerSec:数据率,对于PCM格式的波形数据,数据率等于采样率乘以每样点字节数nBlockAlign:每个样点字节数wBitsPerSample:采样精度,对于PCM格式的波形数据,采样精度为8或16cbSize:附加格式信息的数据块大小概念2、定义设备头结构WAVEHDR定义了指向波形数据缓冲区的设备头。

相关主题