Wave檔案格式
Wave檔案格式( Waveform Audio File Format )
WAVE檔案是多媒體中最常用的數字化聲音檔案格式之一,它是微軟專門為Windows系統定義的波形檔案(Waveform Audio),故又稱為波形聲音檔案,其擴展名為"*.wav"。
WAVE檔案是以RIFF格式(Resource Interchange File Format,資源交互檔案格式)為標準的,每個WAVE檔案的頭四個位元組便是"RIFF"。而常見聲音檔案主要有2種,分別是
WAVE檔案是由若干個Chunk組成的。按照在檔案中的出現位置包括:RIFF Type Chunk、Format Chunk、Fact Chunk、Data Chunk。其中除了Fact Chunk外,其他三個Chunk是必須的。每個Chunk有各自的ID,位於Chunk最開始位置,作為標示,而且均為4個位元組。並且緊跟在ID後面的是Chunk大小(去除ID和Size所佔的位元組數後剩下的其他位元組數目),4個位元組表示,低位元組表示數值低位元元,高位元組表示數值高位元。Chunk相對位置及具體結構介紹如下表五、表六所示:
表五、WAVE檔案包含之Chunk位置關係
RIFF Type Chunk |
Format Chunk |
Data Chunk |
Chunk name | offest | size | Description | Value |
RIFF Chunk (12 Bytes) | 0x00 | 4 | ChunkID | "RIFF" (0x52494646) |
0x04 | 4 | Chunk Data Size | (file size) - 8 | |
0x08 | 4 | RIFF Type | "WAVE" (0x57415645) | |
Format Chunk | 0x00 | 4 | ChunkID | "fmt " (0x666D7420) |
0x04 | 4 | Chunk Data Size | 16 + extra format bytes | |
0x08 | 2 | Compression code | 1 - 65,535(PCM:16) | |
0x | 2 | Number of channels | 1 - 65,535 | |
0x | 4 | Sample rate | 1 - 0xFFFFFFFF | |
0x10 | 4 | Average bytes per second | 1 - 0xFFFFFFFF | |
0x14 | 2 | Block align | 1 - 65,535 | |
0x16 | 2 | Significant bits per sample | 2 - 65,535 | |
0x18 | 2 | Extra format bytes | 0 - 65,535 | |
0x | Extra format bytes * | |||
Fact Chunk | 0x00 | 4 | Chunk ID | "fact" (0x66616374) |
0x04 | 4 | Chunk Data Size | depends on format | |
0x08 | Format Dependant Data | |||
Data Chunk | 0x00 | 4 | ChunkID | “data” (0x64617461) |
0x04 | 4 | Chunk Data Size | depends on sample length and compression | |
0x08 | Sample data |
l RIFF Chunk:
這個Chunk的大小固定為12個位元組,ID為”RIFF”,然後接著為size欄位,該size是整個wave檔案大小減去ID和Size所佔用的位元組數,即FileSize - 8 = Size。然後是Type欄位,為'WAVE',表示是wave檔案。結構定義如下:
struct RIFF_HEADER
{ char szRiffID[4]; // 'R','I','F','F'
DWORD dwRiffSize;
char szRiffFormat[4]; // 'W','A','V','E'
};
struct RIFF_HEADER
{ char szRiffID[4]; // 'R','I','F','F'
DWORD dwRiffSize;
char szRiffFormat[4]; // 'W','A','V','E'
};
l Format Chunk:
n Chunk ID and Data Size:ID為"fmt " (0x666D7420)且Size值為標準WAVE格式資料的大小(16個位元組)加上附加訊息的大小(2個位元組),所以值為16或18。如果聲音資料是用未壓縮的PCM編碼格式則沒有附加訊息欄位。
n Compression Code:壓縮的格式類別代碼,常見的如下表七所示:
表七、Common Wave Compression Codes
Code | Description |
0 (0x0000) | Unknown |
1 (0x0001) | Microsoft PCM /uncompressed |
2 (0x0002) | Microsoft ADPCM |
6 (0x0006) | ITU G |
7 (0x0007) | ITU G.711 μ-law(美國和日本) |
17 (0x0011) | Interactive Multimedia Association ADPCM (IMA ADPCM) |
20 (0x0016) | ITU G.723 ADPCM (Yamaha) |
49 (0x0031) | Microsoft GSM 6.10 Audio (GSM 610) |
64 (0x0040) | ITU G.721 |
80 (0x0050) | ADPCM MPEG |
65,536 (0xFFFF) | Experimental |
n Number of Channels:聲音頻道數
u 1 = 8 bit Mono
u 2 = 8 bit Stereo or 16 bit Mono
u 4 = 16 bit Stereo
n Sample Rate:取樣頻率(每秒取樣數),常見的值為8000~44100,但這個值與聲音頻道數沒有關係
n Average Bytes Per Second:每秒的資料量
u
其值AvgBytesPerSec = SampleRate * BlockAlign
u
(
取樣頻率 *
每個完整樣本的byte數 或 取樣頻率 * 聲音頻道數 * 每個樣本大小/8)
n Block Align:每個完整樣本的byte數
u
其值BlockAlign = NumChannels * SignificantBitsPerSample / 8
u(
聲音頻道數
*
每個樣本大小
/ 8)
n Significant Bits Per Sample:每個樣本的大小,常見的值有8、16、24、32
n Extra Format Bytes:若為未壓縮之PCM檔案則不存在這個欄位,但採用除PCM以外的壓縮編碼格式則這個欄位一定存在。
WAVE的基本結構WAVEFORMATEX結構定義如下:
typedef struct
{ WORD wFormatTag; //編碼格式,包括WAVE_FORMAT_PCM、
//WAVEFORMAT_ADPCM等
WORD nChannls; //聲音頻道數,單聲道(mono)為1,
//雙聲道(stereo)為2
DWORD nSamplesPerSec; //取樣頻率(每秒取樣數),通常為11025、 22050
//或是44100
DWORD nAvgBytesperSec; //每秒的資料量(每秒需要的平均位元元組個數)
WORD nBlockAlign; //每個完整樣本的byte數
//通常值為wBitsPerSample * nChannls / 8
WORD wBitsPerSample; //每個樣本的大小,通常為8 bits或16 bits
WORD cbSize; //用來描述特殊的wave格式的其他欄位
// (Extra Format Bytes)的大小,PCM中忽略此值
}WAVEFORMATEX;
l Fact Chunk:
Fact Chunk,結構如下:
typedef struct
{ char[4]; //”fact”字串
DWORD chunksize;
DWORD datafactsize; //資料轉換為PCM格式後的大小
}factchunk;
datafactsize是這個chunk中最重要的資料,如果這是某種壓縮格式的聲音檔案,那麼從這裡就可以知道它解壓縮後的大小。對於解壓時的計算會有很大的好處!
l Data Chunk:
這個Chunk前8個位元組儲存的是Chunk ID和Data Size,ID為”data”,後面接著Size儲存的是聲音資料的實際大小,也就是扣除掉整個表頭(44個位元組)的檔案大小。而從Data Chunk的第9個位元組開始,存儲的就是聲音信息的資料了,這些資料可以是PCM(沒有壓縮)或ADPCM(壓縮)格式
WAVE檔案有多種不同的編碼格式,以下只介紹其中的PCM 和IMA-ADPCM兩種。
n PCM:
最基本的WAVE檔案是PCM(Pulse-code modulation,脈沖編碼調變)格式的,這種格式直接存儲取樣的聲音資料沒有經過任何的壓縮,是音效卡直接支援的資料格式,要讓音效卡正確播放其他被壓縮的聲音資料,就應該先把壓縮的資料解壓縮成PCM格式,然後再讓音效卡來播放。
所謂的PCM是一種未經壓縮的編碼格式,每個取樣的樣本為在取樣當時的振幅大小(Amplitude),而PCM又可分為Linear PCM(LPCM)與Non-linear PCM兩種。所謂的LPCM指的是當使用 PCM 格式編碼記錄時,每一個取樣位階的間隔大小都是固定的;如果把每一個取樣位階的間隔大小改成對數形式,低電位時取樣位階比較密集,高電位時取樣位階比較稀疏,這樣如果取樣的對象大部分時間都是低電位訊號,我們就可以得到比較好的紀錄品質。這種記錄方式就稱為 Non-linear PCM。所以當我們只說 PCM 的時候,它可能是 LPCM,也可能是 Non-Linear PCM,沒有很明確的指定是哪一種形式,而 DVD 上則只能用 LPCM 音軌,所以它會很明確的把 LPCM 的 "L" 標明上去。
PCM 是一種編碼格式,而WAVE則是一種檔案格式,WAVE裡面可以放LPCM編碼記錄後儲存的資料。WAVE開頭有WAVE檔案格式規定的檔頭,裡面會說明後面存放的是哪一種編碼的資料,有幾聲道,取樣頻率和位元大小等等基本資料,供處理的程式作識別。
我們也可以不需要用WAVE的檔案格式來記錄儲存PCM,把PCM 記錄下來的數位資料直接存成一個檔案,我們稱這種資料叫做RAW PCM,副檔名可以是 .raw 或 .pcm。這種檔案由於沒有檔頭,檔案一開始就是資料的"內容",所以處理程式完全無法知道它有幾聲道,取樣頻率和位元大小,不知道這些就無法正確的分段,讀取正確的資料內容。所以在開啟這類檔案時,程式都會要求你先告訴它以上這些基本資料,然後它才能開始處理。
PCM中的聲音資料沒有被壓縮,取樣按時間的先後順序依次存入(它的基本組織單位是BYTE(8bit)或WORD(16bit))取樣資料按時間先後順序交叉地存入
如下表八所示:
表八、PCM資料的存放方式
樣本一 | 樣本二 | |||
8bit單聲道 | 0聲道 | 0聲道 | ||
16bit單聲道 | 0聲道(左) | 1聲道(右) | 0聲道(左) | 1聲道(右) |
8bit立體聲 | 0聲道低位元組 | 0聲道高位元組 | 0聲道低位元組 | 0聲道高位元組 |
16bit立體聲 | 0聲道(左)低位元組 | 0聲道(左)高位元組 | 1聲道(右)低位元組 | 1聲道(右)高位元組 |
WAVE檔案的每個樣本值包含在一個整數i中,i的大小為容納指定樣本大小所需的最小位元組數。首先存儲低有效位元組,表示樣本幅度的位元放在i的高有效位元上,剩下的位置為0,PCM格式之8位元和16位元的波形樣本與檔頭如下表七、表八所示:
表九、8位元和16位元的PCM波形樣本的資料格式
樣本大小 | 資料格式 | 最大值 | 最小值 |
8位元PCM | unsigned int | 225 | 0 |
16位元PCM | Int | 32767 | -32767 |
表十、PCM格式的WAVE檔案的檔頭
Chunk name | offset | size | Field name | Type | Description |
RIFF Chunk | 0 | 4 | ChunkID | Char | 存放"RIFF" (0x52494646)4個字元 |
4 | 4 | ChunkSize | Long int | (file size)–8 | |
8 | 4 | Format | Char | 存放"WAVE"(0x57415645)4個字元,告之此檔為WAVE格式 | |
Format Chunk | 12 | 4 | Subchunk1ID | Char | "fmt " (0x666D7420) |
16 | 4 | Subchunk1Size | Lont int | 結構PCMWAVEFORMAT的大小,值為16 | |
20 | 2 | AudioFormat | Short int | 編碼格式(1為PCM格式) | |
22 | 2 | NumChannels | Short int | 聲道頻道數(mono=1,Stereo=2) | |
24 | 4 | SampleRate | Long int | 每秒取樣數 | |
28 | 4 | ByteRate | Long int | 每秒資料量 | |
32 | 2 | BlockAlign | Short int | 每次讀取的區塊大小 | |
34 | 2 | BitsPerSample | Short int | 每個取樣的大小 | |
Data Chunk | 36 | 4 | Subchunk2ID | Char | “data” (0x64617461) |
40 | 4 | Subchunk2Size | Long int | 扣除掉WAVE檔頭大小(44Bytes)的聲音資料真正大小 | |
44 | ~end | Data | 聲音資料存放處 |
n IMA-ADPCM:
ADPCM (Adaptive Differential Pulse Code Modulation,可適性差分脈衝編碼調變),使用一個差異化訊號(difference signal)。不將整個樣本加以編碼,ADPCM可以將目前樣本與前一個樣本比較出來的差異傳送出去。由於編碼方式只採取相鄰兩樣本之間差別作紀錄,ADPCM 所需的位元比 (Bit Rate) 較標準PCM為低,就是說ADPCM儲存同一聲音所需的空間比較小。
IMA-ADPCM為Intel公司首先開發,是一種針對16bit (或者更高) 聲音波形資料的一種有損壓縮演算法,它將聲音流中每次取樣的 16bit 資料以 4bit 儲存,所以壓縮比 1:4。而壓縮/解壓縮演算法非常的簡單,所以是一種低空間消耗,高質量聲音獲得的好途徑。它是從PCM的16位元的取樣壓縮成4位元的,對於單聲道的IMA-ADPCM來說,它是將PCM的資料按時間順序依次壓縮並寫入檔案中,每個byte中含兩個取樣,低4位元對應第一個取樣,高4位元對應第二個取樣。而對於雙聲道的IMA-ADPCM來說,它的儲存相對就麻煩一些了,它是將PCM的左聲道的前8個取樣依次壓縮並寫入到一個DWORD中,然後寫入Data Chunk裡。再來是右聲道的前8個取樣。以此循環,當取樣數不足8時(到資料尾端),應該把多出來的取樣用0填充。
IMAADPCMWAVEFORMAT結構定義如下:
Typedef struct
{ WAVEFORMATEX wfmt;
WORD nSamplesPerBlock;
}IMAADPCMWAVEFORMAT;
IMA-ADPCM的wfmt->cbsize不能忽略,一般取值為2,表示此類型的WAVEFORMAT比一般的WAVEFORMAT多出2個位元組,這兩個字元也就是nSamplesPerBlock。
PCM與非PCM主要的差異是聲音資料組織不同,在非PCM格式的檔案中其檔頭至少會加入一個Fact Chunk,這個Chunk是用來記錄資料解壓縮後的大小,這裡說的資料是指聲音資料而非檔案,這個Fact Chunk通常是放在Data Chunk前面。
留言
張貼留言