转自http://blog.csdn.net/ao929929fei/article/details/6164210
1、PCM和WAV
WAV可以使用多种音频编码来压缩其音频流,不过我们常见的都是音频流被PCM编码处理的WAV,但这不表示WAV只能使用PCM编码,MP3编码同样也可以运用在WAV中,和AVI一样,只要安装好了相应的Decode,就可以欣赏这些WAV了。在Windows平台下,基于PCM编码的WAV是被支持得最好的音频格式,所有音频软件都能完美支持,由于本身可以达到较高的音质的要求,因此,WAV也是音乐编辑创作的首选格式,适合保存音乐素材。因此,基于PCM编码的WAV被作为了一种中介的格式,常常使用在其他编码的相互转换之中,例如MP3转换成WMA。
简单来说:pcm是无损wav文件中音频数据的一种编码方式,但wav还可以用其它方式编码。wav其实是一种文件格式,里面包含的声音类型有pcm,MP3,
wav文件包括头和数据两部分,其结构如下:(从文件头开始依次排列)
1)首先是字符串“RIFF” ,占4个字节。(Resource Interchange File Format)
2)波形块的大小:DWORD,占4字节。波形块的大小=(文件大小-8)看下面的表
3)字符串"WAVE",占4个字节。
4)字符串“fmt ”,占4个字节,注意fmt后有个空格字符(0x20)。
5)格式块的大小,DWORD,占4个字节
6)格式块,VC中用WAVEFORMATEX结构体描述,占18个字节,可用sizeof(WAVEFORMATEX)计算。
其中WAVEFORMATEX结构体的定义为:(更详细的描述可以参考msdn)
typedef struct tWAVEFORMATEX
{
WORD wFormatTag; /* format type */
WORD nChannels; /* number of channels (i.e. mono, stereo...) */
DWORD nSamplesPerSec; /* sample rate */
DWORD nAvgBytesPerSec; /* for buffer estimation */
WORD nBlockAlign; /* block size of data */
WORD wBitsPerSample; /* number of bits per sample of mono data */
WORD cbSize; /* the count in bytes of the size of */
/* extra information (after cbSize) */
} WAVEFORMATEX, *PWAVEFORMATEX, NEAR *NPWAVEFORMATEX, FAR *LPWAVEFORMATEX;
7)字符串"data",占4个字节。
8)波形数据的大小,DWORD,占4个字节。
9)声音数据,大小在8)中描述。
以下是一个波形文件样本的头部:
00000000h: 52 49 46 46 E6 E4 05 00 57 41 56 45 66 6D 74 20 ; RIFF驿..WAVEfmt
00000010h: 12 00 00 00 01 00 01 00 40 1F 00 00 80 3E 00 00 ; [email protected]? >..
00000020h: 02 00 10 00 00 00 64 61 74 61 C0 E4 05 00 ; ......data冷..
从该样本可以看出:
该波形文件波形块的大小为386278(0x0005E4E6),波形文件大小为:386278+8 =386286字节;
格式块的大小(WAVEFORMATEX结构体)为18字节;
波形数据的大小为386240字节(0x0005E4C0);
就是说你想要的数据应该就在这两个数据其中一个
格式块(WAVEFORMATEX结构体)中定义的声音数据属性为:
wFormatTag=0x0001 即WAVE_FORMAT_PCM ;
nChannels = 0x0001 即单声道;
nSamplesPerSec = 0x00001F40 即采样率8000Hz;
nAvgBytesPerSec = 0x00003E80 即平均字节速率16000字节(16bit量化),可以根据该数据估计缓冲区的大小;
nBlockAlign = 0x0002 即块联合为2字节(16bit量化,2字节表示一个采样点,播放时必须从以块为单位从块头开始播放);
wBitsPerSample = 0x0010 即每个采样点的比特值为16(16bit量化)。nBlockAlign值即由该值除以8计算出来;
cbSize不使用,填0x0000。
声音数据就是通过MM_WIM_DATA处理获取的数据