音频信号处理

概览

信号处理接口可供音频复合驱动程序使用。此接口 SignalProcessing 是 Composite 协议使用的一种 FIDL 协议,用于提供音频信号处理功能。

SignalProcessing 协议旨在控制信号处理硬件及其拓扑。我们将处理元素 (PE) 定义为音频驱动程序提供的音频数据处理逻辑单元,并将拓扑定义为 流水线中 PE 的排列方式以及与其关联的控制。

SignalProcessing 协议允许硬件供应商实现具有稳定应用二进制接口 (ABI) 的驱动程序,并允许系统集成商使用这些接口进行运行时配置,从而根据系统或产品要求配置驱动程序以实现不同的性能。

SignalProcessing 协议构成 Reader 信号处理协议。仅检索信息的信号处理方法属于 Reader 协议,其余方法属于 SignalProcessing 协议本身。这种分离使得此接口的客户端能够将 Reader 信号处理协议组合到自己的协议中,前提是它们需要向自己的客户端提供只读的功能子集。

SignalProcessing 协议和关联定义是 fuchsia.hardware.audio.signalprocessing FIDL 库的一部分。

拓扑

每个驱动程序都可以有自己的拓扑。驱动程序可以根据特定配置或产品的需要,从应用中抽象出其他驱动程序公开的拓扑。请注意,虽然不是必需的,但可以将拓扑公开给应用,尤其是 audio_core。

注意:

  • 拓扑并非旨在完全描述每个 PE 的音频流水线状态/格式/配置。目的是描述客户端可以根据其知识、配置(例如来自元数据)和特定业务逻辑更改/重新排列的内容。
  • 如果驱动程序支持环形缓冲区,拓扑会包含一个或多个 RingBuffer 类型的处理元素(且仅当驱动程序支持环形缓冲区时才会包含)。
  • 如果驱动程序支持 DAI 互连,拓扑会包含一个或多个 DaiInterconnect 类型的处理元素(仅当驱动程序支持 DAI 互连时)。 *如果驱动程序支持数据包流,拓扑会包含一个或多个 PackeetStream 类型的处理元素(仅当驱动程序支持数据包流时)。
  • 拓扑必须包含至少一种此类元素。

处理元素

PE(在 fuchsia.hardware.audio.signalprocessing FIDL 库中定义为 Element)应是由特定驱动程序管理的硬件提供功能(但也可以像任何其他驱动程序功能一样在软件中进行模拟)。流水线由一个或多个 PE 组成,拓扑由一个或多个流水线组成。

我们将提供信号处理协议的服务器称为驱动程序。我们将功能的使用者(例如 audio_core 等应用)称为客户端。

基本操作

客户端负责请求并配置任何信号处理功能。 当服务器通过回复客户端的 GetElements 提供其 PE 后,客户端可以发出 WatchElementState 调用(请参阅挂起获取模式)来检索 PE 状态,并发出 SetElementState 来根据需要动态控制 PE 参数。例如,如需检索 type GAIN 的 PE 的 gain,客户端会发出 WatchElementState 调用,其中一个用于检索初始状态(驱动程序将回复客户端发送的第一个 WatchElementState),后续调用用于接收包含 gain 的 ElementState 的更新通知。同样,若要检索 type EQUALIZER 的 PE(在 bands_state 中由多个频段组成)的状态,客户端会发出 WatchElementState,以检索初始状态(驱动程序会回复客户端发送的第一个 WatchElementState),包括每个频段的 frequency 字段。

此外,在服务器通过回复客户端的 GetElements 提供其 PE 后,客户端可以使用 GetTopologies 方法请求可用的拓扑。如果 GetTopologies 返回了多个拓扑,则可以使用 SetTopology 选择要使用的拓扑,并使用 WatchTopology 观察对有效拓扑的更新。

GetElements

GetElements 允许选择性地获取所有 PE 的列表。例如,此方法可由客户端在抽象硬件编解码器的驱动程序上调用。一旦客户端知道 PE 列表,便可根据 PE 类型公开的参数配置 PE。

SetElementState

SetElementState 允许客户端使用 GetElements 返回的 ID 控制 PE 的状态。不同类型的 PE 可能向客户端公开不同的状态,SetElementState 参数 state 的类型因 PE 的类型而异。

WatchElementState

WatchElementState 允许客户端使用 GetElements 返回的 ID 监控 PE 的状态。不同类型的 PE 可能向客户端公开不同的状态,WatchElementState 参数 state 的类型因 PE 的类型而异。

PE 的 state 由可通过调用 SetElementState 由客户端直接更改的值组成,也可以间接更改(例如通过对其他 PE 调用 SetElementState),或者独立于客户端更改(例如由于插头检测变化)。

GetTopologies

GetTopologies 允许选择性地获取拓扑列表。例如,此方法可由驱动程序上抽象硬件编解码器的客户端调用。一旦客户端知道拓扑列表,客户端就可以配置服务器以使用特定拓扑。

SetTopology

SetTopology 允许客户端控制服务器使用的拓扑。一次只能选择一种拓扑。

WatchTopology

WatchTopology 允许客户端通过挂起的 GET 请求观察当前有效的拓扑 ID,并在拓扑发生更改时异步收到通知。

处理元素类型

GetElements 返回的 PE 支持多种不同类型的信号处理,这些处理由 PE 类型和参数定义。PE 类型定义了标准信号处理(例如 GAIN、DELAY、EQUALIZER 等)、供应商特定的信号处理(VENDOR_SPECIFIC 例如 SignalProcessing 协议中未定义的类型)以及用于构建多流水线拓扑的 CONNECTION_POINT(允许进行路由和混合定义,请参阅下文中的连接点)。

每个单独的 PE 可以有一个或多个输入通道和一个或多个输出通道。对于路由和混音,PE 可能会使输出通道数与输入通道数不同。

每个渠道(即处理的信号)中的数据可能会被 PE 更改。例如,如果流水线中有一个类型为 AGL 的 PE,该流水线包含一个 DAI_INTERCONNECT 元素,且该元素的 DaiFormat number_of_channels 设置为 2,那么客户端可以通过调用 SetElementState 并将 state started 设置为 true(如果 AGL Element 的 can_stop 为 true,则设置为 false),来启动或停止这两个渠道的 AGL(自动增益限制)。

如果未包含不同 PE 类型中的可选字段,则处理元素的状态不会因特定字段而发生变化。例如,如果 SetElementState 调用中的 EqualizerBandState 不包含可选的 frequency,则均衡器的频段频率状态不会更改。

特定于供应商的数据

ElementState vendor_specific_data 是一个可选参数,可针对任何处理元素指定。这样一来,处理元素就可以指定一个不透明对象,该对象可以作为 SetElementState 的一部分发送到驱动程序,也可以作为 WatchElementState 的一部分从驱动程序接收。

除了任何类型的不透明数据之外,类型为 VENDOR_SPECIFIC 的处理元素还允许驱动程序指定未在 SignalProcessing 协议中定义的类型,例如尚未标准化或不打算标准化且仅由特定供应商提供的类型。类型为 VENDOR_SPECIFIC 的处理元素在 TypeSpecificElement 和 TypeSpecificElementState 中指定了 vendor_specific 变体。此外,它还可以指定要使用 ElementState vendor_specific_data 参数发送到驱动程序或从驱动程序接收的不透明数据,就像任何其他处理元素类型一样。

拓扑

GetTopologies 返回的拓扑支持 GetElements 返回的 PE 的不同排列方式。GetTopologies 可以宣传一种或多种拓扑。

一种拓扑

如果仅通告一个拓扑,即 GetTopologies 返回一个包含一个元素的向量,则所有 PE 都属于此显式单管道。在这种情况下,顺序是明确的。例如,如果 GetElements 返回 2 个 PE:

  1. Element:id = 1,type = AUTOMATIC_GAIN_LIMITER (AGL)
  2. Element:id = 2,type = EQUALIZER (EQ)

由 GetTopologies 返回的 Topology 元素将列出 id 和 processing_elements_edge_pairs 向量,明确指明信号处理的执行顺序,在本例中:

  1. Topology:id = 1,processing_elements_edge_pairs = 包含一个元素的向量,其中 processing_element_id_from = 1,processing_element_id_to = 2。

此广告通过一个流水线宣传一个拓扑:

                +-------+    +-------+
Input signal -> |  AGL  | -> |  EQ   | -> Output signal
                +-------+    +-------+

在此拓扑中,流水线的开头(输入信号输入到流水线的位置)和结尾(输出信号从流水线输出的位置)是隐式的。

如果仅宣传一种拓扑,则内容仅供参考,因为客户端无法更改一种且唯一的拓扑的使用。

多种拓扑

如果通告了多个拓扑(即 GetTopologies 返回一个包含多个元素的向量),则 PE 可用于多种配置(即拓扑)。每种拓扑都会明确列出 PE 的数量及其顺序,也就是说,在这种情况下,顺序是明确的。 PE 的排列和顺序定义了流水线。

通过仅列出支持的特定 PE 排列和排序,服务器可以限制哪些流水线组合有效。

例如,如果 GetElements 返回 6 个 PE:

  1. Element:id = 1,type = AUTOMATIC_GAIN_LIMITER (AGL)
  2. Element:id = 2,type = EQUALIZER (EQ)
  3. Element:id = 3,type = SAMPLE_RATE_CONVERSION (SRC)
  4. Element:id = 4,type = GAIN
  5. Element:id = 5,type = DYNAMICS (DRC1)
  6. Element:id = 6,类型 = DYNAMICS (DRC2) 参数与 DRC1 参数不同。

由 GetTopologies 返回的 Topology 元素将列出每个拓扑的 id 和 processing_elements_edge_pairs,在此示例中:

  1. Topology:id = 1,processing_elements_edge_pairs =
    • processing_element_id_from = 3,processing_element_id_to = 2。
    • processing_element_id_from = 2,processing_element_id_to = 4。
    • processing_element_id_from = 4,processing_element_id_to = 5。
    • processing_element_id_from = 5,processing_element_id_to = 1。
  2. Topology:id = 2,processing_elements_edge_pairs =
    • processing_element_id_from = 2,processing_element_id_to = 4。
    • processing_element_id_from = 4,processing_element_id_to = 6。

这会公布两个拓扑,每个拓扑各有一个流水线:

                +-------+    +-------+    +-------+    +-------+    +-------+
Input signal -> |  SRC  | -> |  EQ   | -> | GAIN  | -> |  DRC1 | -> |  AGL  | -> Output signal
                +-------+    +-------+    +-------+    +-------+    +-------+

                +-------+    +-------+    +-------+
Input signal -> |  EQ   | -> | GAIN  | -> |  DRC2 | -> Output signal
                +-------+    +-------+    +-------+

连接点

类型为 CONNECTION_POINT 的 PE 允许:

  1. 在单个流水线中混合多个渠道。
  2. 混合来自不同流水线的多个渠道。
  3. 重复频道。
  4. 将单个流水线扩展为多个流水线(分散)。