Android 内部使用各种音频数据格式,并在公共 API、文件格式和硬件抽象层 (HAL) 中公开了这些格式的子集。
属性
音频数据格式按其属性分类
- 压缩
- 未压缩、无损压缩或有损压缩。PCM 是最常见的未压缩音频格式。FLAC 是一种无损压缩格式,而 MP3 和 AAC 是有损压缩格式。
- 位深度
- 每个音频样本的有效位数。
- 容器大小
- 用于存储或传输样本的位数。通常,这与位深度相同,但有时会分配额外的填充位以进行对齐。例如,一个 24 位样本可以包含在 32 位字中。
- 对齐
- 如果容器大小与位深度完全相等,则表示形式称为packed(紧凑型)。否则,表示形式为unpacked(非紧凑型)。样本的有效位通常与容器的最左侧(最高有效位)或最右侧(最低有效位)位对齐。仅当位深度不是2 的幂时,才习惯使用术语packed和unpacked。
- 有符号性
- 样本是有符号还是无符号。
- 表示形式
- 定点或浮点;请参见下文。
定点表示
定点是未压缩 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 个或更少有效位的定点表示形式到浮点数的转换是无损的。从浮点数到任何常见的定点表示形式的转换都是有损的。