Android 在内部使用多种音频数据格式,并在公共 API、文件格式和硬件抽象层 (HAL) 中公布了其中的一部分。
属性
音频数据格式按其属性进行分类:
- 压缩
- 未压缩、无损压缩或有损压缩。PCM 是最常见的未压缩音频格式。FLAC 是一种无损压缩格式,而 MP3 和 AAC 是有损压缩格式。
- 位深
- 每个音频样本的有效位数量。
- 容器大小
- 用于存储或传输样本的位数。通常与位深相同,但是有时会为了对齐而分配额外的填充位。例如,一个 24 位样本可以包含在一个 32 位字中。
- 对齐方式
- 如果容器大小与位深完全相同,该表示法被称为“打包”。否则,表示法为“解包”。样本的有效位通常与容器的最左(最高有效)或最右(最低有效)位对齐。通常只有当位深不是 2 的幂时,才使用术语“打包”和“解包”。
- 符号性
- 样本是有符号,还是无符号。
- 表示法
- 定点数或浮点数(见下文)。
定点数表示法
定点数是未压缩 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 | |
余量 (以 dB 为单位) |
0 | 0 | 0 | 0 | 126 4 | |
动态范围 (以 dB 为单位) |
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。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
- 当 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 位或更少有效位的定点数表示法转换到浮点数是无损的。从浮点数转换到任何常见的定点数表示法则是有损的。