在做音频信号采集或音频信号分析时会经常遇到wav格式的文件,本章将介绍wav文件的格式。wav是基于资源交换文件格式(RIFF(Resource Interchange File Format))的应用之一。RIFF是一种带标签的文件结构,其可以定义许多文件格式,比如wav音频文件格式。RIFF文件由块结构组成,块结构由3个部分组成,分别为块ID、块大小、块数据,其中块ID由4字节组成,用于描述块数据;块大小由32位无符号整形数据表示,其只计算块数据的大小,不包含块ID和块大小的长度;块数据由字节数组组成,其采用小端格式,但其是双字节对齐的,当块大小为奇数个时,需要在数据后面补充一个字节。块数据用C代码表示如下所示:
typedef struct
{
uint8_t ckID[4];
uint32_t ckSize;
uint8_t ckData[CKSIZE];
}CK;
wave文件格式如下所示:
其中WAVE chunks由一些WAVE的子块数据组成,比如fmt块、data块。
fmt块:
fmt块携带着wav音频文件重要信息,比如采样率,采样点的数据大小等等,其结构如下所示:
可以看出fmt的块大小cksize值有3个,分别为16、18、40,这取决于wFormatTag的值,当wFormatTag = 0x0001(WAVE_FORMAT_PCM),即PCM格式,cksize = 16;当wFormatTag = 0xFFFE(WAVE_FORMAT_EXTENSIBLE),即扩展格式,cksize = 40;wFormatTag为其他值时,即非PCM格式,cksize = 18。
data块:
data块包含了采集的音频数据,其结构如下所示:
注意当cksize为奇数时,需要往sampled data后面补齐一个空字节的值(0x00)。
举例:
由于大多数实验采集和分析的是PCM格式的wav文件,因此下面将介绍PCM格式的wav文件,如下所示:
其中Nc 为通道数;Ns为块的数目,一个块由Nc个采样组成;M为每个采样数据的字节长度;F为采样速率(块/秒)。
wav格式代码解析
由如上举例,我们可以清楚的知道wav文件具体的格式,通常在存储wav数据到U盘或SD卡时,要先预设cksize字段的值,然后根据实际存储到U盘或SD卡的数据来更新cksize字段的值。代码待续。。。