1、第2章 WAV文件格式第第2 2章章 WAVWAV文件格式文件格式2.1 WAV文件格式文件格式1,2,3,42.2 保存为保存为WAV文件格式文件格式1,2,3,4,52.3 压缩压缩WAVE音频音频52.4 本本 章章 小小 结结第2章 WAV文件格式2.1 WAV文件格式文件格式1,2,3,4 2.1.1 RIFF文件和WAV文件格式 1RIFF文件 RIFF可以看做是一种树状结构,其基本构成单位为“块”(Chunk),它犹如树状结构中的节点。每个Chunk由“辨别码”(ID)、“数据大小”(Size)和“数据”(Data)所组成,如表2-1所示。第2章 WAV文件格式表2-1 RIFF
2、文件格式辨别码(ID)用4字符(ASCII码)表示用于表示Chunk“数据”的类型。如果一个应用程序不能识别该“辨别码”,则将忽略由Chunk“大小”所指定的Chunk“数据”和附加的数据数据大小(Size)用32位无符号数值表示用于表示Chunk“数据”的长度和Chunk“数据”后附加的数据长度(单位为Byte),这一值还包括Chunk“辨别码”和Chunk“大小”所占用的空间(共8Byte)数据(Data)二进制数据,数据可以是固定长度也可以是可变长度。相对于RIFF文件起始位置,数据是“字对齐”(Word-aligned)的,这样可以提高数据访问速度。如果数据的字节长度为奇数,那么在数据
3、后面要附加一个字节,以保持“字对齐”第2章 WAV文件格式 一般而言,Chunk本身并不允许内部再包含Chunk,但有两种情况例外,即分别以“RIFF”及“LIST”为辨别码的Chunk可以包含子Chunk。以“RIFF”为辨别码的Chunk包含子Chunk的格式如图2-1所示。图中前4个字符第2章 WAV文件格式图2-1 RIFF文件结构RIFF Chunk辨别码RIFF Chunk数据长度RIFF Chunk数据RIFF略(formTypechunk)RIFF中的子Chunk第2章 WAV文件格式 2WAV文件 WAV为WAVEFORM(波形)的缩写。WAV文件的结构如图2-2所示,RIF
4、F Chunk中子Chunk的“格式辨别码”为“WAVE”。整个文件由两个Chunk所组成:辨别码“fmt”(注意,最后一个是空白字符)及“data”。第2章 WAV文件格式图2-2 WAV文件结构RIFFxxxxWAVEfmtPCMWAVEFORMAT结构大小PCMWAVEFORMAT结构dataxxxxWAVE声音数据第2章 WAV文件格式 在“fmt”的Chunk下包含了一个PCMWAVEFORMAT数据结构,该结构与前一章中的WAVEFORMATEX结构类似,其定义如下:typedef struct waveformat-tag WORDwFormatTag;WORD nChannel
5、s;DWORDnSamplesPerSec;DWORD nAvgBytesperSec;WORDnBlockAlign;WAVEFORMAT;第2章 WAV文件格式typedef struct pcmwaveformat-tag WAVEFORMAT wf;WORD wBitsPerSample;PCMWAVEFORMAT;第2章 WAV文件格式 其意义分别如下:wFormatTag:记录着此声音的格式代号,例如WAVE_FORMAT_PCM,WAVE_FORMAT_ADPCM等等。nChannels:记录声音的声道数。nSamp1esPerSec:记录每秒采样数(采样率)。nAvgBytes
6、PerSec:记录每秒的平均数据量。nBlockA1ign:记录块的对齐单位。wBitsPerSample:记录每个采样样本所需的位元数。第2章 WAV文件格式 “data”Chunk包含真正的声音数据。Windows目前仅提供WAVE_FORMAT_PCM一种数据格式,其所代表的意义是脉冲编码调制(PCM,Pu1se Code Modulation)。用编辑工具UltraEdit查看WAV文件的文件头,如图2-3所示。表2-2以数据在文件中的存放位置说明了WAV文件格式,其中偏移地址是相对于文件头的地址。第2章 WAV文件格式图2-3 WAV文件的文件头第2章 WAV文件格式表2-2 WAV
7、文件格式说明表偏移地址字节数数据类型内 容 说 明00H4Char“RIFF”标志04H4Long文件长度08H4Char“WAVE”标志0CH4Char“fmt”标志10H4LongWAVEFORMAT结构的长度14H2Int格式类别(例如,10H为PCM形式的声音数据)16H2Int声道数,单声道为1,双声道为218H4Long采样率(每秒样本数),表示每个声道的播放速度1CH4long int波形音频数据传送速率,其值为(声道数每秒数据位数每样本的数据位数)/8。播放软件利用此值可以估计缓冲区的大小第2章 WAV文件格式偏移地址字节数数据类型内 容 说 明20H2Int数据块的调整数(按
8、字节算的),其值为(声道数每样本的数据位数)/8。播放软件需要一次处理多个该值大小的字节数据,以便将其值用于缓冲区的调整22H2Int每样本的数据位数,表示每个声道中各个样本的数据位数。如果有多个声道,对每个声道而言,样本大小都一样24H4Char数据标记符“data”28H4long int声音数据的长度28H以后 long int声音数据第2章 WAV文件格式 Windows定义了在“data”Chunk中数据的存放情形,表2-3列出了四种不同声道数及取样所需的位元数以及位元位置的安排。其中:对于8位单声道,每个样本数据由8位(bit)表示;对于8位立体声,每个声道的数据由一个8位(bit
9、)数据表示,且第一个8位(bit)数据表示0声道(左)数据,紧随其后的8位(bit)数据表示1声道(右)数据;对于16位单声道,每个样本数据由16位(bit)表示;第2章 WAV文件格式 对于16位立体声,每个声道的数据由一个16位(bit)数据表示,且第一个16位(bit)数据表示0声道(左)数据,紧随其后的16位(bit)数据表示1声道(右)数据。第2章 WAV文件格式表2-3 PCM数据的存放方式 样本1(1 Byte)样本2(1 Byte)样本3(1Byte)样本4(1Byte)8位单声道0声道0声道0声道0声道8位立体声0声道(左)1声道(右)0声道(左)1声道(右)样本1(2 By
10、te)样本2(2Byte)16位单声道0声道低字节0声道高字节0声道低字节0声道高字节16位立体声0声道(左)低字节0声道(左)高字节1声道(右)低字节1声道(右)高字节第2章 WAV文件格式 WAV文件的每个样本值包含在一个整数i中,i的长度为容纳指定样本长度所需的最小字节数。首先存储低有效字节,表示样本幅度的位放在i的高有效位上,剩下的位置为0,这样8位和16位的PCM波形样本的数据格式如表2-4所示。第2章 WAV文件格式表2-4 PCM数据的存放方式样本大小数据格式最大值最小值静 音8位PCMunsigned int225012816位PCMint32 767-32 7670第2章 W
11、AV文件格式 2.1.2 WAV文件信息的具体应用 WAV文件包括了对原始声音的高速率采样数据,并且以WAVE_PCM_FORMAT格式的形式保存。在读出WAV文件头信息之后,接着的数据就是原始声音的高速率采样信息。我们可以在Visual C+程序中对这些信息作多方面的处理,其中包括:第2章 WAV文件格式 波形显示 我们可以以时间振幅的方式显示出原始声音的波形,这是最简单同时也是最直接的信息处理方式。在时间范围内,我们可以观察该信号波形是否连续,中间是否有跳变等。频谱显示 我们可以以频率振幅的方式显示出原始声音的频谱,在对原始信号经过FFT变换之后,可以得到该信号的频谱,进而得到该信号的能量
12、集中带、分布特征、谱对称系数等等。第2章 WAV文件格式 用于语音信号识别 讲话者的个体识别是语音信号处理的一个重要内容,但它的一个前提条件是必须提供语音信号的数字波形。通常的方法是将原始的语音信号进行放大、抗混叠滤波、A/D采样、数值编码,最终得到语音信号的数字波形。第2章 WAV文件格式2.2 保存为保存为WAV文件格式文件格式1,2,3,4,5 2.2.1 创建一个空文件 用系统函数CreateFile创建一个空文件,其程序如下:#include FILE*m_fp=NULL;/文件句柄 DWORDdwFileSize=0;/文件长度第2章 WAV文件格式DWORD dwTotalAud
13、ioLength=0;/声音数据长度 HANDLEOpenFileToWrite(LPCTSTR lpFileName)SECURITY_ATTRIBUTESsa;sa.nLength=sizeof(SECURITY_ATTRIBUTES);sa.lpSecurityDescriptor=NULL;sa.bInheritHandle=FALSE;return CreateFile(lpFileName,GENERIC_WRITE,0,&sa,C R E A T E _ A L W A Y S,FILE_ATTRIBUTE_NORMAL,NULL);第2章 WAV文件格式 2.2.2 写WAV文
14、件头 首先,要得到声音采样数据的相关信息,通常这些信息存储在一个WAVEFORMATEX结构中,用系统函数WriteFile将文件头信息写入新创建的文件。其程序如下:BOOL WriteWaveFileHeader(char*DesFilename,WAVEFORMATEX wfx)long cbFmtChunk,cbDataChunk;第2章 WAV文件格式 /m_fp在前面已定义过m_fp=fopen(DesFilename,w+b);if(!m_fp)return FALSE;/打开文件出错cbFmtChunk=sizeof(WAVEFORMATEX)+wfx.cbSize;/WAVEF
15、ORMATEX结构长度dwFileSize=46;/46为文件头的长度dwTotalAudioLength=0;cbDataChunk=dwTotalAudioLength;第2章 WAV文件格式 fwrite(RIFF,1,sizeof(DWORD),m_fp);/RIFF标识符(占用4 Byte)fwrite(&dwFileSize,1,sizeof(DWORD),m_fp);/文件长度(占用4 Byte)fwrite(WAVE,1,sizeof(DWORD),m_fp);/WAVE标识符(占用4 Byte)fwrite(fmt,1,sizeof(DWORD),m_fp);/fmt标识符(
16、占用4 Byte)fwrite(&cbFmtChunk,1,sizeof(DWORD),m_fp);/WAVEFORMAT结构的长度(4Byte)第2章 WAV文件格式 f w r i t e (&w f x,1,c b F m t C h u n k,m _ f p );/WAVEFORMAT结构的内容(18Byte)fwrite(data,1,sizeof(DWORD),m_fp);/data标识符(占用4 Byte)fwrite(&cbDataChunk,1,sizeof(DWORD),m_fp);/声音数据长度(占用4 Byte)return TRUE;第2章 WAV文件格式 2.2.
17、3 写声音数据 将给定缓冲区中声音数据写入WAV文件,其程序如下:BOOL WriteWaveFileData(LPBYTE lpBufferData,DWORD dwDataSize)if(dwDataSize=0)第2章 WAV文件格式 return FALSE;elsefwrite(lpBufferData,1,dwDataSize,m_fp);dwFileSize+=dwDataSize;/文件长度随着增加dwTotalAudioLength=dwTotalAudioLength+dwDataSize;/声音数据长度随着增加return TRUE;第2章 WAV文件格式fseek(m_
18、fp,42,SEEK_SET);/设置文件指针fwrite(&dwTotalAudioLength,1,sizeof(DWORD),m_fp);/写入声音数据长度fclose(m_fp);/关闭文件m_fp=NULL;return true;第2章 WAV文件格式2.3 压缩压缩WAVE音频音频5 2.3.1 CODECs介绍 Microsoft的Windows 95/98/NT/2000操作系统都具有能通过安装的CODECs处理编码的WAVE格式的音频和视频数据流的能力。一个CODEC是一小段用于编码(Code)及解码(DECode)数据流的代码(因此得名CODEC)。许多CODECs既能编
19、码又能解码。而一些CODECs仅能用于解码,这样私有数据可以在系统上播放,但数据格式不能在系统上创建。第2章 WAV文件格式 2.3.2 系统中有什么CODECs Microsoft的Windows 95/98/NT/2000本身附带有几种标准的CODECs,也可由系统中所安装的应用程序安装其它的 CODECs。例如,DSP Group公司的TrueSpeech CODEC随Windows 95发送,因此,用户写的任何基于Windows 95的应用程序都可使用此CODEC(只要用户没有在控制面板中删除它或禁止它)。第2章 WAV文件格式 所有安装的CODECs都由音频编码解码器(ACM)管理(
20、见图2-4)。我们可以用一段小程序从ACM中查到安装了哪些CODECs,它们都支持什么格式。也可双击控制面板中的多媒体选项,选择高级标签,就能看到系统中所安装的CODECs。下面用一段程序介绍如何应用ACM。首先从调用ACM编程接口所需的包含的头文件开始:第2章 WAV文件格式#include#include#include /多媒体注册#include /音频编码解码器#include 第2章 WAV文件格式图2-4 音频编码解码器 第2章 WAV文件格式 mmsystem.h头文件包含了Windows支持的大部分的多媒体功能,但不包含ACM接口及任何厂商定义。mmreg.h包含了对不同厂商
21、设计的各种WAVE数据类型的格式标签的定义。它也包含了用于处理不同的WAVE数据类型的结构(基于WAVEFORAMTEX)的定义。msacm.h包含了ACM所需的API、标志等等。我们要做的第一件事就是执行一些常见的ACM查询来判断版本号,获取它当前管理了多少个驱动程序的信息。下面是查询ACM的部分代码:第2章 WAV文件格式DWORD dwACMVer=acmGetVersion();printf(ACM version%u.%.02u build%u,HIWORD(dwACMVer)8,HIWORD(dwACMVer)&0 x00FF,LOWORD(dwACMVer);if(LOWORD(
22、dwACMVer)=0)printf(Retail);printf(n);第2章 WAV文件格式 acmGetVersion函数返回一个32位的十六进制数值,表示ACM的版本号,其形如0 xAABBCCCC。其中,AA代表ACM的主版本号;BB代表ACM的副版本号;CCCC代表ACM的debug版本的build号,对于一个非debug版本(零售版)的ACM,CCCC总为0。例如,在应用程序中返回版本号为0 x05000856,则ACM版本号为5.00,且系统中安装的是debug版本,build号为2134(十进制)。第2章 WAV文件格式 用acmMetrics函数可以知道系统中安装了多少个C
23、ODECs驱动程序:DWORD dwCodecs=0;M M R E S U L T m m r=a c m M e t r i c s(N U L L,ACM_METRIC_COUNT_CODECS,&dwCodecs);if(mmr)/show_error(mmr);else printf(%lu codecs installedn,dwCodecs);第2章 WAV文件格式 对ACM有了简单了解后,现在可以要求它枚举出系统中当前所有的驱动程序。我们在程序中所调用的枚举函数使用回调函数来显示每个设备的数据,这在Windows编程中是一种很普遍的方法。下面的调用就是枚举当前ACM所管理的所有
24、设备:/枚举所有允许的驱动程序 printf(Enabled drivers:n);mmr=acmDriverEnum(DriverEnumProc,0,0);if(mmr)/show_error(mmr);第2章 WAV文件格式 acmDriverEnum函数列举出可用的ACM驱动程序,第一个参数指出回调函数的地址。现在,让我们看看枚举回调函数DriverEnumProc,它由系统中的每一个驱动程序调用:BOOL CALLBACK DriverEnumProc(HACMDRIVERID hadid,DWORD dwInstance,DWORD fdwSupport)printf(id:%8.
25、8lxH,hadid);printf(supports:n);第2章 WAV文件格式 if(fdwSupport&ACMDRIVERDETAILS_SUPPORTF_ASYNC)printf(async conversionsn);if(fdwSupport&ACMDRIVERDETAILS_SUPPORTF_CODEC)printf(different format conversionsn);if(fdwSupport&ACMDRIVERDETAILS_SUPPORTF_CONVERTER)printf(same format conversionsn);if(fdwSupport&ACM
26、DRIVERDETAILS_SUPPORTF_FILTER)printf(filteringn);第2章 WAV文件格式/获得一些具体信息 ACMDRIVERDETAILS dd;dd.cbStruct=sizeof(dd);MMRESULT mmr=acmDriverDetails(hadid,&dd,0);if(mmr)printf();/show_error(mmr);else 第2章 WAV文件格式 printf(Short name:%sn,dd.szShortName);printf(Long name:%sn,dd.szLongName);printf(Copyright:%sn
27、,dd.szCopyright);printf(Licensing:%sn,dd.szLicensing);printf(Features:%sn,dd.szFeatures);printf(Supports%u formatsn,dd.cFormatTags);printf(Supports%u filter formatsn,dd.cFilterTags);第2章 WAV文件格式/打开驱动程序 HACMDRIVER had=NULL;mmr=acmDriverOpen(&had,hadid,0);if(mmr)printf();/show_error(mmr);else DWORD dwS
28、ize=0;第2章 WAV文件格式 mmr=acmMetrics(had,ACM_METRIC_MAX_SIZE_FORMAT,&dwSize);if(dwSizecbSize=LOWORD(dwSize)sizeof(WAVEFORMATEX);pwf-wFormatTag=WAVE_FORMAT_UNKNOWN;ACMFORMATDETAILS fd;memset(&fd,0,sizeof(fd);fd.cbStruct=sizeof(fd);fd.pwfx=pwf;fd.cbwfx=dwSize;fd.dwFormatTag=WAVE_FORMAT_UNKNOWN;mmr=acmForm
29、atEnum(had,&fd,FormatEnumProc,0,0);第2章 WAV文件格式if(mmr)printf();/show_error(mmr);free(pwf);acmDriverClose(had,0);return TRUE;/继续枚举第2章 WAV文件格式 为结构分配了空间后,现在可以用acmFormatEnum来枚举所支持的格式。这次又用到一个回调函数来取得枚举出的所支持格式的相关数据:BOOL CALLBACK FormatEnumProc(HACMDRIVERID hadid,LPACMFORMATDETAILS pafd,DWORD dwInstance,DWOR
30、D fdwSupport)printf(%4.4lXH,%sn,pafd-dwFormatTag,pafd-szFormat);return TRUE;/继续枚举 第2章 WAV文件格式 2.3.3 使用特定的CODEC 1两步实现编码 在理想的情况下,编码一些数据可能只要向系统发出命令“这有一些数据,请编码成这种格式”即可。但实际上,Windows编程与理想相去甚远,在当前的现实中,我们得自已做许多琐碎的工作。第2章 WAV文件格式 2编码的实现过程 在本例中,实现编码分以下四个阶段:(1)创建一些WAV格式数据的样本;(2)找到一个合适的CODEC;(3)将数据转换为该CODEC可处理的中
31、间格式;(4)将数据转换成所需的格式。第2章 WAV文件格式为了简单起见,源数据用程序创建,而不是录入或是从WAV文件中读取:/首先我们创建一个可能是刚刚才录制的WAV,其格式为11.025 kHz,8位单声道PCM,这是一个/在所有机器上都可用的录入格式。例如1秒长的1 kHz的正弦波WAVE,刚好1000个周期 WAVEFORMATEX wfSrc;memset(&wfSrc,0,sizeof(wfSrc);wfSrc.cbSize=0;第2章 WAV文件格式 wfSrc.wFormatTag=WAVE_FORMAT_PCM;/PCM wfSrc.nChannels=1;/单声道 wfSr
32、c.nSamplesPerSec=11025;/11.025 kHz wfSrc.wBitsPerSample=8;/8 bit w f S r c.n B l o c k A l i g n =w f S r c.n C h a n n e l s *wfSrc.wBitsPerSample/8;wfSrc.nAvgBytesPerSec=wfSrc.nSamplesPerSec*wfSrc.nBlockAlign;DWORD dwSrcSamples=wfSrc.nSamplesPerSec;第2章 WAV文件格式 BYTE*pSrcData=new BYTE dwSrcSamples;/
33、分配1秒种的长度内存空间 BYTE*pData=pSrcData;double f=1000.0;double pi=4.0*atan(1.0);double w=2.0*pi*f;for(DWORD dw=0;dw wBitsPerSample,pwfDrv-nSamplesPerSec);/获取驱动程序所支持的PCM格式标签 /注意:我们只是选取CODEC所支持的枚举出的第一种PCM格式,但不一定是最好的选择 WAVEFORMATEX*pwfPCM=get_driver_format(hadid,WAVE_FORMAT_PCM);if(pwfPCM=NULL)printf(Error ge
34、tting PCM format infon);exit(1);第2章 WAV文件格式 printf(PCM format:%u bits,%lu samples per secondn,pwfPCM-wBitsPerSample,pwfPCM-nSamplesPerSec);还要进一步强调的是,get_driver_format函数仅仅枚举出第一种匹配的格式,也许不能获得最好的质量。第2章 WAV文件格式 让我们看看第一步的转换,它完成的是将源数据转换为中间格式:/将源WAVE转换为CODEC所支持的PCM格式 /我们使用任一种能实现PCM格式间相互转换的驱动程序 HACMSTREAM hs
35、tr=NULL;mmr=acmStreamOpen(&hstr,第2章 WAV文件格式 NULL,/任一驱动程序&wfSrc,/源格式 pwfPCM,/目标格式 NULL,/不过滤 NULL,/无回调函数 0,/实例数据(未使用)ACM_STREAMOPENF_NONREALTIME);/标志第2章 WAV文件格式if(mmr)printf(Failed to open a stream to do PCM to PCM conversionn);exit(1);/为转换结果开辟一个缓冲区 DWORD dwSrcBytes=dwSrcSamples*wfSrc.wBitsPerSample/8
36、;DWORD dwDst1Samples=dwSrcSamples*pwfPCM-nSamplesPerSec/wfSrc.nSamplesPerSec;DWORD dwDst1Bytes=dwDst1Samples*pwfPCM-wBitsPerSample/8;第2章 WAV文件格式 BYTE*pDst1Data=new BYTE dwDst1Bytes;/填写转换信息 ACMSTREAMHEADER strhdr;memset(&strhdr,0,sizeof(strhdr);strhdr.cbStruct=sizeof(strhdr);strhdr.pbSrc=pSrcData;/要转
37、换的源数据 strhdr.cbSrcLength=dwSrcBytes;strhdr.pbDst=pDst1Data;strhdr.cbDstLength=dwDst1Bytes;/准备好头 mmr=acmStreamPrepareHeader(hstr,&strhdr,0);/转换数据第2章 WAV文件格式 printf(Converting to intermediate PCM format.n);mmr=acmStreamConvert(hstr,&strhdr,0);if(mmr)printf(Failed to do PCM to PCM conversionn);exit(1);
38、printf(Converted OKn);/关闭流 acmStreamClose(hstr,0);第2章 WAV文件格式最后一步是将中间格式转换为最终的压缩格式:/将中间格式转换为最终的压缩格式 /打开驱动程序 HACMDRIVER had=NULL;mmr=acmDriverOpen(&had,hadid,0);if(mmr)printf(Failed to open drivern);exit(1);第2章 WAV文件格式 /打开转换流 /注意使用了ACM_STREAMOPENF_NONREALTIME标志 /若没有此标志,一些软件压缩程序会报告512号错误,即不可能 mmr=acmSt
39、reamOpen(&hstr,had,/驱动程序句柄 pwfPCM,/源格式 pwfDrv,/目标格式 NULL,/不过滤 NULL,/无回调函数 0,/实例数据(未使用)第2章 WAV文件格式 if(mmr)printf(Failed to open a stream to do PCM to driver format conversionn);exit(1);/为转换结果分配一个缓冲区 /根据以字节计的平均速率计算输出缓冲区的尺寸 /并加上一机动位(bit)第2章 WAV文件格式/若没有此额外的空间,IMA_ADPCM驱动程序将不能转换 DWORD dwDst2Bytes=pwfDrv-
40、nAvgBytesPerSec*dwDst1Samples/pwfPCM-nSamplesPerSec;dwDst2Bytes=dwDst2Bytes*3/2;/增加一点空间 BYTE*pDst2Data=new BYTE dwDst2Bytes;/填写转换信息 ACMSTREAMHEADER strhdr2;memset(&strhdr2,0,sizeof(strhdr2);strhdr2.cbStruct=sizeof(strhdr2);strhdr2.pbSrc=pDst1Data;/要转换的源数据 strhdr2.cbSrcLength=dwDst1Bytes;第2章 WAV文件格式
41、strhdr2.pbDst=pDst2Data;strhdr2.cbDstLength=dwDst2Bytes;/准备头 mmr=acmStreamPrepareHeader(hstr,&strhdr2,0);/转换数据 printf(Converting to final format.n);mmr=acmStreamConvert(hstr,&strhdr2,0);if(mmr)printf(Failed to do PCM to driver format conversionn);exit(1);第2章 WAV文件格式 printf(Converted OKn);/关闭流及驱动程序 m
42、mr=acmStreamClose(hstr,0);mmr=acmDriverClose(had,0);以上与PCM格式间的转换很相似,但此次我们提供了打开流时想要使用的驱动程序的句柄。实际上,此处仍可使用NULL,因为已预知此驱动程序存在,但提供句柄避免了系统浪费时间为我们查找此驱动程序。第2章 WAV文件格式 /显示转换统计结果 printf(Source wave had%lu bytesn,dwSrcBytes);printf(Converted wave has%lu bytesn,strhdr2.cbDstLengthUsed);printf(Compression ratio i
43、s%fn,(double)dwSrcBytes/(double)strhdr2.cbDstLengthUsed);使用Windows操作系统中所附的CODECs来压缩WAV格式数据易于使用,并使数据占用存储空间更少,传输时间更短。如果你有自已的压缩格式,可创建并安装自已的CODEC,像这里的代码一样使用它 第2章 WAV文件格式2.4 本本 章章 小小 结结 WAV文件是Windows音频中最常用到的一种文件格式,它是RIFF文件类型中的一种。本章主要分析了WAV文件格式,并在Visual C+中实现了如何创建一个WAV文件并保存PCM音频数据。第2章 WAV文件格式 应该说,WAV文件是最简单的一种文件格式之一,因为它保存的是最原始的、未被压缩的PCM数据,是对采样数据最完整的体现,所以通过对WAV文件的分析、统计和可视化显示,可以得到最准确的结果。但是WAV文件又是一个效率不高的存储格式,尤其在网络速度慢,并且系统的存储能力有限的情况下,使用WAV文件就会显得很笨拙了。当然WAV文件的地位和历史意义也是不能否认的。