【数据压缩】WAV PCM FORMAT

时间:2022-05-08 19:42:49

       WAV文件是微软公司开发的一种声音文件格式,大部分的WAV文件中的音频数据是直接通过PCMPulse Code Modulation)脉冲编码调制得到的样本数据,由于未被压缩或压缩比很小所以其质量较高,但同时数据量也很大。在数字领域,存储音频文件的最直接方式就是在满足奈奎斯特抽样定理的条件下,将模拟的音频文件进行抽样量化,将得到的一系列样本值以二进制形式存储在文件中,这就是PCM脉冲编码调制的大致步骤。尽管大部分的WAV文件存储的都是未经压缩的,但它也支持一些音频压缩方法。

      那么如何将模拟的音频变成存储在电脑中的二进制数据呢?首先是选定抽样频率,对模拟音频进行抽样使得其在时间域是离散的,再将抽样值进行量化。WAV文件对每个抽样值的量化比特数没有具体规定,但固定在存储时每个样本值由整数个字节来表示,因此每个样本值的比特数均应该为8bit的整数倍如8bit16bit24bit32bit等。当某个样本值的比特数不是8bit的整数倍时,则需要将其左移并再低位填充0使其变成8bit的整数倍。例如某个抽样量化后的样本值为1011000101,则存储时需要将其补010110001 01000000,再采用小端序(先存低字节,再存高字节,默认存储方式)的方式进行存储,最终该样值被存为B1 40。一个需要注意的小细节是在 WAV文件中,8bit的是unsigned 类型的无符号数据,但16bit或更高的量化级的都是signed 类型的有符号数

      将模拟音频转化为二进制的数据后,要想将其存储在电脑中需要考虑其数据组织的形式,这样在后续对文件进行操作时会更加方便。WAV文件是一种基于RIFF规范的音频文件格式。RIFFResource Interchange File Format)是一种自包含的文件组织格式,它的基本单位是Chunk,一个基于RIFF规范的文件是由若干个Chunk组成的。

Chunk:

1.基本格式:

struct chunk

{

u32   chunk_id;             /* 块标志 */

u32   chunk_size;          /* 块大小*/

u8      data[chunk_size]; /* 块内容*/

};

chunk_id是一个4字节的ASCII标识符,用来标识该Chunk中的数据,不足四字节的再末尾用空位占位。可以有:'RIFF','LIST','fmt ','data','WAV ','AVI '等,采用小端序。

chunk_size也是四字节,存储的是data中的数据长度(以字节为单位),不包括chunk_idchunk_size本身所占的内存单元。

data[chunk_size]:该Chunk中的数据,必须为偶数个字节,若长度为奇数则在最后添一个空字节。

2.各种子类:

Chunk有多种子类,其中两种类型为“RIFF”和“LIST”的两种Chunk可以包含其他块,其他的Chunk则只能有数据。

RIFF/LIST”子类格式如下:

struct chunk

{

u32   chunk_ id;                   /* 块标志 */

u32   chunk_size;                 /* 块大小 ,由于此时的data部分分为typerestdata两部分,所以chunk_size应该为typerestdata数据长度之和*/

u32    type;                           /* 类型 */

u8      restdata[chunk_size-4] /* data中除了type4个字节后的数据,可以有包含的其他Chunk的数据 */

};

 

WAV文件格式:

一个WAV文件就是一个RIFF文件。其组成方式为:一个RIFF Chunk,其type为“WAVE”,其restdata部分包含了两个Chunk分别为“fmt Chunk和“data Chunk

其详细的结构如下:

【数据压缩】WAV PCM FORMAT

ChunkID:四字节,“RIFF”(ASCII字符)

ChunkSize:四字节,表示该WAV文件除去ChunkID和ChunkSize之外的所有数据长度的总和,等于Format长度+SubChunk1长度(绿色部分)+Subchunk2长度(橙色部分),即4+4+4+Subchunk Size+4+4+Subchunk2 Size=4+24+8+Subchunk2 Size=36+Subchunk2 Size,由于只能用4字节来表示文件的大小,因此WAV文件限制在4GB内(有的程序限制其大小为2GB)

Format:四字节,,表示该RIFF文件的类型,此处为:“WAVE”(ASCII字符)

Subchunk1ID:四字节,“fmt ”(注意末尾有一个空格占位,因为一个Chunk的ID必须为四位的ASCII字符)

Subchunk1Size:四字节,“fmt”chunk除去Subchunk1ID和Subchunk1Size之外的所有数据长度之和,为2+2+4+4+2+2=16

AudioFormat:两字节,表示音频数据的编码方式,PCM=1,若不为1则表示其他的数据编码方式,其值所代表的详细编码方式可以见文章末尾;

NumChannels:两字节,表示声道数,Mono = 1,Stereo = 2等

SampleRate:四字节,采样率,常见的采样率有8000,44100等(单位为Hz);

ByteRate:四字节,表示一秒钟内的音频信号数据需要多少个字节来存储,为SampleRate* NumChannels * BitsPerSample/8

BlockAlign:两字节,表示每一时刻的音频信号的抽样值需要几个字节来表示,为NumChannels* BitsPerSample/8

BitsPerSample:两字节,表示量化比特数,8bits = 8, 16 bits = 16等;

(若该音频文件不是PCM 编码,则其fmt chunk后还会有一些其他的参数)

Subchunk2 ID:四字节,“data”ASCII字符);

Subchunk2 Size:四字节,data部分数据的长度,若为奇数则在末尾添加空字节使得长度为偶数;

DataSubchunk2Size个字节,实际的声音数据。


下面是举例说明一个WAV文件中的数据(只列举了文件的前72字节):

【数据压缩】WAV PCM FORMAT

其颜色与上面的结构图相对应。由图可知该WAV文件是双声道、16bit量化的,因此某一时刻的样本值由四字节来表示。文件的音频信号样值若为多声道,其值是交叉排列的,例如双声道为:左声道样值、右声道样值、左声道样值、右声道样值……如此排列,多声道同理。


Audio Format这个参数的值,可以得知WAV文件中音频数据的编码方式,下列是目前WAV文件支持的编码方式:

Code      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)
     GSM 6.10
64 (0x0040)
     ITU G.721 ADPCM
80 (0x0050)
     MPEG
65,536 (0xFFFF)
 Experimental

 

本文参考网址:

http://www.codeguru.com/cpp/g-m/multimedia/audio/article.php/c8935/PCM-Audio-and-Wave-Files.htm

http://soundfile.sapp.org/doc/WaveFormat/