windows声音应用程序开发指南-第2章-WAV文件格式_第1页
windows声音应用程序开发指南-第2章-WAV文件格式_第2页
windows声音应用程序开发指南-第2章-WAV文件格式_第3页
windows声音应用程序开发指南-第2章-WAV文件格式_第4页
windows声音应用程序开发指南-第2章-WAV文件格式_第5页
已阅读5页,还剩69页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第2章WAV文件格式,2.1WAV文件格式1,2,3,42.2保存为WAV文件格式1,2,3,4,52.3压缩WAVE音频52.4本章小结,2.1WAV文件格式1,2,3,4,2.1.1RIFF文件和WAV文件格式1RIFF文件RIFF可以看做是一种树状结构,其基本构成单位为“块”(Chunk),它犹如树状结构中的节点。每个Chunk由“辨别码”(ID)、“数据大小”(Size)和“数据”(Data)所组成,如表2-1所示。,表2-1RIFF文件格式,一般而言,Chunk本身并不允许内部再包含Chunk,但有两种情况例外,即分别以“RIFF”及“LIST”为辨别码的Chunk可以包含子Chunk。以“RIFF”为辨别码的Chunk包含子Chunk的格式如图2-1所示。图中前4个字符,图2-1RIFF文件结构,2WAV文件WAV为WAVEFORM(波形)的缩写。WAV文件的结构如图2-2所示,RIFFChunk中子Chunk的“格式辨别码”为“WAVE”。整个文件由两个Chunk所组成:辨别码“fmt”(注意,最后一个是空白字符)及“data”。,图2-2WAV文件结构,在“fmt”的Chunk下包含了一个PCMWAVEFORMAT数据结构,该结构与前一章中的WAVEFORMATEX结构类似,其定义如下:typedefstructwaveformat-tagWORDwFormatTag;WORDnChannels;DWORDnSamplesPerSec;DWORDnAvgBytesperSec;WORDnBlockAlign;WAVEFORMAT;,typedefstructpcmwaveformat-tagWAVEFORMATwf;WORDwBitsPerSample;PCMWAVEFORMAT;,其意义分别如下:wFormatTag:记录着此声音的格式代号,例如WAVE_FORMAT_PCM,WAVE_FORMAT_ADPCM等等。nChannels:记录声音的声道数。nSamp1esPerSec:记录每秒采样数(采样率)。nAvgBytesPerSec:记录每秒的平均数据量。nBlockA1ign:记录块的对齐单位。wBitsPerSample:记录每个采样样本所需的位元数。,“data”Chunk包含真正的声音数据。Windows目前仅提供WAVE_FORMAT_PCM一种数据格式,其所代表的意义是脉冲编码调制(PCM,Pu1seCodeModulation)。用编辑工具UltraEdit查看WAV文件的文件头,如图2-3所示。表2-2以数据在文件中的存放位置说明了WAV文件格式,其中偏移地址是相对于文件头的地址。,图2-3WAV文件的文件头,表2-2WAV文件格式说明表,Windows定义了在“data”Chunk中数据的存放情形,表2-3列出了四种不同声道数及取样所需的位元数以及位元位置的安排。其中:对于8位单声道,每个样本数据由8位(bit)表示;对于8位立体声,每个声道的数据由一个8位(bit)数据表示,且第一个8位(bit)数据表示0声道(左)数据,紧随其后的8位(bit)数据表示1声道(右)数据;对于16位单声道,每个样本数据由16位(bit)表示;,对于16位立体声,每个声道的数据由一个16位(bit)数据表示,且第一个16位(bit)数据表示0声道(左)数据,紧随其后的16位(bit)数据表示1声道(右)数据。,表2-3PCM数据的存放方式,WAV文件的每个样本值包含在一个整数i中,i的长度为容纳指定样本长度所需的最小字节数。首先存储低有效字节,表示样本幅度的位放在i的高有效位上,剩下的位置为0,这样8位和16位的PCM波形样本的数据格式如表2-4所示。,表2-4PCM数据的存放方式,2.1.2WAV文件信息的具体应用WAV文件包括了对原始声音的高速率采样数据,并且以WAVE_PCM_FORMAT格式的形式保存。在读出WAV文件头信息之后,接着的数据就是原始声音的高速率采样信息。我们可以在VisualC+程序中对这些信息作多方面的处理,其中包括:,波形显示我们可以以时间振幅的方式显示出原始声音的波形,这是最简单同时也是最直接的信息处理方式。在时间范围内,我们可以观察该信号波形是否连续,中间是否有跳变等。频谱显示我们可以以频率振幅的方式显示出原始声音的频谱,在对原始信号经过FFT变换之后,可以得到该信号的频谱,进而得到该信号的能量集中带、分布特征、谱对称系数等等。,用于语音信号识别讲话者的个体识别是语音信号处理的一个重要内容,但它的一个前提条件是必须提供语音信号的数字波形。通常的方法是将原始的语音信号进行放大、抗混叠滤波、A/D采样、数值编码,最终得到语音信号的数字波形。,2.2保存为WAV文件格式1,2,3,4,5,2.2.1创建一个空文件用系统函数CreateFile创建一个空文件,其程序如下:#includeFILE*m_fp=NULL;/文件句柄DWORDdwFileSize=0;/文件长度,DWORDdwTotalAudioLength=0;/声音数据长度HANDLEOpenFileToWrite(LPCTSTRlpFileName)SECURITY_ATTRIBUTESsa;sa.nLength=sizeof(SECURITY_ATTRIBUTES);sa.lpSecurityDescriptor=NULL;sa.bInheritHandle=FALSE;returnCreateFile(lpFileName,GENERIC_WRITE,0,2.2.2写WAV文件头首先,要得到声音采样数据的相关信息,通常这些信息存储在一个WAVEFORMATEX结构中,用系统函数WriteFile将文件头信息写入新创建的文件。其程序如下:BOOLWriteWaveFileHeader(char*DesFilename,WAVEFORMATEXwfx)longcbFmtChunk,cbDataChunk;,/m_fp在前面已定义过m_fp=fopen(DesFilename,w+b);if(!m_fp)returnFALSE;/打开文件出错cbFmtChunk=sizeof(WAVEFORMATEX)+wfx.cbSize;/WAVEFORMATEX结构长度dwFileSize=46;/46为文件头的长度dwTotalAudioLength=0;cbDataChunk=dwTotalAudioLength;,fwrite(RIFF,1,sizeof(DWORD),m_fp);/RIFF标识符(占用4Byte)fwrite(/WAVEFORMAT结构的长度(4Byte),fwrite(,2.2.3写声音数据将给定缓冲区中声音数据写入WAV文件,其程序如下:BOOLWriteWaveFileData(LPBYTElpBufferData,DWORDdwDataSize)if(dwDataSize=0),returnFALSE;elsefwrite(lpBufferData,1,dwDataSize,m_fp);dwFileSize+=dwDataSize;/文件长度随着增加dwTotalAudioLength=dwTotalAudioLength+dwDataSize;/声音数据长度随着增加returnTRUE;,fseek(m_fp,42,SEEK_SET);/设置文件指针fwrite(,2.3压缩WAVE音频5,2.3.1CODECs介绍Microsoft的Windows95/98/NT/2000操作系统都具有能通过安装的CODECs处理编码的WAVE格式的音频和视频数据流的能力。一个CODEC是一小段用于编码(Code)及解码(DECode)数据流的代码(因此得名CODEC)。许多CODECs既能编码又能解码。而一些CODECs仅能用于解码,这样私有数据可以在系统上播放,但数据格式不能在系统上创建。,2.3.2系统中有什么CODECsMicrosoft的Windows95/98/NT/2000本身附带有几种标准的CODECs,也可由系统中所安装的应用程序安装其它的CODECs。例如,DSPGroup公司的TrueSpeechCODEC随Windows95发送,因此,用户写的任何基于Windows95的应用程序都可使用此CODEC(只要用户没有在控制面板中删除它或禁止它)。,所有安装的CODECs都由音频编码解码器(ACM)管理(见图2-4)。我们可以用一段小程序从ACM中查到安装了哪些CODECs,它们都支持什么格式。也可双击控制面板中的多媒体选项,选择高级标签,就能看到系统中所安装的CODECs。下面用一段程序介绍如何应用ACM。首先从调用ACM编程接口所需的包含的头文件开始:,#include#include#include/多媒体注册#include/音频编码解码器#include,图2-4音频编码解码器,mmsystem.h头文件包含了Windows支持的大部分的多媒体功能,但不包含ACM接口及任何厂商定义。mmreg.h包含了对不同厂商设计的各种WAVE数据类型的格式标签的定义。它也包含了用于处理不同的WAVE数据类型的结构(基于WAVEFORAMTEX)的定义。msacm.h包含了ACM所需的API、标志等等。我们要做的第一件事就是执行一些常见的ACM查询来判断版本号,获取它当前管理了多少个驱动程序的信息。下面是查询ACM的部分代码:,DWORDdwACMVer=acmGetVersion();printf(ACMversion%u.%.02ubuild%u,HIWORD(dwACMVer)8,HIWORD(dwACMVer),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(十进制)。,用acmMetrics函数可以知道系统中安装了多少个CODECs驱动程序:DWORDdwCodecs=0;MMRESULTmmr=acmMetrics(NULL,ACM_METRIC_COUNT_CODECS,对ACM有了简单了解后,现在可以要求它枚举出系统中当前所有的驱动程序。我们在程序中所调用的枚举函数使用回调函数来显示每个设备的数据,这在Windows编程中是一种很普遍的方法。下面的调用就是枚举当前ACM所管理的所有设备:/枚举所有允许的驱动程序printf(Enableddrivers:n);mmr=acmDriverEnum(DriverEnumProc,0,0);if(mmr)/show_error(mmr);,acmDriverEnum函数列举出可用的ACM驱动程序,第一个参数指出回调函数的地址。现在,让我们看看枚举回调函数DriverEnumProc,它由系统中的每一个驱动程序调用:BOOLCALLBACKDriverEnumProc(HACMDRIVERIDhadid,DWORDdwInstance,DWORDfdwSupport)printf(id:%8.8lxH,hadid);printf(supports:n);,if(fdwSupport,/获得一些具体信息ACMDRIVERDETAILSdd;dd.cbStruct=sizeof(dd);MMRESULTmmr=acmDriverDetails(hadid,else,printf(Shortname:%sn,dd.szShortName);printf(Longname:%sn,dd.szLongName);printf(Copyright:%sn,dd.szCopyright);printf(Licensing:%sn,dd.szLicensing);printf(Features:%sn,dd.szFeatures);printf(Supports%uformatsn,dd.cFormatTags);printf(Supports%ufilterformatsn,dd.cFilterTags);,/打开驱动程序HACMDRIVERhad=NULL;mmr=acmDriverOpen(,mmr=acmMetrics(had,ACM_METRIC_MAX_SIZE_FORMAT,if(mmr)printf();/show_error(mmr);free(pwf);acmDriverClose(had,0);returnTRUE;/继续枚举,为结构分配了空间后,现在可以用acmFormatEnum来枚举所支持的格式。这次又用到一个回调函数来取得枚举出的所支持格式的相关数据:BOOLCALLBACKFormatEnumProc(HACMDRIVERIDhadid,LPACMFORMATDETAILSpafd,DWORDdwInstance,DWORDfdwSupport)printf(%4.4lXH,%sn,pafd-dwFormatTag,pafd-szFormat);returnTRUE;/继续枚举,2.3.3使用特定的CODEC1两步实现编码在理想的情况下,编码一些数据可能只要向系统发出命令“这有一些数据,请编码成这种格式”即可。但实际上,Windows编程与理想相去甚远,在当前的现实中,我们得自已做许多琐碎的工作。,2编码的实现过程在本例中,实现编码分以下四个阶段:(1)创建一些WAV格式数据的样本;(2)找到一个合适的CODEC;(3)将数据转换为该CODEC可处理的中间格式;(4)将数据转换成所需的格式。,为了简单起见,源数据用程序创建,而不是录入或是从WAV文件中读取:/首先我们创建一个可能是刚刚才录制的WAV,其格式为11.025kHz,8位单声道PCM,这是一个/在所有机器上都可用的录入格式。例如1秒长的1kHz的正弦波WAVE,刚好1000个周期WAVEFORMATEXwfSrc;memset(,wfSrc.wFormatTag=WAVE_FORMAT_PCM;/PCMwfSrc.nChannels=1;/单声道wfSrc.nSamplesPerSec=11025;/11.025kHzwfSrc.wBitsPerSample=8;/8bitwfSrc.nBlockAlign=wfSrc.nChannels*wfSrc.wBitsPerSample/8;wfSrc.nAvgBytesPerSec=wfSrc.nSamplesPerSec*wfSrc.nBlockAlign;DWORDdwSrcSamples=wfSrc.nSamplesPerSec;,BYTE*pSrcData=newBYTEdwSrcSamples;/分配1秒种的长度内存空间BYTE*pData=pSrcData;doublef=1000.0;doublepi=4.0*atan(1.0);doublew=2.0*pi*f;for(DWORDdw=0;dwwBitsPerSample,pwfDrv-nSamplesPerSec);/获取驱动程序所支持的PCM格式标签/注意:我们只是选取CODEC所支持的枚举出的第一种PCM格式,但不一定是最好的选择WAVEFORMATEX*pwfPCM=get_driver_format(hadid,WAVE_FORMAT_PCM);if(pwfPCM=NULL)printf(ErrorgettingPCMformatinfon);exit(1);,printf(PCMformat:%ubits,%lusamplespersecondn,pwfPCM-wBitsPerSample,pwfPCM-nSamplesPerSec);还要进一步强调的是,get_driver_format函数仅仅枚举出第一种匹配的格式,也许不能获得最好的质量。,让我们看看第一步的转换,它完成的是将源数据转换为中间格式:/将源WAVE转换为CODEC所支持的PCM格式/我们使用任一种能实现PCM格式间相互转换的驱动程序HACMSTREAMhstr=NULL;mmr=acmStreamOpen(exit(1);/为转换结果开辟一个缓冲区DWORDdwSrcBytes=dwSrcSamples*wfSrc.wBitsPerSample/8;DWORDdwDst1Samples=dwSrcSamples*pwfPCM-nSamplesPerSec/wfSrc.nSamplesPerSec;DWORDdwDst1Bytes=dwDst1Samples*pwfPCM-wBitsPerSample/8;,BYTE*pDst1Data=newBYTEdwDst1Bytes;/填写转换信息ACMSTREAMHEADERstrhdr;memset(/转换数据,printf(ConvertingtointermediatePCMformat.n);mmr=acmStreamConvert(hstr,最后一步是将中间格式转换为最终的压缩格式:/将中间格式转换为最终的压缩格式/打开驱动程序HACMDRIVERhad=NULL;mmr=acmDriverOpen(,/打开转换流/注意使用了ACM_STREAMOPENF_NONREALTIME标志/若没有此标志,一些软件压缩程序会报告512号错误,即不可能mmr=acmStreamOpen(exit(1);/为转换结果分配一个缓冲区/根据以字节计的平均速率计算输出缓冲区的尺寸/并加上一机动位(bit),/若没有此额外的空间,IMA_ADPCM驱动程序将不能转换DWORDdwDst2Bytes=pwfDrv-nAvgBytesPerSec*dwDst1Samples/pwfPCM-nSamplesPerSec;dwDst2Bytes=dwDst2Bytes*3/2;/增加一点空间BYTE*pDst2Data=newBYTEdwDst2Bytes;/填写转换信息ACMSTREAMHEADERstrhdr2;

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论