首页 > 学院 > 开发设计 > 正文

WAVE文件头格式剖析以及pcm2wav

2019-11-08 00:59:49
字体:
来源:转载
供稿:网友

转自: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=文总长-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 采样数据  表2 8KHz采样、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表3 8KHz采样、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表4 ADPCM语音编码后的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 到文尾 采样数据    表5 GSM语音编码后的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 到文尾 采样数据    表6 SBC语音编码后的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表7 CELP语音编码后的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=文长-58

[cpp] view plain copy// Test.cpp : 定义控制台应用程序的入口点。  //    #include "stdafx.h"  #include <stdlib.h>  #include <stdio.h>  #include <malloc.h>  #include <windows.h>  #include <string>  using namespace std;    struct tagHXD_WAVFLIEHEAD  {      CHAR RIFFNAME[4];      DWord nRIFFLength;      CHAR WAVNAME[4];      CHAR FMTNAME[4];      DWORD nFMTLength;      WORD nAudioFormat;        WORD nChannleNumber;      DWORD nSampleRate;      DWORD nBytesPerSecond;      WORD nBytesPerSample;      WORD    nBitsPerSample;      CHAR    DATANAME[4];      DWORD   nDataLength;  };typedef tagHXD_WAVFLIEHEAD HXD_WAVFLIEHEAD;    int a_law_pcm_to_wav(const char *pcm_file, const char *wav)  {      // 开始准备WAV的文件头      HXD_WAVFLIEHEAD DestionFileHeader;      DestionFileHeader.RIFFNAME[0] = 'R';      DestionFileHeader.RIFFNAME[1] = 'I';      DestionFileHeader.RIFFNAME[2] = 'F';      DestionFileHeader.RIFFNAME[3] = 'F';        DestionFileHeader.WAVNAME[0] = 'W';      DestionFileHeader.WAVNAME[1] = 'A';      DestionFileHeader.WAVNAME[2] = 'V';      DestionFileHeader.WAVNAME[3] = 'E';        DestionFileHeader.FMTNAME[0] = 'f';      DestionFileHeader.FMTNAME[1] = 'm';      DestionFileHeader.FMTNAME[2] = 't';      DestionFileHeader.FMTNAME[3] = 0x20;      DestionFileHeader.nFMTLength = 16;  //  表示 FMT 的长度      DestionFileHeader.nAudioFormat = 6; //这个表示a law PCM        DestionFileHeader.DATANAME[0] = 'd';      DestionFileHeader.DATANAME[1] = 'a';      DestionFileHeader.DATANAME[2] = 't';      DestionFileHeader.DATANAME[3] = 'a';      DestionFileHeader.nBitsPerSample = 8;      DestionFileHeader.nBytesPerSample = 1;    //      DestionFileHeader.nSampleRate = 8000;    //      DestionFileHeader.nBytesPerSecond = 8000;      DestionFileHeader.nChannleNumber = 1;        // 文件头的基本部分      int nFileLen = 0;      int nSize = sizeof(DestionFileHeader);        FILE *fp_s = NULL;      FILE *fp_d = NULL;        fp_s = fopen(pcm_file, "rb");      if (fp_s == NULL)          return -1;        fp_d = fopen(wav, "wb+");      if (fp_d == NULL)          return -2;          int nWrite = fwrite(&DestionFileHeader, 1, nSize, fp_d);     //将文件头写入wav文件      if (nWrite != nSize)      {          fclose(fp_s);          fclose(fp_d);          return -3;      }        while( !feof(fp_s))      {          char readBuf[4096];          int nRead = fread(readBuf, 1, 4096, fp_s);    //将pcm文件读到readBuf          if (nRead > 0)          {              fwrite(readBuf, 1, nRead, fp_d);      //将readBuf文件的数据写到wav文件          }            nFileLen += nRead;      }      fseek(fp_d, 0L, SEEK_SET);   //将读写位置移动到文件开头        DestionFileHeader.nRIFFLength = nFileLen - 8 + nSize;      DestionFileHeader.nDataLength = nFileLen;      nWrite = fwrite(&DestionFileHeader, 1, nSize, fp_d);   //重新将文件头写入到wav文件      if (nWrite != nSize)      {          fclose(fp_s);          fclose(fp_d);          return -4;      }        fclose(fp_s);      fclose(fp_d);        return nFileLen;  }      int _tmain(int argc, _TCHAR* argv[])  {        char pcm[256]={0},wav[256]={0};      strcpy(pcm,"C://2200124.pcm");      strcpy(wav,"C://2200124.wav");      a_law_pcm_to_wav(pcm,wav);           getchar();      return 0;  }  
上一篇:内存四区

下一篇:翻转二叉树

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表