wave file用来保存波形数据。PCM数据可以用wave file来存储。
wave file由一系列的chunk组成,但必须包含一个fmt chunk,和一个data chunk。最基本的结构是这样的:
__________________________ | riff wave chunk | | groupid = 'riff' | | rifftype = 'wave' | | __________________ | | | format chunk | | | | ckid = 'fmt ' | | | |__________________| | | __________________ | | | sound data chunk | | | | ckid = 'data' | | | |__________________| | |__________________________|
数据的存储以sample point为单位,如果是多channel的话,这些channle的sample points组成一个sample frame。下图是2 channel的形式:
sample sample sample frame 0 frame 1 frame n _____ _____ _____ _____ _____ _____ | ch1 | ch2 | ch1 | ch2 | . . . | ch1 | ch2 | |_____|_____|_____|_____| |_____|_____| _____ | | = one sample point |_____|multi-channel的sample frame排列如下:
channels 1 2 _________ _________ | left | right | stereo | | | |_________|_________| 1 2 3 _________ _________ _________ | left | right | center | 3 channel | | | | |_________|_________|_________| 1 2 3 4 _________ _________ _________ _________ | front | front | rear | rear | quad | left | right | left | right | |_________|_________|_________|_________| 1 2 3 4 _________ _________ _________ _________ | left | center | right | surround| 4 channel | | | | | |_________|_________|_________|_________| 1 2 3 4 5 6 _________ _________ _________ _________ _________ _________ | left | left | center | right | right |surround | 6 channel | center | | | center | | | |_________|_________|_________|_________|_________|_________|
另外一个要注意的地方,wave file中数据的存储是little endian排列的。
format chunk
用c语言来表示format chunk的结构如下所示:
#define formatid 'fmt ' /* chunkid for format chunk. note: there is a space at the end of this id. */ typedef struct { id chunkid; long chunksize; short wformattag; unsigned short wchannels; unsigned long dwsamplespersec; unsigned long dwavgbytespersec; unsigned short wblockalign; unsigned short wbitspersample; /* note: there may be additional fields here, depending upon wformattag. */ } formatchunk;
chunksize不包括chunkid 和chunksize所占的8个byte。format chunk里包含了波形数据的各种参数,比如采样率,声道数, bit宽度等。如果存储的是非压缩的数据,比如PCM,wformattag的值为1。如果存储的是压缩的数据,那wformattag值不是1,而且除了format chunk,还需要其他的chunk来保护一些解码必须的参数。
另外几个参数的关系是:wblockalign=wchannels * (wbitspersample % 8);
dwavgbytespersec=dwsamplespersec * wblockalign;
data chunk
data chunk的结构用c语言表示如下:#define dataid 'data' /* chunk id for data chunk */ typedef struct { id chunkid; long chunksize; unsigned char waveformdata[]; } datachunk;chunksize不包括chunkid 和chunksize所占的8个byte。
最简单的也是最基础的wave file format就介绍完了,下面咱们来一个例子吧!下面是一个wave file的前72 bytes.
52 49 46 46 24 08 00 00 57 41 56 45 66 6d 74 20 10 00 00 00 01 00 02 00
22 56 00 00 88 58 01 00 04 00 10 00 64 61 74 61 00 08 00 00 00 00 00 00
24 17 1e f3 3c 13 3c 14 16 f9 18 f9 34 e7 23 a6 3c f2 24 f2 11 ce 1a 0d