本文目的:
1、了解wave格式组成,了解wave头各个部分组成
wav 格式,是微软开发的一种文件格式规范,整个文件分为两部分,第一部分是“文件头”,记录重要的参数信息,对于音频而言,就包括:采样率、通道数、位宽等等;第二部分是“数据块”,即一帧一帧的二进制数据,对于音频而言,就是原始的 PCM 数据。
所以wav格式 = Header(44 bytes) + data
Offset | Size | Name | Description |
---|---|---|---|
0 | 4 | ChunkID | ASCII码”0x52494646”对应字母”RIFF” |
4 | 4 | ChunkSize | 块大小是指除去ChunkID与ChunkSize的剩余部分有多少字节数据。注意:小尾字节序数。Value=36+SubChunk2SizeValue=36+SubChunk2Size 或者Value=4+(8+SubChunk1Size)+(8+SubChunk2Size)。Value=4+(8+SubChunk1Size)+(8+SubChunk2Size)。 |
8 | 4 | Format | ASCII码”0x57415645”对应字母”WAVE”。该块由两个子快组成,一个“fmt”chunk用于详细说明数据格式,一个“data”chunk包含实际的样本数据。 |
12 | 4 | Subchunk1ID | ASCII码”0x666d7420”对应字母”fmt “。 |
16 | 4 | Subchunk1Size | 如果文件采用PCM编码,则该子块剩余字节数为16。 |
20 | 2 | AudioFormat | 如果文件采用PCM编码(线性量化),则AudioFormat=1。AudioFormat代表不同的压缩方式。 |
22 | 2 | NumChannels | 声道数,单声道(Mono)为1, 双声道(Stereo)为 2。 |
24 | 4 | SampleRate | 取样率,例:44.1kHz,48kHz。 |
28 | 4 | ByteRate | 传输速率,单位:Byte/s。Value==SampleRate∗NumChannels∗BitsPerSample/8Value==SampleRate∗NumChannels∗BitsPerSample/8 |
32 | 2 | BlockAlign | 一个样点(包含所有声道)的字节数。Value==NumChannels∗BitsPerSample/8Value==NumChannels∗BitsPerSample/8 |
34 | 2 | BitsPerSample | 每个样点对应的位数。 |
2 | ExtraParamSize | 如果采用PCM编码,该值不存在。 | |
X | ExtraParams | 用于存储其他参数。如果采用PCM编码,该值不存在。 | |
36 | 4 | Subchunk2ID | ASCII码”0x64617461”对应字母”data”。 |
40 | 4 | Subchunk2Size | 实际样本数据的大小(单位:字节)。Value==NumSamples∗NumChannels∗BitsPerSample/8Value==NumSamples∗NumChannels∗BitsPerSample/8 |
44 | * | Data | 实际的音频数据 。 |
简单地分析一下这个 wav 格式头,它主要分为三个部分:
第一部分,属于最“顶层”的信息块,通过“ChunkID”来表示这是一个 “RIFF”格式的文件,“ChunkSize”则记录了整个 wav 文件的字节数,"Format"包含了“WAVE”标识这是一个 wav 文件。
第二部分,属于“fmt”信息块,主要记录了本 wav 音频文件的详细音频参数信息,例如:通道数、采样率、位宽等等(含义请参考我的第一篇文章
第三部分,属于“data”信息块,由“Subchunk2Size”这个字段来记录后面存储的二进制原始音频数据的长度。
现在的wave支持哪些格式:
AudioFormat | Description |
---|---|
0 (0x0000) | Unknown |
1 (0x0001) | PCM/uncompressed |
2 (0x0002) | Microsoft ADPCM |
6 (0x0006) | ITU G.711 a-law |
7 (0x0007) | ITU G.711 µ-law |
17 (0x0011) | IMA ADPCM |
20 (0x0016) | ITU G.723 ADPCM (Yamaha) |
49 (0x0031) | ITU G.721 ADPCM |
80 (0x0050) | MPEG |
65,536 (0xFFFF) | Experimental |
将PCM文件转换为WAVE格式(其实就是在PCM前面加上了44个字节的头):
int simplest_pcm16le_to_wave(const char *pcmpath,int channels,int sample_rate,const char *wavepath)
{
typedef struct WAVE_HEADER{
char fccID[4];
unsigned long dwSize;
char fccType[4];
}WAVE_HEADER;
typedef struct WAVE_FMT{
char fccID[4];
unsigned long dwSize;
unsigned short wFormatTag;
unsigned short wChannels;
unsigned long dwSamplesPerSec;
unsigned long dwAvgBytesPerSec;
unsigned short wBlockAlign;
unsigned short uiBitsPerSample;
}WAVE_FMT;
typedef struct WAVE_DATA{
char fccID[4];
unsigned long dwSize;
}WAVE_DATA;
if(channels==0||sample_rate==0){
channels = 2;
sample_rate = 44100;
}
int bits = 16;
WAVE_HEADER pcmHEADER;
WAVE_FMT pcmFMT;
WAVE_DATA pcmDATA;
unsigned short m_pcmData;
FILE *fp,*fpout;
fp=fopen(pcmpath, "rb");
if(fp == NULL) {
printf("open pcm file error\n");
return -1;
}
fpout=fopen(wavepath, "wb+");
if(fpout == NULL) {
printf("create wav file error\n");
return -1;
}
//WAVE_HEADER
memcpy(pcmHEADER.fccID,"RIFF",strlen("RIFF"));
memcpy(pcmHEADER.fccType,"WAVE",strlen("WAVE"));
fseek(fpout,sizeof(WAVE_HEADER),1);
//WAVE_FMT
pcmFMT.dwSamplesPerSec=sample_rate;
pcmFMT.dwAvgBytesPerSec=pcmFMT.dwSamplesPerSec*sizeof(m_pcmData);
pcmFMT.uiBitsPerSample=bits;
memcpy(pcmFMT.fccID,"fmt ",strlen("fmt "));
pcmFMT.dwSize=16;
pcmFMT.wBlockAlign=2;
pcmFMT.wChannels=channels;
pcmFMT.wFormatTag=1;
fwrite(&pcmFMT,sizeof(WAVE_FMT),1,fpout);
//WAVE_DATA;
memcpy(pcmDATA.fccID,"data",strlen("data"));
pcmDATA.dwSize=0;
fseek(fpout,sizeof(WAVE_DATA),SEEK_CUR);
fread(&m_pcmData,sizeof(unsigned short),1,fp);
while(!feof(fp)){
pcmDATA.dwSize+=2;
fwrite(&m_pcmData,sizeof(unsigned short),1,fpout);
fread(&m_pcmData,sizeof(unsigned short),1,fp);
}
pcmHEADER.dwSize=44+pcmDATA.dwSize;
rewind(fpout);
fwrite(&pcmHEADER,sizeof(WAVE_HEADER),1,fpout);
fseek(fpout,sizeof(WAVE_FMT),SEEK_CUR);
fwrite(&pcmDATA,sizeof(WAVE_DATA),1,fpout);
fclose(fp);
fclose(fpout);
return 0;
}
调用方法:
simplest_pcm16le_to_wave("NocturneNo2inEflat_44.1k_s16le.pcm",2,44100,"output_nocturne.wav");
参考:
http://soundfile.sapp.org/doc/WaveFormat/