.WAV文件,PCM數據
1. 音頻簡介
經常見到這樣的描述: 44100HZ 16bit stereo 或者 22050HZ 8bit mono 等等.44100HZ 16bit stereo: 每秒鐘有 44100 次採樣, 採樣數據用 16 位(2字節)記錄, 雙聲道(立體聲);22050HZ 8bit mono: 每秒鐘有 22050 次採樣, 採樣數據用 8 位(1字節)記錄, 單聲道;
當然也可以有 16bit 的單聲道或 8bit 的立體聲, 等等。
採樣率是指:聲音信號在“模→數”轉換過程中單位時間內採樣的次數。採樣值是指每一次採樣週期內聲音模擬信號的積分值。
對於單聲道聲音文件,採樣數據爲八位的短整數(short int 00H-FFH);
而對於雙聲道立體聲聲音文件,每次採樣數據爲一個16位的整數(int),高八位(左聲道)和低八位(右聲道)分別代表兩個聲道。
人對頻率的識別範圍是 20HZ - 20000HZ, 如果每秒鐘能對聲音做 20000 個採樣, 回放時就足可以滿足人耳的需求. 所以 22050 的採樣頻率是常用的, 44100已是CD音質, 超過48000的採樣對人耳已經沒有意義。這和電影的每秒 24 幀圖片的道理差不多。
每個採樣數據記錄的是振幅, 採樣精度取決於儲存空間的大小:
1 字節(也就是8bit) 只能記錄 256 個數, 也就是隻能將振幅劃分成 256 個等級;
2 字節(也就是16bit) 可以細到 65536 個數, 這已是 CD 標準了;
4 字節(也就是32bit) 能把振幅細分到 4294967296 個等級, 實在是沒必要了.
如果是雙聲道(stereo), 採樣就是雙份的, 文件也差不多要大一倍.
這樣我們就可以根據一個 wav 文件的大小、採樣頻率和採樣大小估算出一個 wav 文件的播放長度。
譬如 "Windows XP 啓動.wav" 的文件長度是 424,644 字節, 它是 "22050HZ / 16bit / 立體聲" 格式(這可以從其 "屬性->摘要" 裏看到),
那麼它的每秒的傳輸速率(位速, 也叫比特率、取樣率)是 22050*16*2 = 705600(bit/s), 換算成字節單位就是 705600/8 = 88200(字節/秒),
播放時間:424644(總字節數) / 88200(每秒字節數) ≈ 4.8145578(秒)。
但是這還不夠精確, 包裝標準的 PCM 格式的 WAVE 文件(*.wav)中至少帶有 42 個字節的頭信息, 在計算播放時間時應該將其去掉,
所以就有:(424644-42) / (22050*16*2/8) ≈ 4.8140816(秒). 這樣就比較精確了.
關於聲音文件還有一個概念: "位速", 也有叫做比特率、取樣率, 譬如上面文件的位速是 705.6kbps 或 705600bps, 其中的 b 是 bit, ps 是每秒的意思;
壓縮的音頻文件常常用位速來表示, 譬如達到 CD 音質的 MP3 是: 128kbps / 44100HZ.
2. wave文件格式
2.1 概述
WAVE文件是計算機領域最常用的數字化聲音文件格式之一,它是微軟專門爲Windows系統定義的波形文件格式(Waveform Audio),由於其擴展名爲"*.wav"。
WAVE是錄音時用的標準的WINDOWS文件格式,文件的擴展名爲“WAV”,數據本身的格式爲PCM或壓縮型。
WAV文件格式是一種由微軟和IBM聯合開發的用於音頻數字存儲的標準,它採用RIFF文件格式結構,非常接近於AIFF和IFF格式。符合 PIFF Resource Interchange File Format規範。所有的WAV都有一個文件頭,這個文件頭音頻流的編碼參數。
WAV對音頻流的編碼沒有硬性規定,除了PCM之外,還有幾乎所有支持ACM規範的編碼都可以爲WAV的音頻流進行編碼。
多媒體應用中使用了多種數據,包括位圖、音頻數據、視頻數據以及外圍設備控制信息等。RIFF爲存儲這些類型的數據提供了一種方法,RIFF文件所包含的數據類型由該文件的擴展名來標識,能以RIFF文件存儲的數據包括:
音頻視頻交錯格式數據(.AVI) 、波形格式數據(.WAV) 、位圖格式數據(.RDI) 、MIDI格式數據(.RMI) 、調色板格式(.PAL) 、多媒體電影(.RMN) 、動畫光標(.ANI) 、其它RIFF文件(.BND)。
wave文件有很多不同的壓縮格式,所以,正確而詳細地瞭解各種WAVE文件的內部結構是成功完成壓縮和解壓縮的基礎,也是生成特有音頻壓縮格式文件的前提。
最基本的WAVE文件是PCM(脈衝編碼調製)格式的,這種文件直接存儲採樣的聲音數據沒有經過任何的壓縮,是聲卡直接支持的數據格式,要讓聲卡正確播放其它被壓縮的聲音數據,就應該先把壓縮的數據解壓縮成PCM格式,然後再讓聲卡來播放。
2.2 Wave文件的內部結構
注:由於WAV格式源自Windows/Intel環境,因而採用Little-Endian字節順序進行存儲。
WAVE文件是以RIFF(Resource Interchange File Format, "資源交互文件格式")格式來組織內部結構的。
RIFF文件結構可以看作是樹狀結構,其基本構成是稱爲"塊"(Chunk)的單元,最頂端是一個“RIFF”塊,下面的每個塊有“類型塊標識(可選)”、“標誌符”、“數據大小”及“數據”等項所組成。塊的結構如表1所示:
名稱 |
Size |
備註 |
塊標誌符 |
4 |
4個小寫字符(如 "fmt ", "fact", "data" 等) |
數據大小 |
4 |
DWORD類型,表示後接數據的大小(N Bytes) |
數據 |
N |
本塊中正式數據部分 |
表1:基本chunk的內部結構
上面說到的“類型塊標識”只在部分chunk中用到,如 "WAVE" chunk中,這時表示下面嵌套有別的chunk。
當使用了 "類型塊標識" 時,該chunk就沒有別的項(如塊標誌符,數據大小等),它只作爲文件讀取時的一個標識。先找到這個“類型塊標識”,再以它爲起點讀取它下面嵌套的其它chunk。
每個文件最前端寫入的是RIFF塊,每個文件只有一個RIFF塊。從 Wave文件格式詳細說明 中可以看到這一點。
非PCM格式的文件會至少多加入一個 "fact" 塊,它用來記錄數據(注意是數據而不是文件)解壓縮後的大小。這個 "fact" 塊一般加在 "data" 塊的前面。
WAVE文件是由若干個Chunk組成的。按照在文件中的出現位置包括:RIFF WAVE Chunk, Format Chunk, Fact Chunk(可選), Data Chunk。具體見下圖:
-------------------------------------------
| RIFF WAVE Chunk |
| ID = "RIFF" |
| RiffType = "WAVE" |
-------------------------------------------
| Format Chunk |
| ID = "fmt " |
-------------------------------------------
| Fact Chunk(optional) |
| ID = "fact" |
-------------------------------------------
| Data Chunk |
| ID = "data" |
-------------------------------------------
圖 Wav格式包含Chunk示例
Fact Chunk
=======================================
| |所佔字節數| 具體內容 |
=======================================
| ID | 4Bytes | "fact" |
---------------------------------------
| Size | 4Bytes | 4 |
---------------------------------------
| data | 4Bytes |解壓後的音頻數據的大小(B)|
---------------------------------------
圖 Fact Chunk
2.3 Wave文件格式詳細說明
別名 字節數 類型 註釋
ckid 4 char "RIFF" 標誌, 大寫
cksize 4 int32 文件長度。這個長度不包括"RIFF"標誌 和文件長度 本身所佔字節, 下面的子塊大小也是這樣。
fcc type 4 char "WAVE" 類型塊標識, 大寫。
ckid 4 char 表示"fmt" chunk的開始。此塊中包括文件內部格式信息。小寫, 最後一個字符是空格。
cksize 4 int32 文件內部格式信息數據的大小。
FormatTag 2 int16 音頻數據的編碼方式。1 表示是 PCM 編碼
Channels 2 int16 聲道數,單聲道爲1,雙聲道爲2
SamplesPerSec 4 int32 採樣率(每秒樣本數), 比如 44100 等
BytesPerSec 4 int32 音頻數據傳送速率, 單位是字節。其值爲採樣率×每次採樣大小。播放軟件利用此值可以估計緩衝區的大小。
BlockAlign 2 int16 每次採樣的大小 = 採樣精度*聲道數/8(單位是字節); 這也是字節對齊的最小單位, 譬如 16bit 立體聲在這裏的值是 4 字節。播放軟件需要 一次處理多個該值大小的字節數據,以便將其值用於緩衝區的調整。
BitsPerSample 2 int16 每個聲道的採樣精度; 譬如 16bit 在這裏的值就是16。如果有多個聲道,則每個聲道的採樣精度大小都一樣的。
[cbsize] 2 int16 [可選]附加數據的大小。
[...] x
[ckid] 4 char "fact".
[cksize] 4 int32 "fact" chunk data size.
[fact data] 4 int32 解壓後的音頻數據的大小(Bytes).
ckid 4 char 表示 "data" chunk的開始。此塊中包含音頻數據。小寫。
cksize 4 int32 音頻數據的長度
...... 文件聲音信息數據(真正聲音存儲部分)
[......] 其它 chunk
2. 將.WAV文件轉換成 .C文件裏的數組存放
1、使用winhex軟件工具打開目標文件。File->Open
2、打開後頁面如下所示:
3、選中要選擇的第一個數據,點擊右鍵,選擇——選塊開始(alt+1)
4.選中要選擇的最後一個數據,點擊右鍵,選擇——選塊結束(alt+2)
5.左鍵點擊編輯->全部複製-->C源碼(此時已把C數組文件粘貼到了剪貼板)
6.將文本複製到一個文件,文本會以數組形式展現。