| <html devsite><head> |
| <title>数据格式</title> |
| <meta name="project_path" value="/_project.yaml"/> |
| <meta name="book_path" value="/_book.yaml"/> |
| </head> |
| <body> |
| <!-- |
| Copyright 2017 The Android Open Source Project |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| |
| <p> |
| Android 在内部使用各种音频<a href="http://en.wikipedia.org/wiki/Data_format">数据格式</a>,并在公共 API、<a href="http://en.wikipedia.org/wiki/Audio_file_format">文件格式</a>和<a href="https://en.wikipedia.org/wiki/Hardware_abstraction">硬件抽象层</a> (HAL) 中公布了其中的一部分。 |
| </p> |
| |
| <h2 id="properties">属性</h2> |
| |
| <p> |
| 音频数据格式是按其属性进行分类: |
| </p> |
| |
| <dl> |
| |
| <dt><a href="https://en.wikipedia.org/wiki/Data_compression">压缩</a></dt> |
| <dd> |
| <a href="http://en.wikipedia.org/wiki/Raw_data">未压缩</a>、<a href="http://en.wikipedia.org/wiki/Lossless_compression">无损压缩</a>或<a href="http://en.wikipedia.org/wiki/Lossy_compression">有损压缩</a>。PCM 是最常见的未压缩音频格式。FLAC 是一种无损压缩格式,而 MP3 和 AAC 是有损压缩格式。 |
| </dd> |
| |
| <dt><a href="http://en.wikipedia.org/wiki/Audio_bit_depth">位元深度</a></dt> |
| <dd> |
| 每个音频样本的有效位数量。 |
| </dd> |
| |
| <dt><a href="https://en.wikipedia.org/wiki/Sizeof">容器大小</a></dt> |
| <dd> |
| 用于存储或传输样本的位数。通常与位元深度相同,但是有时会为了对齐而分配额外的填充位。例如,一个 24 位样本可以包含在一个 32 位字中。 |
| </dd> |
| |
| <dt><a href="http://en.wikipedia.org/wiki/Data_structure_alignment">对齐方式</a></dt> |
| <dd> |
| 如果容器大小与位元深度完全相同,该表示法被称为“打包”。<em></em>否则,表示法为“解包”。<em></em>样本的有效位通常与容器的最左(最高有效)或最右(最低有效)位对齐。<em></em><em></em>通常只有当位元深度不是 <a href="http://en.wikipedia.org/wiki/Power_of_two">2 的幂</a>时,才使用术语“打包”和“解包”。 |
| </dd> |
| |
| <dt><a href="http://en.wikipedia.org/wiki/Signedness">符号</a></dt> |
| <dd> |
| 样本是有符号,还是无符号。 |
| </dd> |
| |
| <dt>表示法</dt> |
| <dd> |
| 定点数或浮点数(见下文)。 |
| </dd> |
| |
| </dl> |
| |
| <h2 id="fixed">定点数表示法</h2> |
| |
| <p> |
| <a href="http://en.wikipedia.org/wiki/Fixed-point_arithmetic">定点数</a>是未压缩 PCM 音频数据的最常见表示法,特别是对于硬件接口。 |
| </p> |
| |
| <p> |
| 定点数在<a href="https://en.wikipedia.org/wiki/Radix_point">小数点</a>前后具有固定(恒定)位数。我们所有的表示法都使用<a href="https://en.wikipedia.org/wiki/Binary_number">基数 2</a>,所以我们用“位”代替“位数”,用“二进制点”或简单的“点”代替“小数点”。<em></em><em><em></em><em></em><em></em></em>点左边的位是整数部分,点右边的位是<a href="https://en.wikipedia.org/wiki/Fractional_part">小数部分</a>。 |
| </p> |
| |
| <p> |
| 我们之所以用“整数 PCM”,是因为定点数值通常作为整数值进行存储和操作。<em></em>作为定点数的解释是隐含的。 |
| </p> |
| |
| <p> |
| 我们对所有有符号的定点数表示法使用<a href="https://en.wikipedia.org/wiki/Two%27s_complement">二进制补码</a>,因此下列表达式的值可使用一个 <a href="https://en.wikipedia.org/wiki/Least_significant_bit">LSB</a> 来实现: |
| </p> |
| <pre class="devsite-click-to-copy"> |
| |largest negative value| = |largest positive value| + 1 |
| </pre> |
| |
| <h3 id="q">Q 和 U 标记</h3> |
| |
| <p> |
| 有各种<a href="https://en.wikipedia.org/wiki/Fixed-point_arithmetic#Notation">标记</a>用于整数中的定点数表示法。我们使用 <a href="https://en.wikipedia.org/wiki/Q_(number_format)">Q 标记</a>:Qm.n 表示 m 个整数位,n 个小数位。<em></em><em></em><em></em><em></em>“Q”计为一位,尽管值以二进制补码表示。总位数为 m + n + 1。<em></em><em></em> |
| </p> |
| |
| <p> |
| Um.n 用于无符号数:m 个整数位和 n 个小数位,并且“U”计为零位。<em></em><em></em><em></em><em></em>总位数为 m + n。<em></em><em></em> |
| </p> |
| |
| <p> |
| 整数部分可以在最终结果中使用,也可以临时使用。在后一种情况下,构成整数部分的位称为“保护位”。<em></em>保护位允许中间计算溢出,只要最终值在范围内,或者可以限制到范围内。请注意,定点数保护位位于左侧,而用于减少舍入误差的浮点数单元<a href="https://en.wikipedia.org/wiki/Guard_digit">保护位</a>位于右侧。 |
| </p> |
| |
| <h2 id="floating">浮点数表示法</h2> |
| |
| <p> |
| <a href="https://en.wikipedia.org/wiki/Floating_point">浮点数</a>是定点数的替代,其中点的位置可以变化。浮点数的主要优点包括:</p> |
| |
| <ul> |
| <li>更大的<a href="https://en.wikipedia.org/wiki/Headroom_(audio_signal_processing)">余量</a>和<a href="https://en.wikipedia.org/wiki/Dynamic_range">动态范围</a>;在中间计算过程中,浮点数运算能够容许超出标称范围,并且只在最后限制值</li> |
| <li>支持特殊值,如无穷数和 NaN</li> |
| <li>在许多情况下,更易于使用</li> |
| </ul> |
| |
| <p> |
| 一直以来,浮点数运算比整数或定点数运算慢,但现在只要控制流决策不是基于计算的值,浮点数运算的速度通常会更快。 |
| </p> |
| |
| <h2 id="androidFormats">Android 音频格式</h2> |
| |
| <p> |
| 主要的 Android 音频格式如下表所列: |
| </p> |
| |
| <table> |
| |
| <tbody><tr> |
| <th></th> |
| <th colspan="6"><center>标记</center></th> |
| </tr> |
| |
| <tr> |
| <th>属性</th> |
| <th>Q0.15</th> |
| <th>Q0.7 <sup>1</sup></th> |
| <th>Q0.23</th> |
| <th>Q0.31</th> |
| <th>浮点数</th> |
| </tr> |
| |
| <tr> |
| <td>容器<br />位</td> |
| <td>16</td> |
| <td>8</td> |
| <td>24 或 32 <sup>2</sup></td> |
| <td>32</td> |
| <td>32</td> |
| </tr> |
| |
| <tr> |
| <td>有效位<br />包括符号</td> |
| <td>16</td> |
| <td>8</td> |
| <td>24</td> |
| <td>24 或 32 <sup>2</sup></td> |
| <td>25 <sup>3</sup></td> |
| </tr> |
| |
| <tr> |
| <td>余量<br />(以 dB 为单位)</td> |
| <td>0</td> |
| <td>0</td> |
| <td>0</td> |
| <td>0</td> |
| <td>126 <sup>4</sup></td> |
| </tr> |
| |
| <tr> |
| <td>动态范围<br />(以 dB 为单位)</td> |
| <td>90</td> |
| <td>42</td> |
| <td>138</td> |
| <td>138 到 186</td> |
| <td>900 <sup>5</sup></td> |
| </tr> |
| |
| </tbody></table> |
| |
| <p> |
| 上述所有定点数格式的标称范围均为 -1.0 至 +1.0 减去一个 LSB。由于采用二进制补码表示法的缘故,负值要比正值多一个。 |
| </p> |
| |
| <p> |
| 脚注: |
| </p> |
| |
| <ol> |
| |
| <li> |
| 以上所有格式表示的是有符号的样本值。8 位格式通常称为“无符号”,但实际上是偏差为 <code>0.10000000</code> 的有符号值。 |
| </li> |
| |
| <li> |
| Q0.23 可以打包成 24 位(三个 8 位字节),或者解包成 32 位。如果解包,则有效位向右对齐到 LSB,以符号扩展填充到 MSB (Q8.23);或向左对齐到 MSB,以零填充到 LSB (Q0.31)。Q0.31 理论上允许多达 32 个有效位,但接受 Q0.31 的硬件接口很少使用所有位。 |
| </li> |
| |
| <li> |
| 单精度浮点数具有 23 个显式位以及一个隐藏位和符号位,因而一共有 25 个有效位。 |
| <a href="https://en.wikipedia.org/wiki/Denormal_number">非规格化数</a>的有效位要少一些。 |
| </li> |
| |
| <li> |
| 单精度浮点数可以表达高达 ±1.7e + 38 的值,这也是大余量的原因所在。 |
| </li> |
| |
| <li> |
| 所示的动态范围适用于非规格化数一直到最大标称值 ±1.0。请注意,某些特定于架构的浮点数实现(如 <a href="https://en.wikipedia.org/wiki/ARM_architecture#NEON">NEON</a>)不支持非规格化数。 |
| </li> |
| |
| </ol> |
| |
| <h2 id="conversions">转换</h2> |
| |
| <p> |
| 本节将讨论各种表示法之间的<a href="https://en.wikipedia.org/wiki/Data_conversion">数据</a>转换。 |
| </p> |
| |
| <h3 id="floatConversions">浮点数转换</h3> |
| |
| <p> |
| 将值从 Qm.n 格式转换为浮点数:<em></em><em></em> |
| </p> |
| |
| <ol> |
| <li>将值转换为浮点数,就像它是一个整数(通过忽略该点)。</li> |
| <li>乘以 2<sup>-n</sup>。<em></em></li> |
| </ol> |
| |
| <p> |
| 例如,要将 Q4.27 内部值转换为浮点数,请使用: |
| </p> |
| <pre class="devsite-click-to-copy"> |
| float = integer * (2 ^ -27) |
| </pre> |
| |
| <p> |
| 从浮点数转换为定点数会遵循以下规则: |
| </p> |
| |
| <ul> |
| |
| <li> |
| 单精度浮点数的标称范围为 ±1.0,但中间值的完整范围为 ±1.7e+38。外部表示法中的浮点数和定点数之间的转换(例如输出到音频设备)将仅考虑标称范围,对超过该范围的值会进行限制。尤其是,当 +1.0 被转换为定点数格式时,它将被限制为 +1.0 减去一个 LSB。 |
| </li> |
| |
| <li> |
| 非规格化数(次正规数)和 +/- 0.0 在表示法中都允许使用,但在处理过程中可能会静默转换为 0.0。 |
| </li> |
| |
| <li> |
| 无穷数可能会通过操作,或者静默硬限制为 +/- 1.0。通常后者用于转换为定点数格式。 |
| </li> |
| |
| <li> |
| NaN 行为尚未定义:NaN 可以作为相同的 NaN 传递,也可以转换为默认 NaN;可以静默地硬限制为 +/- 1.0,也可以静默地转换为 0.0,或者导致错误。 |
| </li> |
| |
| </ul> |
| |
| <h3 id="fixedConversion">定点数转换</h3> |
| |
| <p> |
| 不同 Qm.n 格式之间的转换会遵循以下规则:<em></em><em></em> |
| </p> |
| |
| <ul> |
| |
| <li> |
| 当 m 增加时,用符号扩展左边的整数部分。<em></em> |
| </li> |
| |
| <li> |
| 当 m 减小时,限制整数部分。<em></em> |
| </li> |
| |
| <li> |
| 当 n 增加时,用零扩展右边的小数部分。<em></em> |
| </li> |
| |
| <li> |
| 当 n 减少时,抖动、舍入或截断右侧的多余小数位。<em></em> |
| </li> |
| |
| </ul> |
| |
| <p> |
| 例如,要将 Q4.27 值转换为 Q0.15(无抖动或舍入),则将 Q4.27 值右移 12 位,并限制超过 16 位有符号范围的任何结果。这样将对齐 Q 表示法的点。 |
| </p> |
| |
| <p>要将 Q7.24 转换为 Q7.23,可进行带符号除以 2,或者等价地将符号位添加到 Q7.24 整数,然后带符号右移 1。请注意,简单带符号右移不等于带符号除以 2。<em></em> |
| </p> |
| |
| <h3 id="lossyConversion">有损和无损转换</h3> |
| |
| <p> |
| 如果转换<a href="https://en.wikipedia.org/wiki/Inverse_function">可逆</a>,则是无损的:从 <code>A</code> 转换到 <code>B</code> 再到 <code>C</code>,那么可以得出 <code>A = C</code>。否则,转换是<a href="https://en.wikipedia.org/wiki/Lossy_data_conversion">有损</a>的。<em></em> |
| </p> |
| |
| <p> |
| 无损转换允许<a href="https://en.wikipedia.org/wiki/Round-trip_format_conversion">往返格式转换</a>。 |
| </p> |
| |
| <p> |
| 从具有 25 位或更少有效位的定点数表示法转换到浮点数是无损的。从浮点数转换到任何常见的定点数表示法则是有损的。 |
| </p> |
| |
| </body></html> |