Android 會在內部使用各種音訊資料格式,並在公開 API、檔案格式和硬體抽象層 (HAL) 中公開其中的子集。
屬性
音訊資料格式會依據屬性分類:
- 壓縮
- 未壓縮、無損壓縮或有損壓縮。PCM 是最常見的未經壓縮音訊格式。FLAC 是無損壓縮格式,而 MP3 和 AAC 則是損失式壓縮格式。
- 位元深度
- 每個音訊樣本的有效位元數。
- 容器大小
- 用於儲存或傳輸樣本的比特數。通常這會與位元深度相同,但有時會為對齊而分配額外的填充位元。舉例來說,24 位元樣本可包含在 32 位元字詞中。
- 對齊方式
- 如果容器大小與位元深度完全相同,表示法就稱為「packed」。否則,系統會解壓縮該表示法。樣本的重要位元通常會與容器中最左 (最重大) 或最右 (最不重大) 的位元對齊。一般而言,只有在位元深度不是二的冪數時,才會使用「packed」和「unpacked」這類術語。
- Signedness
- 樣本是否已簽署。
- 表示法
- 固定點或浮點;請參閱下文。
固定小數表示法
固定小數是未壓縮 PCM 音訊資料最常見的表示法,尤其是在硬體介面中。
固定小數點數在小數點前後有固定 (常數) 位數。我們所有的表示法都使用基數 2,因此我們將「位元」替換為「數位」,並將「二進位小數點」或簡稱「小數點」替換為「基數小數點」。小數點左側的位元為整數部分,右側的位元為小數部分。
我們會提到「整數 PCM」,因為固定小數值通常會以整數值儲存及處理。解讀為固定點的做法是隱含的。
我們會使用二進位補數來表示所有帶符號的固定小數表示法,因此在所有值皆以 LSB 為單位的情況下,下列情況會成立:
|largest negative value| = |largest positive value| + 1
Q 和 U 標記法
整數中的固定小數表示法有各種符號。我們使用Q 符號:Qm.n,其中 m 代表整數位元,n 代表小數位元。雖然「Q」的值是以兩個互補形式表示,但仍會計為一個位元。位元總數為 m + n + 1。
Um.n 適用於無符號數字:m 整數位元和 n 小數位元,且「U」計為零位元。位元總數為 m + n。
整數部分可能會用於最終結果,也可能只是暫時性。在後一種情況下,組成整數部分的位元稱為保護位元。只要最終值在範圍內,或可壓縮至範圍內,防護位元就會允許中間計算值溢位。請注意,固定小數值保護位元位於左側,而浮點單位保護位元位於右側,用於減少捨入誤差。
浮點表示法
浮點是固定點的替代方案,其中點的位置可能會有所不同。浮點的主要優點包括:
以往,浮點算術運算的速度比整數或固定點算術運算慢,但現在浮點運算通常會比較快,前提是控制流程決策不是根據運算值。
Android 音訊格式
下表列出主要的 Android 音訊格式:
資源 | Q0.15 | Q0.7 1 | Q0.23 | Q0.31 | float | |
---|---|---|---|---|---|---|
容器 位 |
16 | 8 | 24 或 32 2 | 32 | 32 | |
有效位元 (包括符號) |
16 | 8 | 24 | 24 或 32 2 | 25 3 | |
裕度 (以分貝為單位) |
0 | 0 | 0 | 0 | 126 4 | |
動態範圍 (以分貝為單位) |
90 | 42 | 138 | 138 到 186 | 900 5 |
上述所有固定小數格式的額定範圍為 -1.0 到 +1.0,減去一個 LSB。由於採用二元補碼表示法,負值比正值多一個。
註腳:
-
上述所有格式都會顯示帶符號的取樣值。8 位元格式通常稱為「未簽署」,但實際上是偏差為
0.10000000
的已簽署值。 - Q0.23 可壓縮為 24 位元 (三個 8 位元位元組,由小至大),或解壓縮為 32 位元。如果解包,則有效位元會向右對齊 LSB,並以正負號擴充填充方式向 MSB 延伸 (Q8.23),或是向左對齊 MSB,並以零填充方式向 LSB 延伸 (Q0.31)。理論上,Q0.31 最多可允許 32 個有效位元,但接受 Q0.31 的硬體介面很少使用所有位元。
- 單精度浮點數有 23 個明確位元,加上一個隱藏位元和符號位元,總共 25 個有效位元。非正規數的有效位元較少。
- 單精度浮點值可表示的值上限為 ±1.7e+38,這就是為何有這麼大的空間。
- 所顯示的動態範圍是指非正常值,最高可達額定最大值 ±1.0。請注意,某些架構特定浮點實作 (例如 NEON) 不支援非正常值。
轉換次數
本節將討論不同表示法之間的資料轉換。
浮點轉換
如要將值從 Qm.n 格式轉換為浮點格式:
- 將值轉換為浮點值,就如同它是整數一樣 (忽略小數點)。
- 乘以 2-n。
舉例來說,如要將 Q4.27 內部值轉換為浮點值,請使用:
float = integer * (2 ^ -27)
從浮點轉換為固定點時,請遵循下列規則:
- 單精度浮點值的額定範圍為 ±1.0,但中間值的完整範圍為 ±1.7e+38。浮點和固定點之間的轉換作業 (用於外部表示法,例如輸出至音訊裝置) 只會考量名義範圍,並對超出該範圍的值進行固定。特別是,當 +1.0 轉換為固定小數格式時,會將其限制為 +1.0 減去一個 LSB。
- 在表示法中允許使用非正常值 (子正常值) 和 +/- 0.0,但在處理期間可能會悄悄轉換為 0.0。
- 無窮大值會傳遞至運算,或會在未經使用者同意的情況下,硬限制為 +/- 1.0。一般來說,後者是用於轉換為固定小數格式。
- NaN 行為未定義:NaN 可能會以相同的 NaN 傳播,或可能會轉換為預設 NaN,可能會在無聲音的情況下限制為 +/- 1.0,或在無聲音的情況下轉換為 0.0,或導致錯誤。
固定點轉換
不同 Qm.n 格式之間的轉換會遵循以下規則:
- 當 m 增加時,請將左側的整數部分延伸為符號。
- 當 m 減少時,請夾住整數部分。
- 當 n 增加時,零會在右側擴展小數部分。
- 當 n 減少時,請對右側多餘的部分小數位元進行抖動、捨入或截斷。
舉例來說,如要將 Q4.27 值轉換為 Q0.15 (不經過抖動或捨入),請將 Q4.27 值向右移 12 位元,並夾住超出 16 位元有號範圍的任何結果。這會對齊 Q 表示法的點。
如要將 Q7.24 轉換為 Q7.23,請將帶正負號的除法運算結果除以 2,或將帶正負號的位元加到 Q7.24 整數量,然後將帶正負號的右移運算結果右移 1 位元。請注意,簡單的帶符號右移運算並不等同於帶符號除以 2。
有損和無損轉換
如果轉換可反向轉換,則為無損轉換:從 A
轉換至 B
再轉換至 C
的結果為 A = C
。否則轉換會損失品質。
無損轉換可允許來回格式轉換。
從固定小數表示法 (有效位數 25 位元以下) 轉換為浮點值,不會造成資料損失。從浮點轉換為任何常見的固定點表示法都會造成資料損失。