第7章-设置单播音频流

机器翻译结果,仅用于学习,不喜勿喷,原文档链接

在本章中,我们将了解如何配置和设置单播音频流。此阶段涉及的四个主要spec是:

  • PACS – the Published Audio Capabilities Service,
  • ASCS – the Audio Stream Configuration Service,
  • BAP – the Basic Audio Profile, and
  • CAP – the Common Audio Profile.

CAP 位于其他三个之上,并定义了使用 BAP、ASCS 和 PACS 来配置和管理单播音频流的过程,引入了协调、Context类型和内容控制 ID,以将音频流与用例相关联。大多数时候,CAP 只是一组规则,告诉您运行 BAP 程序的正确顺序以及如何使用Context类型和内容控制 ID。顶层蓝牙® LE Audio profile,例如 HAP 和 TMAP,建立在 CAP 之上,主要扩展了强制性要求。在本章中,我将专注于底层的 BAP 过程,因为它们完成了繁重的工作,但在必要时将参考 CAP 和更高层的profile。

所有LE audio spec都基于BLE 的 GATT 结构,具有client-server关系。更高层spec为单播音频流提供Context并添加控制,但 BAP、ASCS 和 PACS 是它们构建的基础。

7.1 PACS—Published Audio Capabilities Service

PACS 是最简单的spec,本质上是对 Acceptor 可以做什么的说明。 Acceptor 使用 PACS 在两个特性中公开这些功能——如果它支持音频接收器角色,则为接收器 PAC 特性;如果它支持音频源角色,则为源 PAC 特性。这些包含已发布的音频兼容性记录,称为 PAC 记录,其中包括有关编解码器及其支持的配置的信息,以及其他可选功能。在它们之间,它们暴露了设备的全部功能。

PACS 可以被认为是 Acceptor 音频功能的数据库,它在制造时被填充,并且在产品的整个生命周期内都是静态的,尽管它可以通过固件更新进行更新。 PACS 指定initiator在开始配置和建立音频流的过程时获得的信息。广播助手也可以使用 PACS 过滤它检测到的广播流,以便广播接收器仅显示兼容的音频流,但我们将在广播一章中介绍。

关于 PACS 指定的信息的一个重要概念是它是关于acceptor总能力的事实陈述。 PACS 描述了 Acceptor 能够做什么。这是设备相互了解的第一步。在 Initiator 读取了这些功能之后,Acceptor 通常会在建立流的过程中公开一组更有限的首选功能,并且 Initiator 应该使用这些值。但是,Acceptor 不应拒绝 Initiator 基于其公开的 PACS 信息请求的任何配置。

目的是这应该导致一个有效的配置过程,特别是当涉及多个acceptor时,特别是如果它们来自不同的制造商并且具有不同的功能。这是经典蓝牙音频profile的演变,允许central和peripheral通过协商循环,两个设备尝试确定音频连接的最佳设置。在某些实现中,这会导致死锁、永远无法建立连接,或者影响音频质量的编解码器配置不佳。这个问题导致包含“S”和“D”编码设置作为 CVSD 的建议和 mSBC 的“T”eSCO参数集。 PACS 的目的是防止出现这些问题。

7.1.1 Sink PAC and Source PAC characteristics

Sink PAC 和 Source PAC 特征都包含“i” PAC 记录的数组,采用表 7.1 所示的形式。

PAC RecordDescription
Number_of_PAC_RecordsNumber of PAC records [i] for this characteristic
Codec_ID [i] (5 octets)Octet 0: Codec (defined in the Bluetooth Assigned Numbers) LC3 = 0x06
Vendor Specific = xnn
Octets 1&2: Company ID, if vendor specific,
otherwise 0x00
Octets 3&4: Vendor specific Codec ID,
otherwise 0x00
Codec_Specific_Capabilities_Length [i] (1 octet)Length of the codec specific capabilities for the codec in the ith PAC Record.
Codec_Specific_Capabilities [i] (length varies)Identification of the capabilities of the codec implementation in the ith PAC Record, normally expressed as a bitfield.
Metadata length [i] (1 octet)Length of the metadata associated with the ith PAC Record. 0x00 if there is none.
Metadata [i]LTV formatted metadata for the ith PAC record
Table 7.1 Format of a PAC Record

7.1.2 编解码器特定功能

每个LE audio spec都包含至少一个使用 LC3 编解码器的 PAC 记录,因为这是在 BAP 中强制要求的,它是通用音频框架的最低层。分配给 LC3 的编号是 0x06,因此每个LE audio 接收器将至少有一个 PAC 记录,其 Codec_ID 为 0x0000000006。请注意,Codec_ID 是host controller接口分配编号列表中描述的编码格式,而不是音频/视频分配编号列表中定义的音频编解码器 ID。

LC3 的 Codec_Specific_Capabilities 要求在 BAP 第 4.3.1 节中定义,由五个 LTV 结构组成。每个 LTV 都有一个类型代码,在 Generic Audio Assigned Numbers 文档中定义,以便读取它的设备可以识别它。

由于其中三个 LTV 是位域,这意味着 Codec_Specific_Capabilities 结构中通常描述了多种组合。

7.1.2.1 Supported_Sampling_Frequencies LTV

这五个 LTV 结构中的第一个是表 7.2 中所示的 Supported_Sampling_Frequencies (Type = 0x01),它是一个覆盖 8 kHz 到 384 kHz 范围的采样频率位域。通过将相应位设置为 1 来指示对每个值的支持。此 LTV 是强制性的。 (请注意,此结构可用于任何编解码器。LC3 仅指定 8、16、24、32、44.1 和 48 kHz 采样频率,显示为浅阴影)。
在这里插入图片描述

7.1.2.2 Supported_Frame_Durations LTV

第二个编解码器能力 LTV 结构是表 7.3 的 Supported_Frame_Durations (Type = 0x02),它提供了 LC3 编解码器支持的两个帧持续时间的信息——7.5ms 和 10ms。当设置为 1 时,位 0 和 1 表示支持 LC3 的 7.5ms 和 10ms 帧这两个选项。如果同时支持 7.5 ms 和 10 ms,则可以使用第 4 位和第 5 位来指示是否首选其中之一。只能设置第 4 位和第 5 位之一。此 LTV 也是强制性的。

BitAll other bits543210
Frame DurationRFU7.5ms preferred10ms preferredRFURFU10ms supported7.5ms supported
Table 7.3 Supported Frame Durations (0x02)
7.1.2.3 Supported_Audio_Channel_Counts LTV

第三个 LTV 结构是 Supported_Audio_Channel_Counts (Type = 0x03),如表 7.4 所示。这是另一个位域,它指示可以包含在 CIS 或 BIS 中的音频通道的数量。 Channel Count 是多路复用音频通道的数量,可以在等时流上以相同方向承载,我们在第 5.8 节中进行了介绍。位 0 到 7 表示支持的通道数,值为 1 表示支持的选项。必须至少设置一位,否则表示无法设置音频通道。如果不支持多路复用,则 Channel Count 为 1,可以省略此 LTV 结构。
在这里插入图片描述

7.1.2.4 Supported_Octets_Per_Codec_Frame LTV

第四个 LTV 结构是 Supported_Octets_Per_Codec_Frame (Type = 0x04),如表 7.5 所示。此结构由两对两个八位字节组成,下对(八位字节 0 和 1)指定每个编解码器帧的最小八位字节数,上对指定每个编解码器帧的最大八位字节数。两者都可以设置为相同的值,其中仅支持特定数量的八位字节。它定义了所选采样率支持的比特率范围(参见表 5.1)。此 LTV 也是强制性的。
在这里插入图片描述

7.1.2.5 Supported_Max_Codec_Frames_Per_SDU LTV

Supported_Codec_Specific_Capabilities 中的第五个也是最后一个 LTV 结构是 Supported_Max_Codec_Frames_Per_SDU (Type = 0x05),它是一个单个八位字节,说明可以打包到单个 SDU 中的编解码器帧的最大数量。如果每个 SDU 只有一帧,则可以省略。

7.1.2.6 Preferred_Audio_Contexts LTV

Codec Specific Capabilities 后面可以跟metadata,metadata采用 LTV 结构进行格式化,并在 Generic Audio Assigned Numbers 文档的 Codec Specific Capabilities LTV 结构部分进行了描述。目前,与 PAC 记录相关的唯一已定义metadata是 Preferred_Audio_Contexts LTV。这是Context类型值的 2 个八位字节位域,使用 Generic Audio Assigned Numbers 文档中的Context类型的标准值。如果某个位设置为 0b1,则表示此Context类型是该 PAC 记录中编解码器配置的首选用例。它通常仅在Acceptor首选特定 PAC 记录用于特定用例时才会出现,提供比 Supported_Audio_Contexts 特征 (qv) 更多的粒度。

7.1.3 音频接收器的最低 PACS 能力

强制性 BAP LC3 要求意味着充当单播音频接收器(即接收音频流)的接收器必须支持在 16 和 24kHz 采样频率下以 10ms 的帧持续时间接收至少一个音频通道。类似地,每个充当单播音频源(即传输音频流)的接收器必须支持以 16 kHz 采样频率和 10ms 帧持续时间对至少一个音频通道进行编码。

音频接收器和源的强制 16kHz 采样率要求每个 SDU 支持 40 个八位字节,而音频接收器的 24 kHz 采样率需要 60 个八位字节。对于以下说明 PAC 记录的示例,我们将只查看 Sink PAC 特征。相同的原则适用于源 PAC 特性。

接收器 PAC 特性通常会在单个 PAC 记录中公开这两个强制性编解码器设置。或者,可以将它们分成两个 PAC 记录,每个记录指定一组功能。 BAP 只需要支持一个音频通道(BAP 表 4.2 中的音频配置 1),但是为了说明 PAC 记录是如何构建的,让我们看一个可以支持两个音频通道的acceptor示例(对应于音频配置 4)。如果将这些作为四个单独的 PAC 记录公开,它们将类似于表 7.6。
在这里插入图片描述

作为如何形成它们的示例,表 7.6 包含所有受支持的LE audio profile的强制编解码器要求的接收器 PAC 记录参数,即 BAP 表 5.2 和表 6.4 中的 16_2_1、16_2_2、24_2_1 和 24_2_2 QoS 配置.涵盖这些:

  • Supported_Sampling_Frequencies 特性的值为 0x04 对应 16kHz 和 0x10 对应 24kHz。
  • Supported_Frame_Durations 为 0x02 表示它仅支持 10ms 帧。
  • Supported_Audio_Channel_Counts 值为 0x00 和 0x01,以支持一个和两个通道。
  • Supported_Octets_per_Codec_Frame 的值为 0x2828 和 0x3C3C 用于 40 和 60 个八位字节,对应于 16_2_n 和 24_2_n QoS 设置,最后,
  • Supported_Max_Codec_Frames_Per_SDU 表示每个 SDU 只有一个编解码器帧,其值为 0x01。这可以省略,因为它是默认值。在这个 Sink PAC Characteristic 中没有metadata。

在表 7.7 的单个 PAC 记录中可以更简洁地提供相同的信息:

PAC RecordRecord 0 (L-T-V)
Codec_ID (LC3)0x0D
Codec_Specific_Capabilities_Length0x0B
Codec_Specific_Capabilities
Supported Sampling Frequencies0x 02 01 14
Supported Frame Durations0x 02 02 02
Supported Audio Channel Counts0x 02 03 03
Supported Octets per Frame0x 03 04 3C28
Supported Max Codec Frames Per SDU0x 02 05 01 (Could be omitted as default = 1)
Table 7.7 The PAC record content of Table 7.6 as a single record

这两种表示并不完全等价。 PACS 规定,Acceptor 必须支持参数值的所有可能组合以及 PAC 记录中声明的参数值的所有其他可能组合。这意味着如果 PAC 记录中包含多个值,如表 7.7 中的示例,那么每个可能的组合都是有效的,因为Initiator 可以将 PAC 记录扩展为所有可能组合的数组。理论上,这意味着如果需要,暴露表 7.7 的单个 PAC 记录的 Acceptor 应该支持 24 kHz 采样的 40 个八位字节的值和 16 kHz 采样的 60 个八位字节的值,以及 40 到 60 之间的任何八位字节值,虽然这些都是非标准的。为了互操作性,假设Initiator 应该限制自己使用 BAP 表 5.2 和 6.4 中的特定配置,这些配置已经过尝试和测试,但Initiator 应该选择另一种组合。这不是好的做法,但这是允许的。如果不是所有这些组合在设备中都有效,则 PAC 记录应表示为单独的 PAC 记录。但是,这可能会导致记录数量迅速增加,这不是一件好事。上面的示例是 BAP 所需的基线支持,产生了四个 PAC 记录,这是可管理的。尝试对 TMAP 执行相同的操作将需要至少 96 个单独的 PAC 记录。正如我们将很快看到的那样,ASE 配置过程可以指导配置等时流的首选选项,因此可以为应用程序保留单独的 PAC 记录,例如供应商特定的编解码器功能。 PACS 的第 3 节提供了更多详细信息。

如果 Acceptor 支持多于一种编解码器类型,则每种类型都需要至少一个 Sink 或 Source PAC 特征,因为 PAC 记录的 Codec_ID 字段是唯一的。由实现决定编解码器的所有 PAC 记录是否在单个或多个 Sink PAC 或 Source PAC 特征中公开。如果有大量 PAC 记录,实现可能希望将它们拆分为单独的 PAC 记录特征,以防止在读取它们时超出最大 ATT MTU 大小。

接收器 PAC 特性不区分单播和广播流,因此这些值适用于两者。广播时忽略源 PAC 特征。

7.1.4 音频位置

Sink PAC 和 Source PAC 特性都可以分别具有关联的 Sink_Audio_Locations 和 Source_Audio_Locations 特性,尽管这些是可选的。音频位置的基本概念已在第 3 章中描述。 Sink_Audio_Locations 和 Source_Audio_Locations 特性指定接收器支持接收和传输的音频流的哪些音频位置。每个特征都有一个四字节字段,它是一个位字段,指示它支持哪些渲染或捕获位置。

如果它们存在,则必须始终设置至少一位。如果它们不存在,则设备应接受发起方建议的任何音频位置。在许多情况下,这些值由制造商设置并且是只读的;右耳塞永远只能是右耳塞,右前的单个接收器和/或源音频位置也是如此。扬声器可能会将其 Sink_Audio_Locations 特性设置为 Front Left 和 Front Right。当Initiator 想要建立一个流时,它会决定发送哪个音频流来匹配音频位置。如果它找到两个扬声器,它通常会将左立体声流发送到暴露左前位置的扬声器,并将右立体声流发送到具有右前位置的扬声器。如果他们都说他们可以同时支持左前和右前(大多数人都会这样做),那么用户通常会使用应用程序来配置哪个是哪个。 Sink 和 Source Audio Locations 特性可能是可写的,这将允许配置实用程序设置扬声器位置以供其他initiator使用。因为这些都是低功耗蓝牙音频spec中的互操作功能,这意味着任何兼容的音频应用程序都应该能够执行这种配置。或者,扬声器制造商可以在其扬声器上提供物理开关,以允许用户指定扬声器是接收左流还是右流。

在第 5 章中,我们研究了 Initiator 和 Acceptor 如何处理缩混立体声流以进行单声道再现,表明这可以在对音频流进行编码之前完成,也可以在接收和解码之后完成。 Acceptor 可以使用其 PAC 记录向 Initiator 指示它是否能够进行缩混。如果它将其音频位置设置为左前和右前,但仅支持单个LE audio 通道,则意味着它无法进行缩混,而只会渲染已提供的流。如果它显示对两个通道的支持,则意味着它可以将它们解码为要呈现的单独流。然后由 Acceptor 实现将它们呈现为:

  • 单独的左右音频通道,如果它是条形音箱或立体声扬声器,它会这样做,
  • 它解码的两个音频通道中的一个,如果它是耳塞或助听器,它可能会这样做,或者
  • 如果它包含单个扬声器,则将它们缩混为单个单声道音频通道。

后两个选项通常需要扬声器的某种级别的用户配置,但这取决于实施。

Source_Audio_Locations 特性的行为方式相同,但在大多数情况下,它可能仅限于支持左前和右前。如果 Acceptor 支持单个音频通道,则 Initiator 将假定它是单声道麦克风。如果它支持两个音频通道,则initiator会假定它是一个立体声麦克风。

使用 Sink 和 Source Audio Location 特性以及 Audio Channel Counts 为引导音频流提供了很大的灵活性。其中大部分是隐含的,因此实施者需要仔细考虑他们使用的参数组合。

Sink 和 Source Audio Location 特征值都可以更改,包括在连接期间。但是,如果在连接期间发生这种情况,则不需要终止音频流。新值将应用于下一个流建立过程。应用程序还可以决定更改流,例如,如果用户想要镜像立体声效果,因为他们面对的方向,在左右音频流之间交换左右声道输入。这是特定于实现的,超出了spec。

7.1.5 支持的音频Context

每个 Acceptor 都需要包含一个 Supported_Audio_Contexts 特性,它列出了它支持的Context类型。这通常是一个静态列表,它只会随着软件更新而改变,它改变了acceptor的功能。

支持的音频Context的名称有点误导。这个特性的作用是列出Acceptor可以使其自身不可用的Context类型(即用例),以防止任何Initiator试图为Acceptor不感兴趣的用例建立音频流。支持每个Context类型都是可选的,除了«Unspecified» Context类型,必须在每个 Supported_Audio_Contexts 特性 [BAP 3.5.2.1] 中支持。如果音频Context未标记为受支持,发起方仍可以尝试建立流,通过将该Context类型映射到其音频流的«Unspecified» Context类型。如果 Acceptor 当前将 «Unspecified» 设置为可用(见下文),它没有理由拒绝该请求。作为接收到音频流的结果,Acceptor 可以决定为将来的请求更改该Context类型值的 Available_Audio_Contexts 设置。

鉴于这种行为,Acceptor 应该设置 Supported_Audio_Contexts 特性中的每个Context类型位,它认为它有理由使该用例不可用。 (Audio Sink 被禁止对所有东西都不可用,因为 Assigned Numbers 文档禁止 Available_Audio_Contexts 值为 0x0000。)

7.1.6 可用的音频Context

Acceptor 使用 Available_Audio_Contexts 特性来通知 Initiator 它不适用于它在 Supported_Audio_Contexts 特性中声明支持的特定Context类型。为了允许Initiator 继续音频流建立过程,Initiator 想要设置的音频流的Context类型必须在 Available_Audio_Contexts 特性中显示为可用。与静态的 Supported_Audio_Contexts 值不同,Acceptor 可以随时更新其 Available_Audio_Contexts 值,并在更新时通知连接的 Initiator。

为了说明这一点,图 7.1 显示了 Supported_Audio_Contexts 和 Available_Audio_Contexts 特性的典型设置。
在这里插入图片描述

在这个例子中,Acceptor 支持 «Unspecified»,(这是强制性的),以及

«紧急警报»、«铃声»、«对话»、«教学»和«媒体»。它显示所有这些都是可用的。如果 Initiator 想要使用这些 Context Types 中的任何一个启动流,Acceptor 应该接受它。

如果Initiator 想要建立一个流来传送按键声音,它可以被«Sound Effects»上下文类型覆盖。这是因为 Available_Audio_Contexts 位图显示 «Unspecified» 可用。只要«Unspecified»在 Acceptor 中显示为可用,initiator就可以在其Streaming_Audio_Contexts元数据的属性中将它想要使用的不可用Context类型映射到«Unspecified»。在这种情况下,Acceptor 必须接受音频流。
在这里插入图片描述
图 7.2 说明了在 Supported_Audio_Contexts 特性中设置Context类型位的值。在此示例中,支持«紧急警报»和«铃声»,但当前未在 Available_Audio_Contexts 特征中标记为可用。这意味着如果 Initiator 尝试建立与这些Context类型相关联的流,它将被 Acceptor 拒绝,因为它们被明确设置为不可用。如果这些位未被设置为受支持,则Initiator 可以将它们映射到«Unspecified» 。但是,在这种情况下,这是不允许的,因为它们被设置为受支持而不是可用。但是,Initiator 仍然可以将与“警报”、“通知”或任何其他不受支持的音频Context相关联的流重新映射到«Unspecified»,Acceptor应该接受。
在这里插入图片描述
最后,图 7.3 显示了一个示例,其中 «Unspecified» 被指示为不可用(请记住始终必须支持 «Unspecified»)。将 «Unspecified» 设置为不可用可防止initiator将任何其他不可用的Context类型映射到

«Unspecified»,因此在这种情况下,Acceptor 仅适用于与 «Instructional»、«Media» 或 «Conversational» 相关联的音频流。

表 7.8 说明了initiator如何解释设置的这种行为。 Acceptor 可以有效地设置三个选项:

  • 允许Initiator 继续建立音频流,
  • 禁止它启动音频流,或
  • 说它不在乎——试试吧。

不支持和可用的组合是不允许的。

Supported Audio ContextsAvailable Audio ContextsInterpretation for Initiator
0b00b0音频流Context类型可以映射到«Unspecified»
0b00b1不允许这种组合
0b10b0Initiator 不应建立具有此Context类型的音频流
0b10b1Initiator可以建立一个具有此Context类型的音频流
Table 7.8 Result of Supported and Available Bluetooth® LE Audio Context Type settings

虽然 Supported_Audio_Contexts 特性对所有client都有效,但 Acceptor 可能会向不同client公开不同的 Available_Audio_Contexts 特性值。这允许 Acceptor 决定不同的 Initiator 可以做什么,例如控制哪些设备可以将媒体流式传输到它,或者基于每个client为电话建立音频流。如何管理这取决于实现,并且取决于acceptor来管理执行此操作所需的不同名称空间。实施后,它为Acceptor提供了一种基于用例设置连接策略的方法,这在蓝牙经典音频profile中是不可能的。

7.2 ASCS—Audio Stream Control Service

PACS 指定 Acceptor 公开其属性的方式以及它在任何时间点可以执行的操作。对于大多数设备,它将包括广泛的编解码器设置和Context选项,它是否可以充当源和/或接收器,以及它支持哪些音频位置。这个范围需要缩小到单独的参数集来建立音频流,这通常是因为当前的资源限制,例如当一个acceptor支持多个音频流时,可能需要不同的参数。通过为每个音频流定义endpoint ,这就是音频流控制服务发挥作用的地方。音频流控制服务在 Acceptor 上实现,并定义了 Initiator 如何使用 BAP 中定义的过程在两者之间配置和建立音频流。

7.2.1 音频流endpoint

音频流控制服务的核心是音频流endpoint 的概念。音频流endpoint 或 ASE 定义为acceptor中单播音频流的起点或终点。 Initiator 不包含任何 ASE——它在 Acceptor 上配置 ASE。如果音频数据流入 ASE,它就是 Sink ASE。如果它流出它,它就是一个Source ASE,这两者都是由只读特性描述的。 Acceptor 必须为它能够支持的每个音频流公开至少一个 ASE。

对于每个 ASE,Acceptor 为每个连接的 Initiator 维护一个状态机实例。 ASE 的状态由每个 Initiator 控制,尽管在某些情况下 Acceptor 可以自主更改 ASE 的状态。 Sink 和 Source PAC 为 Initiator 提供设备范围的属性,而 Sink 和 Source ASE 表示每个连接的当前状态和属性。这些可以使用 Sink 或 Source ASE 特性读取,这将返回表 7.9 中显示的信息。

FieldSize (Octets)Description
ASE_ID1A unique ID for each client namespace
ASE_State10x00 = Idle
0x01 = Codec Configured
0x02 = QoS configured
0x03 = Enabling
0x04 = Streaming
0x05 = Disabling
0x06 = Releasing
State specific ASE ParametersvariesDepends on the state (See ASCS Tables 4-2 to 4-5)
Table 7.9 ASE Characteristic format

图 7.4 显示了 Sink ASE 的状态机。 Source 的状态机稍微复杂一些,因为它包含一个额外的 Disabling 状态。我们将从 Sink ASE 状态机开始,因为启用 ASE 的过程在 Streaming 状态之前基本上是相同的,然后查看进入 Disabling 状态时的差异。
在这里插入图片描述
ASCS 通过使用表 7.10 中列出的操作码向 ASE 控制点特征写入一系列命令,定义了initiator如何通过这些状态移动acceptor上的每个 ASE。它们在 ASCS 的第 4.2 节中定义。

OpcodeOperationDescription
0x01Config CodecConfigures an ASE’s codec parameters.
0x02Config QoSConfigures the ASE’s preferred QoS parameters.
0x03EnableApplies the CIS parameters and starts coupling an ASE to a corresponding CIS.
0x04Receiver Start ReadyCompletes the CIS establishment and signals that an ASE is ready to receive or transmit audio data.
0x05DisableStarts to decouple an ASE from its CIS.
0x06Receiver Stop Ready (Source ASE only)Signals that the Initiator is ready to stop receiving data and completes decoupling a Source ASE from its CIS.
0x07Update MetadataUpdates metadata for an ASE.
0x08ReleaseReturns an ASE to the Idle or Codec Configured state.
Table 7.10 ASE Control Point operation opcodes

操作码 0x01(配置编解码器)和 0x02(配置 QoS)可用于转换 ASE 的状态,或更新已处于该状态的 ASE 的配置。操作码 0x07 更新metadata,但不改变状态。所有其他操作码都会导致 ASE 状态机中的另一个状态的转换。

只要 ASE 处于相同的状态,Initiator 就可以对单个 ASE 或多个 ASE 在 Acceptor 上执行 ASE 控制点操作。如果 CIG 在一个或多个 Acceptor 上包含多个 CIS,则 Initiator 应确保在将每个 Acceptor 上的 ASE 移至 Enabling 状态之前,它已从每个 Acceptor 上的每个 ASE 收集了相关信息。这重复了 CAP 所说的,即以正确的顺序对 Coordinated Set 的所有成员执行 BAP 过程。 (在大多数情况下,CIG 中的所有 Acceptor 都将是 Coordinated Set 的成员。但是,在 CAP 中允许 ad-hoc 集,其中 Acceptor 可以被分配以一起工作而不是 Coordinated Set 的成员,其中情况下配置的顺序留给实现。)

ASE 的一个特性是,Acceptor 支持每个 ASE 的单独实例,用于与 Initiator 的每个当前连接。如果有多个initiator与一个acceptor具有活动 ACL 连接,则acceptor将为每个initiator维护一组独立的 ASE 值。它为每个 Initiator 维护不同的 ASE_ID 命名空间。虽然 ASE_ID 在每个命名空间中必须是唯一的,但相同的 ASE_ID 可以存在于不同的命名空间中。这意味着每个 ASE_ID 及其对应的句柄都保持唯一。管理这取决于实施。对一个命名空间中的 ASE 的更改不会影响不同命名空间中相同 ASE 的状态(尽管该更改可能会导致应用程序将 CIS 从一个 ASE 移动到另一个 ASE 作为该更改的结果,但这是实现具体的。)

如果 Acceptor 建立了与多个 Initiator 的连接历史,它们可能会决定维护具有缓存配置的 ASE 集。这简化了从不同initiator转换到音频流的过程。尽管该spec允许一个 Acceptor 使用多个 Initiator 启用并发音频流,但实际上这需要大量资源和复杂的调度,因此可能很少见,至少在LE audio 设备的早期实现中是这样。在大多数情况下,利用缓存配置来实现简单的转换可能会提供更简单的解决方案。
在这里插入图片描述
图 7.5 显示了这些原则是如何工作的。它显示了具有三个 ASE 的acceptor如何为三个不同的client公开其实例化状态。目前,只有client A 已与句柄为 0x1234、0x1236 和 0x1240 的 ASE 建立流。如果client A 读取这三个 ASE,它将得知这三个都处于流状态。

如果client B 读取相同的句柄,它将被告知所有三个都是空闲的。请注意,client B 的 ASE_ID 可能不同,因为 Acceptor 为每个client分配和维护不同的命名空间。

最后,当client C 读取它们时,它会被告知它们处于 Codec 配置状态。这通常是因为client C 已经启用了之前的一组流,并且当它们被释放时,它要求 Acceptor 将 ASE 保持在 Codec Configured 状态,以在client C 下次想要建立流时加快连接。在这种状态下,编解码器配置被公开,因此client C 可以在将 ASE 移动到 QoS 配置状态之前查看是否需要执行重新配置。在其他状态下,不会公开编解码器配置信息。

Acceptor 必须为它可以支持的每个音频流公开至少一个 ASE。如果它在任一方向上支持多个LE audio 通道,则无论它是否使用所有这些音频通道,它都必须为每个音频通道至少支持一个 ASE。如果它支持多路复用,则每个方向上的 ASE 数量必须等于或大于为该方向设置为 0b1 的音频位置位数除以 Audio_Channel_Counts LTV [BAP 3.5.3] 中设置的音频通道的最高数量.如果一个 Acceptor 可以同时支持来自两个或多个 Client 的同时 Audio Streams,它需要为每个 Audio Stream 提供一个 ASE。更简单地说,Acceptor 必须支持它声称可以扔给它的所有东西,每个音频流至少有一个 ASE。

PAC 记录的全局范围和 ASE 的更有限的配置之间可能存在冲突,但它们有不同的目的和范围。为了理解 PAC 记录和 ASE 之间的关系,考虑一个类比可能会有所帮助,因此我们将再次求助于食物。如果您想到一家餐厅,那么已发布的音频功能就像厨房里的完整食材清单。 ASE 是单独的菜肴,仅使用这些成分的一部分。餐厅的期望是人们从菜单上选择菜肴,因为它们通常是为了适应用例而开发的,在餐厅的情况下,可能是早餐、午餐、下午茶或晚餐。但是,有时客户可能会要求不同的东西。如果一个用餐者进来并要一个汉堡,里面有薯条、土豆泥、吐司、意大利面和蛋奶冻(我希望这不是任何菜单上的项目),BAP 认为顾客永远是对的并允许这样做。为了限制这些情况,公开与上层profile支持的用例相对应的单个 PAC 记录可能会有所帮助。在这个餐厅类比中,这将是一天中不同时间的不同菜单。

在状态机中移动涉及 BAP 发出命令和 ASCS 响应的相互作用。与其孤立地详细介绍 ASCS,不如查看设置流时交互的实际过程更有用。

7.3 BAP – Basic Audio Profile

ASCS 描述了 ASE 的状态,但没有描述使用它们的过程,因为它是驻留在server上的服务。它是acceptor上每个音频流endpoint 当前状态的声明。要执行使我们通过 ASE 状态机以配置 ASE 并启用 CIS 的转换,我们需要移动到定义client(initiator)行为的基本音频profile。 BAP 为单播和广播定义了这些过程,CAP 将它们捆绑在一起。在本章中,我们将把自己限制在单播过程中。在下一章中,我们将对广播做同样的事情。

设置源 ASE 本质上是相同的过程,但有一个额外的状态,我们将在最后介绍。

7.3.1 在 ASE 状态机中移动

在 ASE 状态机中移动使用标准过程。发起方向接收方的 ASE 控制点特征发送命令,指定要执行的控制操作(即,它希望 ASE 转换到哪个状态,或者需要更新哪个状态)。该命令指定该命令应用于哪些 ASE 或哪些 ASE 以及该特定状态转换的参数。

该命令采用表 7.11 中所示的形式,并包括一组针对每个状态的操作特定参数。在完成状态机配置过程时,我们将查看每组特定于操作的参数。

FieldSize (Octets)Description
Opcode1Control Point Operation for the next state or update, as shown in Table 7.10).
Number of ASEs1Total number of ASEs included in this operation
ASE_ID[i]1The IDs of those ASEs
Operation specific parametersVariesA list of parameters for each of the [i] ASEs
Table 7.11 Basic structure of ASE Control Point command operations for an Initiator

在每个阶段,Initiator 都知道Acceptor的能力。只要它不请求acceptor提供的功能之外的功能,initiator就可以期望acceptor遵守其所有 ASE 控制点命令的值。一旦接收到每个 ASE 控制点命令,acceptor就会以 ASE 控制点特征通知进行响应,指示命令中包含的 [i] 个 ASE_ID 中的每一个是否成功,如表 7.12 所示。

FieldSize (Octets)Description
Number of ASEs1Total number of ASEs included in this operation
ASE_ID[i]1The IDs of those ASEs
Response_Code[i]10x00 if successful, otherwise an error response code from Table 5.1 of ASCS
Reason[i]1An extended reason code from Table 5.1 of ASCS. 0x00 indicates success. Other codes provide reasons where the operation has failed.
Table 7.12 ASE Control Point characteristic format as notified to its Client

如果其中任何一个被拒绝或有错误,则会有一套全面的错误响应通知Initiator ,以便它可以重试。请注意,所有这些操作都是针对数组[i] ASE。它们可以作为每个 ASE 的单独命令发送,但将每个接受器的所有 ASE_ID 包含在一个操作中会更有效。

假设没有问题,Acceptor 然后继续使用 Initiator 在其 ASE 控制点命令中提供的值更新其所有 Sink ASE 和 Source ASE 特征的状态。如果这导致任何 ASE 发生变化,Acceptor 将通知每个已更改的 ASE 的新值。

由于 ASE 控制点命令的目的是通过更改其状态或更新参数值来实现对 ASE 的更改,因此initiator将期待这些通知。但是,并非所有 ASE 都需要在每个 ASE 控制点操作中进行转换或更新。这意味着与同一 Initiator 相关联的 Acceptor 上的不同 ASE 可能处于不同的状态。如果有疑问,Initiator 应该阅读他们的 ASE 特性。 (如果使用了 CAP Audio Streaming 过程,则不应该出现这种情况,因为这需要在继续执行下一个命令之前将所有 Acceptor 转换到相同的状态。但是,即使在这里,某些 ASE 也可能不在 Enabled 或流状态(如果它们被配置为“备用”ASE 以供将来使用,我们将在第 7.6 节中介绍。)

图 7.6 显示了该过程的简化序列图。相同的过程适用于 Sink ASE 和 Source ASE。
在这里插入图片描述
此过程的巧妙(或复杂,取决于您的观点)部分是 ASE 控制点命令中的参数以及 Sink ASE 和 Source ASE 特性在您完成流建立过程时对于每个状态都是不同的,提供initiator下一次操作所需的信息。前几个操作中的不同参数允许Initiator 了解 ASE 的所有功能并收集设置 CIG 及其组成 CIS 所需的信息。

所有initiator的操作都具有相同的基本格式,如表 7.9 所示,但特定于状态的 ASE 参数随每个 ASE_State 而变化。 ASE 特性通知的 ASCS 表 4-2 至 4-5 和 ASE 控制点命令的第 5.2 – 5.6 节中定义了各个参数集。

Initiator 可以使用其 ASE 控制点操作命令配置多个 ASE,但每个配置的 ASE 都会独立通知其状态。例如,如果 Initiator 为耳机启用四个 ASE - 单独的 Sink ASE 用于左右立体声,两个 Source ASE 用于每侧的麦克风,它将收到一个更新 ASE 控制点特性的通知和四个独立的通知来自两对 Sink 和 Source ASE。

通过 ASCS 状态机的每个步骤都被定义为 BAP 中的特定过程。在下一节中,我们将通过这些来了解该过程是如何工作的。

7.4 配置 ASE 和 CIG

想要建立连接的Initiator ,无论是响应用户操作、外部事件还是来自Acceptor的请求,都需要从确定用例中涉及的所有Acceptor的能力开始。假设这是设备第一次连接,并且没有缓存任何内容,那么 Initiator 有多种选择来确定 Acceptor 的功能,这取决于 Initiator 是否只需要 BAP 规定的基本功能,是否有来自另一个规定的功能上层profile,这意味着它也需要遵循 CAP,或者它是否希望使用可选或专有功能。这些选项如表 7.13 所示。在随后的连接中,可能会有关于 Acceptor 能力的缓存信息,允许 Initiator 跳过这些步骤。

Initiator ActionResult
Discover Sink PACAcceptor can receive unicast audio with BAP mandatory settings
Discover Sink Audio LocationsAcceptor can receive unicast audio with BAP mandatory settings
Discover Sink ASEAcceptor can receive unicast audio with BAP mandatory settings
Discover Source PACAcceptor can transmit unicast audio with BAP mandatory settings
Discover Source Audio LocationsAcceptor can transmit unicast audio with BAP mandatory settings
Discover Source ASEAcceptor can transmit unicast audio with BAP mandatory settings
Discover Profile or ServiceAcceptor supports additional mandatory requirements
Read Sink PACDiscover the Acceptor’s capabilities for reception
Read Source PACDiscover the Acceptor’s capabilities for transmission
Table 7.13 Options for an Initiator to determine an Acceptor’s capabilities

假设我们正在处理 TMAP 或 HAP,并且想要连接到左右一对acceptor。发现至少有一个 Acceptor 支持 HAP 或 TMAP,通过发现它们的服务 UUID,Initiator 知道所支持的强制编解码器配置和 QoS 设置,因此它可以直接跳转到 CAP 并运行 CAP 连接过程非绑定设备 [CAP 8.1.2] 进行连接。Initiator 将确定第一个耳塞是否是协调集的成员,并且在我们的示例中,然后将运行 CAP 过程序言 [CAP 7.4.2],与该集中的两个设备绑定。完成后,它可以使用 CAP Unicast Audio Start 程序 [CAP 7.3.1.2] 开始建立连接的主要业务。这告诉Initiator 逐步完成底层 BAP 过程。

首先,Initiator 需要发现每个 Acceptor 上的所有 Sink 和 Source ASE,并确认每个 Acceptor 至少有一个 ASE,支持它要设置的每个音频流的正确方向。它还应该检查 PAC 特性以确保acceptor能够支持它想要使用的设置。这些过程在 BAP 中的音频角色发现过程 [BAP 5.1]、音频能力发现过程 [BAP 5.2] 和 ASE_ID 发现过程 [BAP 5.3] 中进行了描述。

音频角色发现和 ASE_ID 发现都是强制性的,因为除非您知道有合适的 ASE 可以连接,否则您无法继续。音频Context发现 [BAP 5.4] 是可选的,但如果Initiator 想要使用可选设置,则它是必需的。

BAP 旨在提供一种互操作性的回退级别,这将允许每个 Initiator 能够与任何具有合理音频质量的 Acceptor 建立音频流,以确保它们始终能够连接。如果initiator只是使用 BAP 的强制设置或它已经发现acceptor支持的profile,它可能有足够的信息来跳过这个阶段。同样,如果连接请求来自 Acceptor,无论是直接还是通过 Announcement,它可能已经提供了此信息。

下一步是为每个 ASE 配置编解码器。在此之前,Initiator 应该通过使用 Supported_Audio_Contexts 过程 [BAP 5.4] 和 Available_Audio_Contexts 过程 [BAP 5.5] 检查Acceptor的 Supported_Audio_Contexts 和 Available_Audio_Contexts 特性来检查每个 ASE 是否可以支持预期的用例。这些在第 7.1.5 节中进行了描述。

7.4.1 BAP 编解码器配置过程

假设满足必要的 Sink 和/或 Source ASE 要求,Initiator 将通过在每个 Acceptor 上配置每个 ASE 来开始设置等时流。它通过使用 BAP 编解码器配置过程 [BAP 5.6.1] 来做到这一点,其中它使用 Config_Codec 操作码 0x01 写入 ASE 控制点特性,以便将每个 ASE 移动到编解码器配置状态。 Initiator 已经确定了支持哪些编解码器配置,因此它现在为其当前应用程序选择所需的配置并将其连同目标延迟和 PHY 一起发送。该操作的参数格式在 ASCS 的表 5.2 中定义,并在表 7.14 中进行了总结。
在这里插入图片描述
这里有很多要点需要强调。首先是这些参数不需要对于每个音频流都相同。使用双向 CIS,参数,甚至 PHY 和编解码器,对于每个方向都可能不同。在大多数情况下,它们不是,但如果您在一个方向上流式传输音乐并使用返回方向进行语音控制,它们很可能是。目前,大多数profile都要求使用 LE 2M PHY 运行LE audio 。

第二个是这些参数中的前两个以“Target”为前缀,是建议。 Acceptor 将使用这些建议来选择它认为最能满足要求并适合其当前状态的 QoS 参数,然后返回这些选择以响应此命令。

相反,Codec ID 和 Codec Specific Configuration 参数是事实陈述,是 ASE 使用特定值的指令。编解码器配置通常基于正在使用的上层profile,它建立在 BAP 中指定的强制选项之上。我们在第 5 章(编解码器和 QoS)中查看了 BAP 和其他profile定义的强制和可选 QoS 配置。在大多数情况下,发起方将选择这些预定义配置之一,尽管它也可以使用顶层profile中定义的附加编解码器的设置,连同其推荐的 QoS 设置,或制造商特定的编解码器。它也可以组成自己的配置,尽管这样做存在互操作性差的风险。预定义的配置已经过大量测试,以确保它们运行良好,并且应该始终是首选选项。

实施者应注意,有两种听起来非常相似的编解码器特定 LTV 结构。首先,Codec_Specific_Capabilities LTV 结构用于 PAC 记录,通常表示一系列能力。第二,Codec_Specific_Configuration LTV 结构用于 Codec Configuration 操作(如上所述),用于单个特定配置。各个参数的语法略有不同。

在整个过程中,设备会在一定程度上相互跳舞,提出建议,以便对方可以提供最适合其当前资源状态的信息。这不是真正的协商——最好将其描述为知情枚举,允许发起方填充命令以发送到其controller以配置每个 CIS。即便如此,其 HCI 命令中的一些参数也是建议,controller对如何配置 CIG 拥有最终决定权。

需要注意的第三点重要的一点是,虽然 Acceptor 通过其 PAC 记录通知它可以支持的编解码器参数的范围,但 Initiator 会写入特定的值,这些值定义了它将如何配置编码的音频流。其中一些在 Acceptor 发送的 Supported settings 和 Initiator 写入的实际设置中定义了不同的值。例如,正如我们在上面看到的,Supported_Sampling_Frequency LTV 是一个位域,而 Sampling_Frequency LTV 是映射到采样频率的特定值。因此,如果 ASE 仅支持 16kHz,Acceptor 将通知值 0x04。作为响应,发起方将通过写入 0x03 配置 ASE 编解码器以支持 16kHz 采样。但是,回到这个过程…

获得有关 ASE、它们的功能和Availability的信息后,Initiator 可以发出一个操作码为 0x01 的无响应写入命令,其中包括它想要在acceptor上配置的所有 ASE_ID 的数组,它可以涵盖两者方向。 Acceptor 将通过更新然后通知其 ASE 控制点特征来响应,包括适当的响应代码(如果正常,则为 0x00)。然后,Acceptor 将所有指定的 ASE 转换为 Codec Configured 状态。一旦完成,Acceptor 将通知每个 ASE 的新状态,包括以下特定于状态的参数(总结在表 7.15 中),这些参数在 ASCS 的表 4.3 中进行了描述。

FieldDescription
FramingSupport for framed or unframed ISOAL PDUs
Preferred PHYA bitfield of values. Normally includes 2Mbps
Preferred Retransmission Number (RTN)How many times packets should be retransmitted
Maximum Transmit LatencyThe maximum allowable delay for Bluetooth transport
Presentation Delay Min & MaxSupported range of Presentation Delay
Preferred Presentation Delay Min & MaxPreferred range of Presentation Delay
Codec ConfigurationThe codec configuration for this ASE
Table 7.15 Notified parameters following a Config_Codec opcode (Table 4.3 of ASCS)

这结束了 BAP 编解码器配置过程,并将我们转到 QoS 配置过程 [BAP 5.6.2]。

7.4.2 BAP QoS 配置过程

在 Codec 配置过程结束时,Initiator 的 Host 会将每个 Acceptor 在 Codec 配置过程结束时通知的配置参数与其当前应用程序的要求进行比较,并在它被告知了什么。

在发出 Config QoS 命令之前,发起方最好使用 LE Set CIG Parameters HCI 命令将这些参数发送到其controller。这将确认可以支持所选参数集。请记住,这些是与用例相关的建议,它们会通知controller中的调度算法。controller选择的实际值可能略有不同。该 HCI 命令中使用的参数如表 7.16 所示。该命令的完整详细信息在第 4 卷 E 部分第 7.8.98 节的核心中。

正如我们在第 4 章中看到的,应用程序不能为链路层强制指定特定值。重申这里发生的事情,Initiator 和Acceptor交换了信息,允许Initiator 确定将什么放入其 HCI 命令中,以指示核心调度最能满足应用程序要求的 CIS。 (蓝牙实现使用 HCI 命令进行测试以检查它们是否兼容,但它们不需要在生产产品中公开。芯片和堆栈供应商可能会提供替代 API 来提供此功能,但了解 HCI 命令有助于演示这个过程是如何工作的。)
在这里插入图片描述
在表 7.16 中,以斜体突出显示的参数是对controller的建议,它可以选择忽略。

在 LE Set CIG 参数 HCI 命令(表 7.16)中需要两个值,它们不是来自 ASE 配置过程。第一个是 Worst_Case_SCA,它是所有 Acceptor 中最坏情况下的睡眠时钟精度。Initiator 需要通过在发出命令之前请求每个设备的睡眠时钟精度的当前值来确定这一点,通常使用 LE_Request_Peer_SCA HCI 命令。

第二个是Packing参数,决定CIS事件是顺序发送还是交错发送。如果设置为 0,它们将是连续的;如果设置为 1,它们将被交错。

通常,framed参数值设置为 0,以便controller可以决定,但某些profile(例如 HAP)可能会要求在某些情况下将其设置为 1,以强制它们被framed。 BAP 表 5.2 中为单播音频流推荐的 QoS 设置表明,除了那些具有 44.1kHz 采样频率的应该被framed的之外,它们都应该是unframed的。

在这个阶段,controller不会通知Initiator 或Acceptor的host它选择的值——这些信息将在 CIS 建立时传送。相反,发起方的host只确认可以安排其请求的配置,以及每个 CIS 的连接句柄。

一旦接收到 HCI_Command_Complete 事件,确认 CIS 可以被调度,Initiator 应依次向其每个Acceptor发送操作码设置为 0x02 的 ASE 控制点操作命令,操作特定参数在 ASCS 表 5.3 中定义如下表 7.17 所示。这会将 ASE 移动到 QoS 配置状态。发起方在 Config QoS 命令中使用的值复制了它在其 HCI LE_Set_CIG_Parameters 命令中使用的参数值。
在这里插入图片描述
Presentation Delay 是唯一不包含在 HCI LE Set CIG Parameters 命令中的参数;相反,它被直接发送到 Acceptor。在几乎所有应用中,Presentation Delay 的值对于所有 Sink ASE 都是相同的。每个 Sink ASE 的 Presentation Delay 值相同的原因是这决定了音频将被呈现的点。对于耳塞和助听器,这总是同时发生的。在某些情况下,例如在会议室或礼堂中有多个扬声器时,可能需要分配不同的值以应对与他们在房间中的相对位置相关的延迟,但这不是常态。

如果有一个或多个源 ASE,它们可能使用与接收 ASE 值不同的Presentation Delay值,尤其是因为作为Presentation Delay一部分的总 LC3 编码时间明显大于解码时间(大约 13 毫秒,而不是 2 毫秒)。因此,需要更多时间来包含该编码。但是,所有源 ASE 通常会使用彼此相同的值。

发起方为呈现选择的Presentation Delay值应在接收器 ASE 公开的首选Presentation Delay范围内,而捕获值应在源 ASE 公开的范围内。这些值不应超出acceptor集为每个方向公开的 Max 和 Min 值的公共范围,理想情况下应在首选 Max 和 Min 值的范围内(参见表 7.15)。如果Context类型是«Live»,它应该使用最低的公共最小值。

和之前一样,发起方在无响应写入命令中发送这些信息,之后它会收到更新的 ASE 控制点特性的通知,确认每个 ASE 已移动到 QoS 配置状态,然后是每个 ASE 的更新的 ASE 特性的通知。日月光。这些通知中的参数反映了在之前的 ASE 控制点操作中设置的值:
在这里插入图片描述
再重复一遍,Initiator 应该在进入下一个状态之前,为它打算在所有 Acceptor 上使用的所有 ASE 逐步检查每个状态,即,它将它们全部带到 Codec 配置状态,然后全部到QoS 配置状态等。这纯粹是常识,因为 Initiator 需要从所有这些获取信息,以确保它为跨所有 Acceptor 工作的 ASE 设置配置参数。但是,可以肯定的是,CAP 强制执行此操作。

如果多个 Acceptor 或 ASE 不提供一组一致的参数,则 Initiator 可以为其中一个或多个重复 Config 和 QoS 配置过程的每个步骤,包括从 QoS 配置状态返回到 Codec 配置状态。然而,期望这个过程通常是一个单步过程,只对每组 ASE 执行一次,因为如果它保持所有状态变化同步,效率会更高。因此,处理步骤是:

  • Initiator 发送一个带有多个 ASE 的目标值和显式值的命令
  • Acceptor 通过通知其 ASE 控制点特性来确认所有这些 ASE 的新状态(可能包括故障代码)
  • Acceptor 使用 ASE 特性分别通知每个 ASE 的首选值。 (这是它说明已配置的内容及其对下一个配置步骤的偏好的地方。)

在任何时候,initiator都可以检查单个 ASE 特性。参数将指示 ASE 的状态,以及与该状态相关的值。如果 Initiator 在 Idle 状态下读取 ASE_ID,它将收到的唯一信息是 ASE_ID 和 ASE_State 值 0,表示 Idle 状态。读取 ASE 特征的最常见原因是在未收到预期通知时确认先前的 ASE 控制点操作。

当发起方的host向其controller发送 HCI LE 设置 CIG 参数命令时,它将 CIG 移动到其已配置状态。此时,Initiator 的host仍然可以修改 CIS 的属性或向 CIG 添加更多 CIS,方法是使用其数组结构为特定 CIS 重新发送 HCI LE Set CIG 参数命令。如果是这样,则需要使用 Config QoS 命令通过使用 ASE 控制点特性的数组功能写入 ASE 来更新相关的 ASE。

一旦所有 ASE 都处于 QoS 配置状态并配置了 CIG,我们就可以开始启用音频流。

7.4.3 启用 ASE 和 CIG

配置完所有 ASE 后,发起方将拥有指示其controller启用 CIG 和组成 CIS 所需的所有信息。 Acceptor 的 Host 知道 Isochronous Channels 的主要参数,尽管有些值仍然是临时的,因为实际的 RTN 值将取决于调度。如果controller还必须支持其他无线连接,它可能会决定妥协以在不同的无线连接之间分配空中传输时间,并设置一个低于其host请求的值。在每个 CIS 建立时,设置将在链路层级别进行配置,并通知给 Initiator 和每个 Acceptor 的各自host。

initiator现在可以调用 BAP 5.6 中定义的启用 ASE 过程,方法是使用表 7.19 中显示的参数写入每个acceptor的 ASE 控制点特性,操作码设置为 0x03(启用)。从此时起,发起方不能更改 CIG、CIS 或 ASE 配置,但音频流metadata除外。

ParameterDescription
Number of ASEsTotal number of ASEs to be enabled (i)
ASE_ID [i]The specific ASEs which are being enabled
Metadata Length [i]Length of metadata for ASE [i]
Metadata [i]LTV formatted metadata. This is most commonly the Streaming_Audio_Contexts and CCID_List LTV structures, but can include other LTV structures.
Table 7.19 State Specific Parameters for the Enabling operation – Opcode 0x03 (Table 5.4 of ASCS)

CAP 要求启用操作中的metadata包括 Streaming_Audio_Contexts,并为每个单播音频流设置正确的值。如果存在与音频流相关的内容控制过程,则启用命令中的metadata还必须包含 CCID_List LTV 结构。 [第 7.3.1.2.6 章]

每个acceptor将通知其 ASE 控制点特性,将其 ASE 移动到启用状态,然后依次通知 ASE 控制点命令中指定的每个 ASE 的 ASE 特性,返回它们的 CIG 和 CIS ID,以及任何由 Initiator 写入的metadata,如表 7.20 所示。
在这里插入图片描述
ASE 的metadata值只能由发起方设置或更新。Acceptor不能对这些进行更改,即使它充当音频源。 Acceptor 可以随时更新其 Available_Audio_Contexts 值,但这些值不会出现在 ASE metadata中。它们也不会导致当前流的终止。 Available_Audio_Contexts 中的任何更改仅用于后续连接尝试。

现在 ASE 处于启用状态,是时候启用所需的 CIS 并将它们耦合到 ASE。请记住第 4 章中的内容,并非 CIG 中包含的每个已配置 CIS 都需要建立,因为Initiator 可以配置 CIS,当其需求变化时,它可以交换进出。Initiator 通过从核心调用连接的等时流中心建立过程来启用它所需的 CIS [第 3 卷,C 部分,第 9.3.13 节]。链路层将向Acceptor生成一个 CIS_Request,Acceptor使用来自核心的等时流外设建立过程建立 CIS [第 3 卷,C 部分,第 9.3.14 节]。此时,Initiator 将开始传输长度为零的 PDU 数据包。如果是双向 CIS,则需要同时建立 Sink 和 Source ASE。

在这一点上,ASE 的行为有一个条件,实现者需要注意这一点。如果 CIS 在启用操作之前存在,则不会通知从启用状态到流式处理状态的转换。相反,Acceptor 自动将 ASE 转换到其 Streaming 状态,而不需要 Initiator 编写 Streaming 命令。如果 Acceptor 正在重用现有配置并且原始 CIG 从未被禁用,则最有可能发生这种情况。

正如我们在第 4 章的 CIG 状态机中看到的,一旦启用了 CIG,就不能更改 CIS 配置,因此对编解码器配置、QoS 参数或Presentation Delay的任何更改都需要终止 CIG 和配置过程重新启动。单个 CIS 可以断开连接或恢复(使用 LE 创建 CIS 命令),但只有它们的metadata才能在它们处于启用或流式传输状态时更新。

7.4.4 音频数据路径

Isochronous Streams 现在已经启动并运行,但我们还没有连接任何音频数据——Isochronous Channels 只是传送空数据包。下一步(如果尚未完成)是为每个 ASE 连接一个数据路径,它使用音频数据路径设置过程 (BAP 5.6.3.1),而后者又使用 LE Setup ISO 数据路径 HCI 命令。

LE audio 为音频数据路径和编解码器的位置提供了很大的灵活性。编解码器可以驻留在host或controller中,音频数据可以来自 HCI,或者更典型的是通过 PCM 或供应商专有路由。
在这里插入图片描述
图 7.7 显示了三种最常见的数据路径配置,表明编解码器可以在 Host 或 Controller 中实现。音频通常通过 PCM 接口从编解码器路由,但如果在host中编码,它也可以通过 HCI 传输。为了设置每个数据路径,Initiator 和 Acceptor 都将使用 LE Setup ISO Data Path HCI 命令将在 Config Codec 状态期间写入的编解码器配置绑定到每个 CIS 的连接句柄,指定方向取决于它是否是 Source 或 Sink ASE。 Initiator 和 Acceptor 中的数据路径配置可能不同,因为编解码器位置和数据路径实现通常取决于所使用的特定芯片组。由于数据路径设置在每个设备内部,因此这是一种实现选择。这种详细程度通常对应用程序开发人员隐藏在更通用的 API 之下,但了解配置过程的每个阶段发生的情况很有用。

到目前为止,该过程对于接收器和源 ASE 都是通用的。现在这两个过程发生了分歧。它们在状态机中仍然在同一条路径上,但是命令的顺序有所不同。

对于一个 Sink ASE,一旦 Acceptor 成功建立了它的数据路径,它可以自主地将 ASE 移动到 Streaming 状态,然后将每个 Sink ASE 特性通知给 Initiator,ASE 状态代码设置为 0x05(Streaming)。一旦收到此通知点,initiator就可以开始将音频数据包流式传输到该 ASE 接收器。
在这里插入图片描述
图 7.8 显示了一个非常简化的用于建立 Sink ASE 的消息序列图,显示了整个序列和 Acceptor 到 Streaming 状态的自主转换。 BAP 第 5.6.3 节提供了更详细的 MSC。

对于源 ASE,Acceptor 需要等待 Initiator 确认它已准备好从该 ASE 接收数据。一旦它从acceptor接收到 ASE 特征通知,并且一旦它准备好传输音频数据,initiator将写入该 ASE 的 ASE 控制点特征,操作码设置为 0x04(接收开始就绪)。 (注意,Sink ASE 不需要包含在该命令的 ASE 数组中,因为它们会独立移动到 Streaming 状态。)此时,Acceptor 会将 Source ASE 转换为 Streaming 状态,通知其 ASE特征并开始音频流。

源 ASE 对应的 MSC 如图 7.9 所示。这里,Initiator 需要向 Acceptor 的 ASE 控制点特性发出 Receiver Start Ready 命令,以启动音频数据包传输。
在这里插入图片描述

7.4.5 更新单播metadata

在 Enabling 或 Streaming 状态下,Initiator 可以通过使用 0x07(更新metadata)[BAP 5.6.4] 的操作码写入 ASE 控制点来更新任何 ASE 的metadata。这是将 ASE 重新用于不同的音频应用程序的便捷方式,而无需拆除和重新建立任何音频流。

这在 CAP 单播音频更新过程 [CAP 7.3.1.3] 中进行了描述,允许重用 ASE,保持其当前配置,但更改Context类型和 CCID_List metadata。一个典型的应用程序是使用相同的流从电话转移到同一部电话上的音乐播放器。存在固有限制,即编解码器配置无法更改。另一个问题是电话通常是双向的,而音乐流是单向的。但是,在配置过程中,可以配置足够多的 ASE 来应对这种情况。在用例的转换点,initiator可以禁用和启用 ASE,直到它拥有所需的已配置 ASE 数量,并在此过程中更新它们的metadata。请注意,在双向 CIS 的情况下,ASE 可能被禁用,但 CIS 将保持启用以支持另一个方向及其 ASE。这是一个很好的例子,说明如何通过增加音频流的灵活性来重新利用和重用蓝牙经典音频多profile问题。

7.4.6 结束单播流

结束单播流的过程是 Sink 和 Source ASE 状态机分歧的地方。我们将在下一节中介绍源 ASE。不同之处在于源 ASE 具有禁用状态,而接收器 ASE 没有。

要停止流向接收器 ASE,ASE 需要使用 CAP 单播音频停止过程 [CAP 7.3.1.4] 转换回 QoS 配置状态。这调用了 BAP 禁用 ASE 过程 [BAP 5.6.5],其中initiator使用 0x05(禁用)命令写入 ASE。此时,Initiator 停止向 ASE 发送音频数据。如果 CIS 是双向的并且源 ASE 未被禁用,则发起方将继续发送空 PDU 以允许接收方返回其音频数据。

此时不会自动禁用关联的 CIS。如果Initiator 希望删除它,它应该使用 HCI_Disconnect 命令 [Core Vol 4, Part E, 7.1.6]。由于禁用接收器 ASE 只会将其移动到 QoS 配置状态,因此可以在稍后通过将启用操作码写入 ASE 控制点特性来重新建立 ASE。如果 CIS 已使用 HCI Disconnect 禁用,它仍然可以使用 HCI LE Create CIS 命令恢复。

如果不打算重用 ASE,可以通过执行 BAP 释放 ASE 过程 [BAP 5.6.6] 将其移至释放状态。一旦 ASE 处于 Releating 状态,Acceptor 就会自动将其转换到 Idle 状态,或者,如果它想简化下一个 ASE 配置周期,它可以通过将编解码器配置返回到 Codec 配置状态来缓存编解码器配置。

一旦与 CIS 关联的所有 ASE 都被禁用,发起方可以禁用仍然启用的任何 CIS 并拆除关联的数据路径。当 CIG 中的所有 CIS(跨所有acceptor)都已禁用时,应将 CIG 移至非活动状态。

7.4.7 源 ASE 状态机

源 ASE 的行为略有不同,因为我们需要initiator的确认以确保干净的转换。这引入了禁用状态。它仅用于源 ASE,并显示在图 7.10 的源 ASE 状态机中
在这里插入图片描述
对于 Source ASE,Acceptor 需要 Initiator 确认 Initiator 已准备好停止接收音频数据。 Acceptor 可以自动停止流式传输,但 Receiver Stop Ready 命令会导致流式传输完全终止。如果有重用 ASE 的潜在需求,这一点很重要。在通知它处于禁用状态的事实后,Acceptor 应该等待来自 Initiator 的命令,告诉它停止流式传输并转移到 QoS 配置状态。从那里,源 ASE 可以被移动到释放状态,但如果它这样做了,那么如果不让 ASE 再次通过状态机,就不可能重用 CIS。

一旦处于释放状态,无论是通过从接收器 ASE 的流状态直接转换、从源 ASE 的禁用状态直接转换,还是从任何一个的 QoS 配置状态释放,Initiator 和Acceptor都应该拆除他们的数据路径和终止CIS。 Acceptor 可以选择转换到 Idle 或 Codec Configured 状态,这两种操作都是自主执行的。如果 CIS 是双向的,则在接收器和源 ASE 都处于释放状态之前不应终止它。当最终的 CIS 终止时,CIG 从 Inactive CIG 状态移动到 No CIG 状态。

7.4.8 ASE 上的自主操作

我们已经看到,Acceptor 可以自主地将 Sink ASE 从 Enabling 状态转换为 Streaming 状态,并从 Releating 状态转换为 Idle 状态或 Codec Configured 状态。这些不是Acceptor可以自主行动的唯一场合。除了表 7.21 中显示的转换之外,所有状态机转换都可以由 Acceptor 或 Initiator 执行。然而,在大多数情况下,在状态机周围移动是如上所述执行的。

ASE TypeCurrent StateNext StateInitiating Device
Sink and SourceCodec ConfiguredQoS ConfiguredInitiator
Sink and SourceQoS ConfiguredQoS ConfiguredInitiator
Sink and SourceQoS ConfiguredEnablingInitiator
SourceDisablingQoS ConfiguredInitiator
Sink and SourceReleasingCodec ConfiguredAcceptor
Sink and SourceReleasingIdleAcceptor
Table 7.21 ASE transitions which are confined to Initiator or Acceptor actions

7.4.9 ACL 链路丢失

如果 Acceptor 和 Initiator 之间的 ACL 链接丢失,则该 Acceptor 的所有 CIS 都将断开连接。在 CIG 中涉及其他 Acceptor 的情况下,Acceptor 应该将所有与丢失的 ACL 链接关联的 ASE 移动到 QoS 配置状态,以便在链接返回时可以重新启用 CIS。 Acceptor 会通知这种状态变化,尽管 Initiator 是否会收到通知是个问题。

由于Acceptor不一定知道任何其他Acceptor的存在,他们可能不知道 CIG 是否仍处于活动状态或流向其他Acceptor。如果他们在链路丢失后没有收到重新连接请求,他们可能会使用特定于实现的超时来将他们的 ASE 恢复到空闲状态。在稍后重新连接 ACL 链接时,发起方应读取该接受方的 ASE 特性以检查其状态。如果由于超时而从 QoS 配置状态中释放,发起方通常需要拆除并重新建立整个 CIG。请记住,Initiator 和 Acceptor 之间存在不对称性——ASE 状态机位于 Acceptor 上,而 CIG 状态机位于 Initiator 上。 Acceptor 永远不会知道 CIG 状态;它是具有 ACL 连接状态全局视图的Initiator 用来驱动 ASE 状态的东西。

7.5 处理丢失的Acceptors

在开始配置 ASE 之前,CAP 要求Initiator 连接到目标协调集中的所有Acceptor。在现实世界中,有时并非所有这些都存在,因为其中一个已关闭、丢失或超出范围。在这种情况下,Initiator 应该继续设置它可以找到的协调集的成员。在这种情况发生之前等待多长时间,是否涉及用户反馈,以及发送到可用acceptor的音频通道的选择都是特定于实现的。 Initiator 应该继续搜索丢失的 Acceptor,并在发现它们时添加它们。

CIG 的性质是,一旦它处于活动状态,就无法配置其他 CIS。因此,如果 Initiator 只为它可以找到的 Acceptor 配置 CIS,那么,如果出现丢失的,并且没有为它们安排 CIS,它将不得不拆除 CIG,重新配置它并重新建立 CIS,这将破坏音频流

为防止音频中断,发起方可以为任何丢失的 ASE 使用缓存值调度 CIG。如果它稍后检测到丢失的acceptor的存在,它可以配置它们的 ASE,然后启用活动 CIG 中的关联 CIS,(因为它们已经被调度),并开始传输音频数据。 CAP 没有描述这个过程;除了 CAP 程序之外,它是通过使用 BAP 程序的功能扩展,但它可以带来更好的用户体验

7.6 预配置 CIS

存在类似的情况,即Initiator 知道Acceptor可能参与许多具有不同 ASE 配置的不同用例。一个常见的例子是流音乐(A2DP 的模拟),它只需要接收器 ASE 来启用 CIS 将音频从Initiator 传送到acceptor,但可能会被传入的电话中断,其中从麦克风返回音频流( s) 是必需的。为了使这种转换更快,initiator可以配置一组满足两种用例的 ASE,即两个 Sink ASE 和两个 Source ASE,这样当它想要在两个应用程序之间转换时,它需要做的就是启用或禁用源 ASE,而不是关闭所有内容并重新启动。

这样做的缺点是总是分配返回的等时流的空中传输时间,尽管它可能永远不会被使用。用于高可靠性的立体声 48_2_2 流占用了大约 63% 的空中传输时间。如果计划包含 32_2_2 返回流,则该值增加到 90%。相比之下,双向 32_2_2 流仅占用 41% 的空中传输时间。两个应用程序的延迟要求也存在差异。对于通常使用高可靠性 QoS 设置的音乐流媒体,48_2_2 流的整体延迟,以及 32_2_2 的返回仅超过 140 毫秒。这比使用双向低延迟 32_2_1 流获得的 56 毫秒要长得多。表 7.22 说明了不同 QoS 配置对双向流的空中传输时间和延迟的影响。
在这里插入图片描述
这意味着设计人员需要注意空中传输时间、QoS 和呼叫建立时间之间的权衡。做出这个决定通常取决于Initiator 中的其他空中传输时间资源需求。它说明了LE audio 的灵活性,但强调了与经典蓝牙音频profile相比,实施者需要更多地了解整个系统。

7.7 谁负责?

设计师的问题之一是决定“谁负责?”低功耗蓝牙音频的发展已经看到了一些强烈的意见;来自认为手机负责一切的手机制造商,以及认为需要赋予其产品更多自主权的扬声器和耳戴式耳机制造商,导致了Sink led Journey的概念。spec为两者提供了空间,但他们需要开发人员意识到一些后果。

看一个简单的例子很有用,它是一对耳塞,每个耳塞都有一个麦克风。电话制造商可能希望同时使用两者,因为这将允许他们处理两个音频流,从而产生更好的语音信号。另一方面,耳塞制造商可能更喜欢只使用一个,从而节省另一个耳塞的电池寿命。如果他们看到带有活动麦克风的电池开始下降,他们甚至可能希望能够在通话过程中交换正在使用的那个。

问题是,如何启用这些选项?假设耳塞之间存在通信,其中一个可以考虑不暴露其源 ASE,尽管这是一种蛮力方法,尤其是当手机可以通过读取 PAC 记录来推断其存在时。正如我们在上面看到的,Acceptor 应该为它能够支持的每个音频流公开一个 ASE,即使它可能无法在所有时间点都支持它。更好的方法是使用 PACS 中的 Available_Audio_Contexts 特性来指示server无法传输音频,并将 Available_Source_Contexts 设置为 0x0000(这是允许将所有Context类型位设置为零的少数情况之一。 )

如果Initiator (电话)可以看到每个耳塞都有一个可用的 Source ASE,那么它就可以有效地负责。它可能决定只选择一个(尤其是因为处理两个未按时间对齐的传入流并非易事,并且会增加其功耗)。如果它只想使用一个,它可以使用其他信息,例如检查每个耳塞的电池状态,来指导它选择麦克风。

如果它更智能,它可以查看通话期间是否有规律地重复短语,推断这意味着信噪比差,并添加第二个麦克风以尝试通过获得几分贝的信号来提高质量。同样,电话应用程序可以记录与特定人员通话的持续时间,并从该历史记录中推断出通话的可能长度、耳塞电池寿命,并使用它来决定要设置多少音频流和 QoS 设置这将使电池在预期的通话持续时间内存活下来。差异化的机会太多了!我怀疑这两种方法在短期内都不太可能,因为手机将继续将耳塞视为一种可以随意使用的资源。

另一方面,Sink led 旅程的支持者希望耳塞具有更多的决策能力。但是,这意味着它们具有相互通信的能力,这目前超出了范围(HAPS 中的预设本地同步除外)。如果这对决定他们只想在一个耳塞上使用麦克风,他们可以在他们之间决定哪一个会受到电池冲击,而另一个可以将其 Available_Source_Contexts 设置为 0x0000。 (他们可以在电池盒中执行此操作,因此不必使用单独的 sub-GHz 无线电链路。)

这种方法的优点是电话知道源 ASE 对两者都存在,因此它可以在 CIS 中配置流。它无法为将 Available_Source_Contexts 显示为 0x0000 的耳塞启用它,因为耳塞将在配置编解码器阶段拒绝它。但是,发起方可以对其进行调度,因为它可以在 HCI LE 设置 CIG 参数命令中放置它想要的任何内容。尽管我们已经看到该过程通常使用initiator从acceptor接收到的信息,但它可以使用缓存或假设的值来丢失acceptor或 ASE。这意味着,如果在某个时候需要更换麦克风,这可能会发生。否则,Initiator 将需要拆除 CIG 并重建它,从而导致呼叫中断。 (这不应该终止调用,因为流的丢失不会导致 TBS 状态机发生任何变化,但这不是一个好的用户体验)。

这里的重点是 PACS 和 ASCS 特性允许对音频流的设置方式拥有惊人的所有权。Initiator 可以单方面采取行动,但这可能会影响设备的工作情况。为了获得最佳性能和用户体验,设计人员需要了解所提供的选项以及如何使用它们。

--oOo--

设置单播音频流的方法到此结束,现在我们可以将注意力转向广播。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值