wav檔案詳解
- WAV頭分析
WAV是微軟公司(Microsoft)開發的一種聲音檔案格式,在多媒體中使用的聲波檔案格式之一,它是以RIFF(Resource Interchange File Format 資源互動檔案格式) 格式為标準的。每個WAV檔案的頭四個位元組就是“RIFF”。WAV檔案由檔案頭和資料體兩大部分組成。其中檔案頭又分為RIFF/WAV檔案辨別段和聲音資料格式說明段兩部分,檔案頭中還包含了音頻流的編碼參數。
如下圖所示
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIwczX0xiRGZkRGZ0Xy9GbvNGL2EzXlpXazxSPJpWT0EEVlJnTuNGbS1mYoR2MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL5EzM0QzN1UTM3ATMwEjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
//wav頭
typedef __packed struct
{
ChunkRIFF riff; //riff塊
ChunkFMT fmt; //fmt塊
ChunkFACT fact; //fact塊 線性PCM,沒有這個結構體
ChunkDATA data; //data塊
}__WaveHeader;
WAV檔案頭包含三部分,RIFF,fmt,fact,資料存儲大小端定義按上圖中的定義,規律大概是這樣的,如果是字元串常量,則按閱讀習慣,采用大端存儲模式,如果是十六進制資料的純資料,則按一般處理器處理規律小端模式存儲。
WAV檔案是非常簡單的一種RIFF檔案,它的格式類型為“WAVE ”。RIFF塊包含兩個子塊,這兩個子塊的ID分别是“fmt ”和“data ” 。其中“fmt ”子塊由結構PCMWAVEFORMAT所組成,其子塊的大小就是sizeof(PCMWAVEFORMAT),資料組成就是PCMWAVEFORMAT結構中的資料。
-
- RIFF結構如下,定義,
typedef __packed struct
{
u32 ChunkID; //chunk id;這裡固定為"RIFF",即0X46464952
u32 ChunkSize ; //集合大小;檔案總大小-8
u32 Format; //格式;WAVE,即0X45564157
}ChunkRIFF ;
-
- fmt結構
//fmt塊
typedef __packed struct
{
u32 ChunkID; //chunk id;這裡固定為"fmt ",即0X20746D66
u32 ChunkSize ; //子集合大小(不包括ID和Size);這裡為:20.
u16 AudioFormat; //音頻格式;0X01,表示線性PCM;0X11表示IMA ADPCM
u16 NumOfChannels; //通道數量;1,表示單聲道;2,表示雙聲道;
u32 SampleRate; //采樣率;0X1F40,表示8Khz
u32 ByteRate; //位元組速率;
u16 BlockAlign; //塊對齊(位元組);
u16 BitsPerSample; //單個采樣資料大小;4位ADPCM,設定為4
u16 ByteExtraData; //附加的資料位元組;2個; 線性PCM,沒有這個參數
u16 sampleperblock; //一般是一個資料塊中的采樣數量 如:0x01F9
}ChunkFMT;
ByteExtraData這個資料重點說一下,在原始線性PCM編碼格式,不需要這個參數,隻有壓縮的PCM編碼格式,一般都是按塊存儲的,需要知道一個塊内的采樣數量。
-
- fact結構
//fact塊
typedef __packed struct
{
u32 ChunkID; //chunk id;這裡固定為"fact",即0X74636166;
u32 ChunkSize ; //子集合大小(不包括ID和Size);這裡為:4.
u32 NumOfSamples; //采樣的數量;
}ChunkFACT;
“All (compressed) non-PCM formats must have a Fact chunk (Rev. 3documentation). The chunk contains at least one value, the number of samples in the file.”
雖然标準協定要求”所有非PCM編碼的WAV檔案要求有fact塊”,但實際分析了兩個wav檔案的檔案頭,一種PCM編碼,一種IMA-ADPCM編碼,這兩個檔案都沒有fact塊,但是window可以正常播放;說明fact塊對這兩種類型的wav檔案也不是必須的。
- 音頻資料
- data結構
//data塊
typedef __packed struct
{
u32 ChunkID; //chunk id;這裡固定為"data",即0X5453494C
u32 ChunkSize ; // 音頻資料塊大小。(除去WAV頭的所有資料)
}ChunkDATA;
-
- 資料塊BLOCK結構
IMA-ADPCM壓縮的音頻資料是以資料塊存儲的,存儲格式如下:
//ADPCM壓縮的資料塊結構
typedef __packed struct
{
u16 presample; //第一個采樣值16bit
u8 index ; //上一個資料塊的最後一個 index
u8 rsv; //保留
u8 dat[sampleperblock-1];
}DATA_BLOCK;
為了資料存儲對齊,友善處理,一般一個音頻BLOCK的大小是16的整數倍;如果設定BLOCK大小為256Byte,減去資料塊頭長度4位元組,還剩252位元組,4bit表示一個采樣的話,可存儲共252x2+1=505個采樣點(加上資料頭裡的一個采樣值)。
對于PCM編碼的WAV檔案,隻需要按照順序存儲原始采樣值即可,不需要分塊。
PCM編碼的WAV檔案實際例子:
IMA-ADPCM編碼的WAV檔案實際例子:
- ADPCM編解碼
Windows自帶的一個小工具
這個小工具我試過了,轉換成不是ima-adpcm格式, 而是轉換成microsoft adpcm格式,這2種格式之間有什麼差別 我不知道 ,但是市面上大多數是ima-adpcm格式,是以我就不研究這個microsoft adpcm格式了。
相容性問題:
1, cooledit生成的IMA ADPCM 編譯的WAV檔案, foobar.exe不能播放,
2. 錄音筆錄制的 ADPCM WAV就可以播放,
對比發現, cooledit生成的wav檔案好像更符合标準,有fact部分,而錄音筆錄音的wav沒有fact部分,标準規定如果是壓縮的wav格式的話,要求有fact部分,但實際是有這部分播放器就不識别,放不出來,而沒有這部分,大多數播放器就可以很好的播放。 或許是cooledit相容性不好。