1. 程式人生 > 程式設計 >詳解RIFF和WAVE音訊檔案格式

詳解RIFF和WAVE音訊檔案格式

RIFF file format

RIFF全稱為資源互換檔案格式(Resources Interchange File Format),是Windows下大部分多媒體檔案遵循的一種檔案結構。RIFF檔案所包含的資料型別由該檔案的副檔名來標識,能以Rhttp://www.cppcns.comIFF格式儲存的資料有:

  • 音訊視訊交錯格式資料 .AVI
  • 波形格式資料 .WAV
  • 點陣圖資料格式 .RDI
  • MIDI格式資料 .RMI
  • 調色盤格式 .PAL
  • 多媒體電影 .RMN
  • 動畫游標 .ANI
  • 其他的RIFF檔案 .BND

CHUNK

chunk是RIFF檔案的基本單元,其基本結構如下:

struct chunk
{
	uint32_t id;   // 塊標誌
	uint32_t size; // 塊大小
	uint8_t data[size]; // 塊資料
};
  • id 4位元組,用以標識塊中所包含的資料。如:RIFF,LIST,fmt,data,WAV,AVI等,由於這種檔案結構 最初是由Microsoft和IBM為PC機所定義,RIFF檔案是按照小端 little-endian位元組順序寫入的。
  • size 塊大小 儲存在data域中的資料長度,不包含id和size的大小
  • data 包含資料,資料以字為單位存放,如果資料長度為奇http://www.cppcns.com數(位元組為單位),則最後新增一個空位元組。

chunk是可以巢狀的,但是隻有塊標誌為RIFF或者LIST的chunk才能包含其他的chunk。

RIFF chunk

標誌為RIFF的chunk是比較特殊的,每一個RIFF檔案首先存放的必須是一個RIFF chunk,並且只能有這一個標誌為RIFF的chunk。RIFF的資料域的起始位置是一個4位元組碼(FOURCC),用於標識其資料域中chunk的資料型別;緊接著資料域的內容則是包含的subchunk,如下圖

詳解RIFF和WAVE音訊檔案格式

這是一個RIFF chunk中包含有兩個subchunk,可以看出RIFF chunk的資料域首先是是4位元組的 Form Type,接著是兩個subchunk,每一個subchun有包含有自己的標識、資料域的大小以及資料域。
除了RIFhttp://www.cppcns.comF cunk可以巢狀其他的chunk外,另一個可以有subchunk的就是LIST chunk。

詳解RIFF和WAVE音訊檔案格式

上圖中,首先是RIFF檔案必須的RIFF chunk,其資料域又包含有兩個subchunk,其中一個subchunk的型別為LIST,該LIST chunk又包含了兩個subchunk。

FourCC

FourCC 全稱為Four-Character Codes,是一個4位元組32位的識別符號,通常用來標識檔案的資料格式。例如,在音視訊播放器中,可以通過 檔案的FourCC來決定呼叫那種CODEC進行視音訊的解碼。例如:DIV3,DIV4,DIVX,H264等,對於音訊則有:WAV,MP3等。對於上面的RIFF檔案,則有:RIFF,WAVE,data等。FourCC是4個ASCII字元,不足四個字元的則在最後補充空格(不是空字元)。比如,FourCC fmt,實際上是'f' 'm' 't' ' '。

FourCC的生成通常可以使用如下巨集:

#define MAKE_FOURCC(a,b,c,d) \
( ((uint32_t)d) | ( ((uint32_t)c) << 8 ) | ( ((uint32_t)b) << 16 ) | ( ((uint32_t)a) << 24 ) )

在程式 中還是不要使用太長的巨集為好,在C++中可以使用模板和enum結合的方式。來保證在編譯時期就能夠將FourCC生成出來。

#dewww.cppcns.comfine FOURCC uint32_t	
template <char ch0,char ch1,char ch2,char ch3> struct MakeFOURCC{ enum { value = (ch0 << 0) + (ch1 << 8) + (ch2 << 16) + (ch3 << 24) }; };
FOURCC fourcc_fmt = MakeFOURCC<'f','m','t',' '>::value;

將字元常量傳入模板,在結構體中宣告一個enum,編譯器會在編譯時期確定列舉值,這樣就能給保證FOURCC在編譯就能生成出來。

WAV file

WAV 是Microsoft開發的一種音訊檔案格式,它符合上面提到的RIFF檔案格式標準,可以看作是RIFF檔案的一個具體例項。既然WAV符合RIFF規範,其基本的組成單元也是chunk。一個WAV檔案通常有三個chunk以及一個可選chunk,其在檔案中的排列方式依次是:RIFF chunk,FormatyfXNJjJ chunk,Fact chunk(附加塊,可選),Data chunk。

詳解RIFF和WAVE音訊檔案格式

一個WAV檔案,首先是一個RIFF chunk;RIFF chunk又包含有Format chunk,Data chunk以及可選的Fact chunk。各個chunk中欄位的意義如下:

  • RIFF chunk
  • id
  • FOURCC 值為'R' 'I' 'F' 'F'
  • size
  • 其data欄位中資料的大小 位元組數
  • data
  • 包含其他的chunk
  • Format chunk
  • id
  • FOURCC 值為 'f' 'm' 't' ' '
  • size
  • 資料欄位包含資料的大小。如無擴充套件塊,則值為16;有擴充套件塊,則值為= 16 + 2位元組擴充套件塊長度 + 擴充套件塊長度或者值為18(只有擴充套件塊的長度為2位元組,值為0)
  • data

存放音訊格式、聲道數、取樣率等資訊
format_tag
2位元組,表示音訊資料的格式。如值為1,表示使用PCM格式。
channels
2位元組,聲道數。值為1則為單聲道,為2則是雙聲道。
samples_per_sec
取樣率,主要有22.05KHz,44.1kHz和48KHz。
bytes_per sec
音訊的位元速率,每秒播放的位元組數。samples_per_sec * channels * bits_per_sample / 8,可以估算出使用緩衝區的大小
block_align
資料塊對齊單位,一次取樣的大小,值為聲道數 * 量化位數 / 8,在播放時需要一次處理多個該值大小的位元組資料。
bits_per_sample
音訊sample的量化位數,有16位,24位和32位等。
cbSize
擴充套件區的長度
擴充套件塊內容
22位元組,具體介紹,後面補充。

  • Fact chunk(option)
  • id
  • FOURCC 值為 'f' 'a' 'c' 't'
  • size
  • 資料域的長度,4(最小值為4)
  • 取樣總數 4位元組
  • Data chunk
  • id

FOURCC 值為'd' 'a' 't' 'a'

  • size

資料域的長度

  • data

具體的音訊資料存放在這裡

採用壓縮編碼的WAV檔案,必須要有Fact chunk,該塊中只有一個數據,為每個聲道的取樣總數。

Format chunk 中的編碼方式

在Format chunk中,除了有音訊的資料的取樣率、聲道等音訊的屬性外,另一個比較主要的欄位就是format_tag,該欄位表示音訊資料是以何種方式編碼存放的。其具體的取值可以為以下:

  • 0x0001

WAVE_FORMAT_PCM,採用PCM格式

  • 0x0003

WAVE_FORMAT_IEEE_FLOAT,存放的值為IEEE float,範圍為[-1.0f,1.0f]

  • 0x0006

WAVE_FORMAT_ALAW,8bit ITU-T G.711 A-law

  • 0x0007

WAVE_FORMAT_MULAW,8bit ITU-T G.711 μ-law

  • 0XFFFE

WAVE_FORMAT_EXTENSIBLE,具體的編碼方式有擴充套件區的 sub_format欄位決定

關於擴充套件格式塊

當WAV檔案使用的不是PCM編碼方式是,就需要擴充套件格式塊,它是在基本的Format chunk又新增一段資料。該資料的前兩個位元組,表示的擴充套件塊的長度。緊接其後的是擴充套件的資料區,含有擴充套件的格式資訊,其具體的長度取決於壓縮編碼的型別。當某種編碼方式(如 ITU G.711 a-law)使擴充套件區的長度為0,擴充套件區的長度欄位還必須保留,只是其值設定為0。
擴充套件區的各個位元組的含義如下:

size 2位元組
擴充套件區的資料長度 ,可以為0或22

  • valid_bits_per_sample 2位元組

有效的取樣位數,最大值為取樣位元組數 * 8。可以使用更靈活的量化位數,通常音訊sample的量化位數為8的倍數,但是使用了WAVE_FORMAT_EXTENSIBLE時,量化的位數有擴充套件區中的valid bits per sample來描述,可以小於Format chunk中制定的bits per sample。

  • channle mask 4位元組

聲道掩碼

  • sub format 16位元組

GUID,include the data format code,資料格式碼。

在Format chunk中的format_tag設定為0xFFFE時,表示使用擴充套件區中的sub_format來決定音訊的資料的編碼方式。在以下幾種情況下必須要使用WAVE_FORMAT_EXTENSIBLE

  • PCM資料的量化位數大於16
  • 音訊的取樣聲道大於2
  • 實際的量化位數不是8的倍數
  • 儲存順序和播放順序不一致,需要指定從聲道順序到音效卡播放順序的對映情況。

Data chunk

Data塊中存放的是音訊的取樣資料。每個sample按照取樣的時間順序寫入,對於使用多個位元組的sample,使用小端模式存放(低位位元組存放在低地址,高位位元組存放在高地址)。對於多聲道的sample採用交叉存放的方式。例如:立體雙聲道的sample儲存順序為:聲道1的第一個sample,聲道2的第一個sample;聲道1的第二個sample,聲道2的第二個sample;依次類推....。對於PCM資料,有以下兩種的儲存方式:

  • 單聲道,量化位數為8,使用偏移二進位制碼
  • 除上面之外的,使用補碼方式儲存。

總結

本文主要介紹了RIFF檔案的格式和WAV音訊檔案格式,為後面實現對WAVE檔案的讀寫打一個理論基礎。後面打算使用C++標準庫,實現對WAV檔案的讀寫。

到此這篇關於RIFF和WAVE音訊檔案格式的文章就介紹到這了,更多相關RIFF和WAVE音訊格式內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!