等时适配层

Mark Walen大约 7 分钟

基础

等时适配层(ISOAL)的主要目的,是解决在涉及音频设备的连接型与广播型等时通信中可能出现的潜在问题。 它也可能在等时通信的其他应用场景中发挥作用。

Nick Hunn 的著作 Introducing Bluetooth LE Audio(《蓝牙 LE 音频介绍》)第 5.2 节对该主题有详细阐述,推荐阅读。

音频采样基础(Audio Sampling 101) 数字音频的工作原理是对模拟音频信号进行采样,并对采样后的音频应用编解码器(codec)进行压缩或其他处理,以便存储,或者在蓝牙 LE 音频的情况下进行传输。

在读取或接收编码后的数字音频数据时,流程则相反:使用编解码器对数据进行解码,生成一系列数字采样,然后利用这些数字采样(近似地)重现原始的模拟音频。

图 1.1 展示了采样、编码和传输音频信号的步骤,以及接收编码音频数据、解码并最终渲染音频的逆向步骤。

音频处理步骤
图1.1 音频处理步骤

音频编解码器的一个关键目标是 减小音频数据的大小,以便能够在带宽有限(且宝贵!)的链路上高效传输。

采样的过程包括在固定时间间隔测量并记录信号的幅度。采样的频率称为 采样率(sample rate)

图 1.2 中的垂直线表示对连续变化的音频信号(由曲线表示)进行的采样。这一系列采样点构成了原始模拟信号的近似表示。

采样越频繁(即采样率越高),这种近似就越接近原始信号。在反向处理以重建原始音频时,采样率越高,重建效果越好,感知的音质也越高。

采样的另一个维度是 位深(bit depth)。在采样时,信号的幅度需要用整数值表示。

一种方法是将可能的幅度值范围划分为 256 个离散幅度带,并用 0 到 255 之间的数字表示每个幅度带。在这种方案下,每个采样只需一个字节(8 位)即可记录采样幅度所属的幅度带,因此位深称为 8 位

将可能的幅度范围划分为更多离散幅度带,可以提供更细粒度的采样值表示系统,从而潜在地提高音质。例如,24 位位深可以用 0 到 16,777,215 范围内的整数表示可能的幅度值范围。然而,每个采样需要 3 个字节,因此使用更高位深进行采样会产生三倍的数据量。

离散采样表示连续的模拟信号
图 1.2 离散采样表示连续的模拟信号

编解码器与帧(Codecs and Frames)

像 LC3 这样的编解码器(codec),用于蓝牙 LE 音频,可能将原始数字采样数据压缩到 不到原始大小的 25%(但请注意,实际压缩效果在很大程度上取决于原始音频内容)。这是一个非常显著的节省。

编解码器通常通过识别并利用一系列连续采样中的模式来工作。举一个非常简单的例子,仅用于说明这一原理:如果数据集中包含一连串 100 个采样值,且每个值都相同,例如 50,那么假设位深为 8 位,编解码器可能将其表示为两个字节 [100, 50],而不是原来的 100 个字节 [50, 50, 50..., 50]。显然,为了让编解码器发挥作用,它需要分析和编码 整系列采样,而不是一次只处理一个采样(单个采样中几乎找不到模式!)。

编解码器一次分析的一组采样称为 帧(frame)。帧具有固定的持续时间,通常以毫秒为单位,并包含由采样率决定的若干采样。例如,当采样率为 44.1 kHz 时,10 毫秒的帧包含 4410 个采样。

不同的音频产品可能使用不同的帧持续时间,10 毫秒和 7.5 毫秒较为常见。当一个设备生成音频(源设备)使用某种帧持续时间,而另一个设备接收音频(接收设备)使用不同的帧持续时间时,就会出现需要解决的问题。这正是 等时适配层(ISOAL) 的作用所在。

帧式(Framed)与非帧式(Unframed)

当设备使用等时通信时,发送设备和接收设备使用的帧持续时间 不必相同。这会产生两种可能的情况:

  1. 第一个设备使用的帧持续时间是另一个设备使用的帧持续时间的 整数倍
  2. 第一个设备使用的帧持续时间 不是 另一个设备使用的帧持续时间的整数倍。

在第一种情况下,较大帧持续时间与较小帧持续时间之间的关系很简单,将数据在两者之间转换是一个直接操作。在一个或多个必需的链路层 PDU 的负载中发送的数据称为 非帧式(unframed),其中不包含用于支持帧持续时间适配的额外数据。

在第二种情况下,链路层 PDU 可能包含较大负载的一部分,同时附带简短的头字段,用于指示该部分是帧的 开始延续结束。这种格式的数据称为 帧式(framed)

无论是 连接型等时 PDU(Connected Isochronous PDU) 还是 广播型等时 PDU(Broadcast Isochronous PDU)(由链路层定义),都包含一个称为 LLID 的字段。LLID 用于指示链路层 PDU 的负载是 帧式 还是 非帧式 数据。

ISOAL 根据从链路层接收到的数据是否帧式,应用不同的处理过程。同样,是否需要帧式处理也会影响 ISOAL 对从上层 SDU 接收到的数据进行处理,并传递给链路层以在链路层 ISO PDU 中传输的方式。

分片与重组(Fragmentation and Recombination)

如果数据为 非帧式(unframed),则重组过程会将一个或多个链路层 PDU 负载中包含的一个或多个片段,组合成 单个服务数据单元(Service Data Unit, SDU)。随后,ISOAL 将该 SDU 传递给上层。如图 3.1 所示。

非帧式 ISO PDUs 的重组
图3.1 非帧式 ISO PDUs 的重组

上层 SDU 需要被拆分为更小的负载 以便在链路层 PDU 中传输,并且 不需要帧式处理 时,该过程称为 分片(fragmentation)。如图 3.2 所示。

分片生成非帧式 ISO PDUs
分片生成非帧式 ISO PDUs

非帧式 PDU 包含一个头部,其中包含字段,用于指示其后的数据是 SDU 的开始前一个 SDU 的延续,还是 该 SDU 的结束

每个 PDU 只包含 单个非帧式 SDU 的一个片段

分段与重组(Segmentation and Reassembly)

如果数据为 帧式(framed),则重组过程会将一个或多个链路层 PDU 负载中包含的一个或多个 分段(segment) 组合成 单个服务数据单元(Service Data Unit, SDU)。随后,ISOAL 将该 SDU 传递给上层。如图 4.1 所示。

帧式 ISO PDU的重组
图4.1 帧式 ISO PDU的重组

上层 SDU 需要被拆分为更小的负载 以便在链路层 PDU 中传输,且 需要帧式处理 时,该过程称为 分段(segmentation)。如图 4.2 所示。

分段生产帧式 ISO PDUs
分段生产帧式 ISO PDUs

帧式 PDU 中的每个分段都包含一个头部,其中包含字段,用于指示其后的数据是 SDU 的开始前一个 SDU 的延续,还是 该 SDU 的结束,并且包含 时间偏移信息(timing offset information)。帧式 PDU 可以包含 同一 SDU 的多个片段