WAVE文件头格式剖析以及pcm2wav

转自:http://blog.csdn.net/loveheronly/article/details/7383385



常用语音编码的WAVE文件头格式剖析


  WAVE文件头作为多媒体中使用的声波文件格式之一,它是以RIFF格式为标准的。RIFF是英文Resource Interchange File Format的缩写,每个WAVE文件的头四个字节便是“RIFF”。合理利用WAVE文件头可以更有效地进行语音解码。

  通常意义上说的语音编码都是指将8KHz采样、16比特量化的线性PCM语音信号压缩成其它格式的语音信号,解码时就将其它格式的语音信号变换成8KHz采样、16比特量化的线性PCM语音信号。一般说来,这个转换过程比较复杂,费时费力。如果对其它格式的语音信号直接加上对应的WAVE文件头就不用这个转换过程,用微软自带的录音机就可解码语音。

 下面就分别剖析各种语音编码的WAVE文件头格式,用如下各个表(表1到表7)进行对比即可。


表1 8KHz采样、16比特量化的线性PCM语音信号的WAVE文件头格式表(共44字节)




偏移地址 字节数 数据类型 内容 文件头定义为
00H 4 char "RIFF" char riff_id[4]="RIFF"
04H 4 long int 文件总长-8 long int size0=文总长-8
08H 8 char "WAVEfmt " char wave_fmt[8]
10H 4 long int 10 00 00 00H(PCM) long int size1=0x10
14H 2 int 01 00H int fmttag=0x01
16H 2 int int channel=1 或2
18H 4 long int 采样率 long int samplespersec
1CH 4 long int 每秒播放字节数 long int bytepersec
20H 2 int 采样一次占字节数 int blockalign=声道数*量化数/8
22H 2 int 量化数 int bitpersamples=8或16
24H 4 char "data" char data_id="data"
28H 4 long int 采样数据字节数 long int size2=文长-44
2CH 到文尾 char 采样数据  




表2 8KHz采样、8比特A律量化的PCM语音信号的WAVE文件头格式表(共58字节)




偏移地址 字节数 数据类型 内容 文件头定义为
00H 4 char "RIFF" char riff_id[4]="RIFF"
04H 4 long int 文件总长-8 long int size0=文总长-8
08H 8 char "WAVEfmt " char wave_fmt[8]
10H 4 long int 12000000H(ALAW) long int size1=0x12
14H 2 int 06 00H int fmttag=0x06
16H 2 int 声道数 int channel=1 或2
18H 4 long int 采样率 long int samplespersec
1CH 4 long int 每秒播放字节数 long int bytepersec
20H 2 int 采样一次占字节数 int blockalign=0x01
22H 4 long int 量化数 long int bitpersamples=8
26H 4 char "fact" char wave_fact="fact"
2AH 8 char 0400000000530700H定 char temp
32H 4 char "data" char wave_data="data"
36H 4 long int 采样数据字节数 lont int size2=文长-58




表3 8KHz采样、8比特U律量化的PCM语音信号的WAVE文件头格式表(共58字节)




偏移地址 字节数 数据类型 内容 文件头定义为
00H 4 char "RIFF" char riff_id[4]="RIFF"
04H 4 long int 文件总长-8 long int size0=文总长-8
08H 8 char "WAVEfmt " char wave_fmt[8]
10H 4 long int 12000000H(ULAW) long int size1=0x12
14H 2 int 07 00H int fmttag=0x07
16H 2 int 声道数 int channel=1 或2
18H 4 long int 采样率 long int samplespersec
1CH 4 long int 每秒播放字节数 long int bytepersec
20H 2 int 采样一次占字节数 int blockalign=0x01
22H 4 long int 量化数 long int bitpersamples=8
26H 4 char "fact" char wave_fact="fact"
2AH 8 char 0400000000530700H定 char temp
32H 4 char "data" char wave_data="data"
36H 4 long int 采样数据字节数 lont int size2=文长-58




表4 ADPCM语音编码后的WAVE文件头格式表(共90字节)




偏移地址 字节数 数据类型 内容 文件头定义为
00H 4 char "RIFF" char riff_id[4]="RIFF"
04H 4 long int 文件总长-8 long int size0=文总长-8
08H 8 char "WAVEfmt " char wave_fmt[8]
10H 4 long int 32000000H(ADPCM) long int size1=0x32
14H 2 int 02 00H int fmttag=0x02
16H 2 int 声道数 int channel=1 或2
18H 4 long int 采样率 long int samplespersec
1CH 4 long int 每秒播放字节数 long int bytepersec
20H 2 int 采样一次占字节数 int blockalign=声道数*量化数/8
22H 2 int 量化数 int bitpersamples=4
24H 34 char 固定字节 char temp1
46H 4 char "fact" char wave_fact="fact"
4AH 8 char 0400000004930600H定 char temp2
52H 4 char "data" char wave_data="data"
56H 4 long int 采样数据字节数 lont int size2=文长-90
5AH 到文尾 采样数据    




表5 GSM语音编码后的WAVE文件头格式表(共60字节)




偏移地址 字节数 数据类型 内容 文件头定义为
00H 4 char "RIFF" char riff_id[4]="RIFF"
04H 4 long int 文件总长-8 long int size0=文总长-8
08H 8 char "WAVEfmt " char wave_fmt[8]
10H 4 long int 14000000H(GSM) long int size1=0x14
14H 2 int 31 00H int fmttag=0x31
16H 2 int 声道数 int channel=1 或2
18H 4 long int 采样率 long int samplespersec
1CH 4 long int 每秒播放字节数 long int bytepersec
20H 8 char 4100000002004001H定 char temp1
28H 8 char 6661637404000000H定 char temp2
30H 4 char 40 E2 05 00H定 char temp3
34H 4 char "data" char wave_data="data"
38H 4 long int 采样数据字节数 lont int size2=文长-60
3CH 到文尾 采样数据    




表6 SBC语音编码后的WAVE文件头格式表(共58字节)




偏移地址 字节数 数据类型 内容 文件头定义为
00H 4 char "RIFF" char riff_id[4]="RIFF"
04H 4 long int 文件总长-8 long int size0=文总长-8
08H 8 char "WAVEfmt " char wave_fmt[8]
10H 4 long int 12000000H(SBC) long int size1=0x12
14H 2 int 71 00H int fmttag=0x71
16H 2 int 声道数 int channel=1 或2
18H 4 long int 采样率 long int samplespersec
1CH 4 long int 每秒播放字节数 long int bytepersec
20H 2 int 采样一次占字节数 int blockalign=0x25
22H 4 long int 量化数 long int bitpersamples=16
26H 4 char "fact" char wave_fact="fact"
2AH 8 char 0400000076280400H定 char temp
32H 4 char "data" char wave_data="data"
36H 4 long int 采样数据字节数 lont int size2=文长-59




表7 CELP语音编码后的WAVE文件头格式表(共58字节)




偏移地址 字节数 数据类型 内容 文件头定义为
00H 4 char "RIFF" char riff_id[4]="RIFF"
04H 4 long int 文件总长-8 long int size0=文总长-8
08H 8 char "WAVEfmt " char wave_fmt[8]
10H 4 long int 12000000H(CELP) long int size1=0x12
14H 2 int 70 00H int fmttag=0x70
16H 2 int 声道数 int channel=1 或2
18H 4 long int 采样率 long int samplespersec
1CH 4 long int 每秒播放字节数 long int bytepersec
20H 2 int 采样一次占字节数 int blockalign=0x0C
22H 4 long int 量化数 long int bitpersamples=16
26H 4 char "fact" char wave_fact="fact"
2AH 8 char 0400000060520700H定 char temp
32H 4 char "data" char wave_data="data"

36H 4 long int 采样数据字节数 lont int size2=文长-58


[cpp]  view plain  copy
  1. // Test.cpp : 定义控制台应用程序的入口点。  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include <stdlib.h>  
  6. #include <stdio.h>  
  7. #include <malloc.h>  
  8. #include <windows.h>  
  9. #include <string>  
  10. using namespace std;  
  11.   
  12. struct tagHXD_WAVFLIEHEAD  
  13. {  
  14.     CHAR RIFFNAME[4];  
  15.     DWORD nRIFFLength;  
  16.     CHAR WAVNAME[4];  
  17.     CHAR FMTNAME[4];  
  18.     DWORD nFMTLength;  
  19.     WORD nAudioFormat;  
  20.   
  21.     WORD nChannleNumber;  
  22.     DWORD nSampleRate;  
  23.     DWORD nBytesPerSecond;  
  24.     WORD nBytesPerSample;  
  25.     WORD    nBitsPerSample;  
  26.     CHAR    DATANAME[4];  
  27.     DWORD   nDataLength;  
  28. };typedef tagHXD_WAVFLIEHEAD HXD_WAVFLIEHEAD;  
  29.   
  30. int a_law_pcm_to_wav(const char *pcm_file, const char *wav)  
  31. {  
  32.     // 开始准备WAV的文件头  
  33.     HXD_WAVFLIEHEAD DestionFileHeader;  
  34.     DestionFileHeader.RIFFNAME[0] = 'R';  
  35.     DestionFileHeader.RIFFNAME[1] = 'I';  
  36.     DestionFileHeader.RIFFNAME[2] = 'F';  
  37.     DestionFileHeader.RIFFNAME[3] = 'F';  
  38.   
  39.     DestionFileHeader.WAVNAME[0] = 'W';  
  40.     DestionFileHeader.WAVNAME[1] = 'A';  
  41.     DestionFileHeader.WAVNAME[2] = 'V';  
  42.     DestionFileHeader.WAVNAME[3] = 'E';  
  43.   
  44.     DestionFileHeader.FMTNAME[0] = 'f';  
  45.     DestionFileHeader.FMTNAME[1] = 'm';  
  46.     DestionFileHeader.FMTNAME[2] = 't';  
  47.     DestionFileHeader.FMTNAME[3] = 0x20;  
  48.     DestionFileHeader.nFMTLength = 16;  //  表示 FMT 的长度  
  49.     DestionFileHeader.nAudioFormat = 6; //这个表示a law PCM  
  50.   
  51.     DestionFileHeader.DATANAME[0] = 'd';  
  52.     DestionFileHeader.DATANAME[1] = 'a';  
  53.     DestionFileHeader.DATANAME[2] = 't';  
  54.     DestionFileHeader.DATANAME[3] = 'a';  
  55.     DestionFileHeader.nBitsPerSample = 8;  
  56.     DestionFileHeader.nBytesPerSample = 1;    //  
  57.     DestionFileHeader.nSampleRate = 8000;    //  
  58.     DestionFileHeader.nBytesPerSecond = 8000;  
  59.     DestionFileHeader.nChannleNumber = 1;  
  60.   
  61.     // 文件头的基本部分  
  62.     int nFileLen = 0;  
  63.     int nSize = sizeof(DestionFileHeader);  
  64.   
  65.     FILE *fp_s = NULL;  
  66.     FILE *fp_d = NULL;  
  67.   
  68.     fp_s = fopen(pcm_file, "rb");  
  69.     if (fp_s == NULL)  
  70.         return -1;  
  71.   
  72.     fp_d = fopen(wav, "wb+");  
  73.     if (fp_d == NULL)  
  74.         return -2;  
  75.   
  76.   
  77.     int nWrite = fwrite(&DestionFileHeader, 1, nSize, fp_d);     //将文件头写入wav文件  
  78.     if (nWrite != nSize)  
  79.     {  
  80.         fclose(fp_s);  
  81.         fclose(fp_d);  
  82.         return -3;  
  83.     }  
  84.   
  85.     while( !feof(fp_s))  
  86.     {  
  87.         char readBuf[4096];  
  88.         int nRead = fread(readBuf, 1, 4096, fp_s);    //将pcm文件读到readBuf  
  89.         if (nRead > 0)  
  90.         {  
  91.             fwrite(readBuf, 1, nRead, fp_d);      //将readBuf文件的数据写到wav文件  
  92.         }  
  93.   
  94.         nFileLen += nRead;  
  95.     }  
  96.     fseek(fp_d, 0L, SEEK_SET);   //将读写位置移动到文件开头  
  97.   
  98.     DestionFileHeader.nRIFFLength = nFileLen - 8 + nSize;  
  99.     DestionFileHeader.nDataLength = nFileLen;  
  100.     nWrite = fwrite(&DestionFileHeader, 1, nSize, fp_d);   //重新将文件头写入到wav文件  
  101.     if (nWrite != nSize)  
  102.     {  
  103.         fclose(fp_s);  
  104.         fclose(fp_d);  
  105.         return -4;  
  106.     }  
  107.   
  108.     fclose(fp_s);  
  109.     fclose(fp_d);  
  110.   
  111.     return nFileLen;  
  112. }  
  113.   
  114.   
  115. int _tmain(int argc, _TCHAR* argv[])  
  116. {  
  117.   
  118.     char pcm[256]={0},wav[256]={0};  
  119.     strcpy(pcm,"C:\\2200124.pcm");  
  120.     strcpy(wav,"C:\\2200124.wav");  
  121.     a_law_pcm_to_wav(pcm,wav);  
  122.   
  123.     
  124.    getchar();  
  125.     return 0;  
  126. }  

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值