WAVE文件作为多媒体中使用的声波文件格式之一,它是以RIFF格式为标准的。RIFF是英文Resource Interchange File Format的缩写,每个WAVE文件的头四个字节便是“RIFF”。WAVE文件由文件头和数据体两大部分组成。其中文件头又分为RIFF/WAV文件标识段和声音数据格式说明段两部分。
Wave主要包含size:
1,ChunkSize 整个文件大小,不能用它提取音频数据,Chunk1Size不固定而且文件结尾可能有填充描述信息
2,SubChunk1Size 如若不是10H,说明Chunk1有附加信息,Size就不固定,Chunk2的offset就不再是36,如要找Chunk2,需要检索 64 61 74 61 data的关键字。
3,SubChunk2Size 音频数据的真实大小。
Offset | BlockName | Size | Comment |
0 | ChunkID | 4 | 52 49 46 46 RIFF |
4 | ChunkSize | 4 | ChunkSize + 8(chunkId和chunksize)= 整个文件大小 |
8 | Format | 4 | 57 41 56 45 WAVE |
12 | Subchunk1ID | 4 | 66 6D 74 20 fmt |
16 | SubChunk1Size | 4 | 10H:subchunk1没有附加信息,常规size, e.g:12H:chunk1包含附加信息,chunk size不固定 |
20 | AudioFormat | 2 | 1:pcm编码 |
22 | NumChannels | 2 | Channel Number |
24 | SampleRate | 4 | Sample Rate |
28 | ByteRate | 4 | SampleRate * NumChannels * BitsPerSample/8 |
32 | BlockAlign | 2 | NumChannels * BitsPerSample/8 |
34 | BitsPerSample | 2 | BitsPerSample |
36 | SubChunk2ID | 4 | 64 61 74 61 data |
40 | SubChunk2Size | 4 | 数据Data真实的Size |
44 | Data | Data | |
44+DataLen | Information | 有些wave会填充描述信息 |
分析Header的方案一,
直接定义一个头信息的结构体如下,然后直接fread到wav_header。
但是有个大小端的问题,比如uint32_t是由四个字节组合而成的。
struct wav_header {
uint32_t riff_id;
uint32_t riff_sz;
uint32_t riff_fmt;
uint32_t fmt_id;
uint32_t fmt_sz;
uint16_t audio_format;
uint16_t num_channels;
uint32_t sample_rate;
uint32_t byte_rate;
uint16_t block_align;
uint16_t bits_per_sample;
uint32_t data_id;
uint32_t data_sz;
};
分析Header的方案二
定义一个44个字节的数组,灵活但是不简洁
/*read the header*/
if(fread(head, sizeof(char), ID_WAVE_HEADER, fp) != ID_WAVE_HEADER)
{
printf("not a wave file\n");
return -1;
}
/*check the format pcm = 1*/
if (head[20] != PCM_FORMAT_16BITS_1)
{
printf("format != 1(pcm) :%d\n",head[20]);
return -1;
}
/*check the channel num = 2*/
if (head[22] != CHANNEL_2)
{
printf("channel num != 2 :%d\n",head[22]);
return -1;
}
/*check the samplerate = 48kHz*/
samplerate = head[24] + (head[25] << 8) + (head[26] << 8*2) + (head[27] << 8*3);
if (samplerate != SAMPLERATE_48KHZ)
{
printf("samplerate != 48000 :%d\n",samplerate);
return -1;
}
/*check the bits per frame*/
if (head[34] != SAMPLEBITS_16)
{
printf("bitsnum != 16 :%d\n",head[34]);
return -1;
}
/*calculate pcm data size*/
datanum = head[40] + (head[41] << 8) + (head[42] << 8*2) + (head[43] << 8*3);
printf("datanum :%d\n",datanum);
pcmdata = (char*)malloc(datanum);