音频信号处理

概览

信号处理接口可能会被音频复合驱动程序使用。此接口 SignalProcessingComposite 协议用于提供音频信号处理功能的 FIDL 协议。

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

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

SignalProcessing 协议构成了 Reader 信号处理协议。仅检索信息的信号处理方法属于 Reader 协议,其余方法属于 SignalProcessing 协议本身。通过这种分离,即使此接口的客户端需要向其客户端提供只读功能子集,也可以将 Reader 信号处理协议编入自己的协议中。

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

拓扑

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

注意:

  • 拓扑并不能完整描述每个 PE 内外的音频流水线状态/格式/配置。目的是描述客户端根据其知识、配置(例如,根据元数据)和特定业务逻辑可以更改/重新排列哪些内容。
  • 用于提供 Composite 协议的音频驱动程序的拓扑必须包含 ENDPOINT PE,以便为驱动程序支持的环形缓冲区和 DAI 互连提供 ID。

处理元素

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

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

基本操作

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

此外,在服务器通过回复客户端的 GetElements 提供其 PE 之后,客户端还可以使用 GetTopologies 方法请求可用拓扑。如果 GetTopologies 返回多个拓扑,则可以使用 SetTopology 选择要使用的拓扑。

GetElements

GetElements 允许选择获取所有产品专家的列表。例如,客户端可以在抽象出硬件编解码器的驱动程序上调用此方法。在客户端知道 PE 列表后,客户端就可以根据 PE 类型公开的参数来配置 PE。

SetElementState

SetElementState 允许客户端使用 GetElements 返回的 ID 来控制产品专家的状态。不同类型的 PE 可能会向客户端公开不同的状态,SetElementState 参数 state 的类型取决于 PE 的类型。

WatchElement

WatchElement 允许客户端使用 GetElements 返回的 ID 监控产品专家的状态。不同类型的 PE 可能会向客户端公开不同的状态,WatchElement 参数 state 的类型取决于 PE 的类型。

PE 的 state 由多个值组成,这些值可以由客户端通过调用 SetElement 直接更改,也可以以间接方式更改,例如通过在其他 PE 上调用 SetElement 来间接更改,或者由于插头检测更改等独立于客户端而更改。

GetTopologies

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

SetTopology

SetTopology 允许客户端控制服务器所使用的拓扑。任何时候都只能选择一个拓扑。

处理元素类型

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

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

产品专家可能会更改每个频道中的数据(即处理的信号)。例如,如果流水线中有一个类型为 AGL 的 PE,且该 PE 包含类型为 DAI_INTERCONNECTDaiFormat number_of_channels 设为 2 的 ENDPOINT,则可以通过调用 SetElementState 并将 state enable 设置为 true 或 false 的客户端为这 2 个通道启用或停用 AGL(自动增益限制)(这假设 AGL Elementcan_disable 设置为 true)。

如果未包含不同 PE 类型中的可选字段,则处理元素的状态不会就特定字段进行更改。例如,如果 SetElement 中的 EqualizerBandState 不包含可选的 frequency,则均衡器的频段频率状态不会更改。

供应商专属数据

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

除了任何类型的不透明数据外,VENDOR_SPECIFIC 类型的处理元素还允许驱动程序指定 SignalProcessing 协议中未定义的类型,例如,某种尚未标准的类型,或者不打算标准化并仅由特定供应商提供的类型。VENDOR_SPECIFIC 类型的处理元素不指定任何 TypeSpecificElement 参数,而是可以使用 ElementState vendor_specific_data 参数指定要与驱动程序发送或接收的不透明数据,就像使用任何其他处理元素类型一样。

拓扑

GetTopologies 返回的拓扑支持 GetElements 返回的 PE 的不同排列。GetTopologies 可以通告一个或多个拓扑。

一个拓扑

如果通告了一个拓扑,即 GetTopologies 返回包含一个元素的向量,则所有 PE 都属于这个明确的单个流水线。本例中的排序是显式的。例如,如果 GetElements 返回 2 个 PE:

  1. Element:id = 1,类型 = AUTOMATIC_GAIN_LIMITER (AGL)
  2. Element:ID = 2,类型 = 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
                +-------+    +-------+

在此拓扑中,开头(输入信号输入到流水线)和流水线结尾(输出信号从流水线输出)都是隐式的。可以通过 ENDPOINT 类型的产品专家 (PE) 来明确指定此类规则(请参阅下面的端点)。

如果仅通告了一个拓扑,则内容仅供参考,因为客户端无法更改唯一拓扑的使用。

多个拓扑

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

服务器通过仅列出支持的 PE 的具体排列方式和顺序,可以限制有效的流水线组合。

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

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

在本例中,GetTopologies 返回的 Topology 元素将列出每个拓扑的 idprocessing_elements_edge_pairs

  1. Topology:id = 1,processing_elements_edge_pairs = *.processing_element_id_from= 3 andprocessing_element_id_to= 2. *. processing_element_id_from = 2,processing_element_id_to = 4。 *.processing_element_id_from= 4 andprocessing_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 andprocessing_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 类型的产品专家支持:

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

端点

ENDPOINT 类型的 PE 是可选的(即使存在 CONNECTION_POINT),它允许通过明确的起始输入和结束输出来完成流水线结构。不过,对于提供 Composite 协议的驱动程序,任何受支持的环形缓冲区或 DAI 互连都必须列为 ENDPOINT,并且 GetElements 会返回类型 RING_BUFFERDAI_INTERCONNECTComposite 协议 API 需要端点 PE ID 来识别环形缓冲区和 DAI 互联配置。

如果未指定 ENDPOINT,则没有传入边缘的 PE 是输入,没有传入边缘的 PE 是输出。例如,上述多个拓扑中的示例包含两个拓扑,每个拓扑都具有一条流水线,拓扑 ID 1 中的单个流水线以 PE ID 3 开头,以 PE ID 1 结尾,拓扑 ID 2 中的单个流水线以 PE ID 2 开头,以 PE ID 6 结尾。