USB 数字音频

本文介绍了 Android 对 USB 数字音频和相关基于 USB 的协议的支持。

受众

本文的目标受众是 Android 设备 OEM、SoC 供应商、USB 音频外围设备供应商、高级音频应用开发者以及其他寻求详细了解 Android 系统上的 USB 数字音频内部机制的人员。

Nexus 设备最终用户应参阅 Nexus 帮助中心“使用 USB 主机模式录制和播放音频”一文。尽管本文并非面向最终用户,但某些发烧友级消费者可能会觉得其中部分内容很有趣。

USB 概览

通用串行总线 (USB) 在 Wikipedia 文章 USB 中被非正式地描述,并由 USB Implementers Forum, Inc. 发布的标准正式定义。为了方便起见,我们在此总结了关键的 USB 概念,但标准是权威参考。

基本概念和术语

USB 是一种总线,具有数据传输操作的单个发起者,称为主机。主机通过总线与外围设备通信。

注意:术语设备配件外围设备的常用同义词。我们在此避免使用这些术语,因为它们可能与 Android 设备 或称为配件模式的 Android 特定概念相混淆。

枚举是主机的关键角色:检测哪些外围设备连接到总线,并查询通过描述符表达的其属性的过程。

一个外围设备可能是一个物理对象,但实际上实现了多个逻辑功能。例如,网络摄像头外围设备可以同时具有摄像头功能和麦克风音频功能。

每个外围设备功能都有一个接口,用于定义与该功能通信的协议。

主机通过管道与外围设备通信,该管道连接到端点,端点是外围设备功能之一提供的数据源或数据接收器。

管道有两种类型:消息管道和管道。消息管道用于双向控制和状态。流管道用于单向数据传输。

主机启动所有数据传输,因此术语输入输出是相对于主机而言的。输入操作将数据从外围设备传输到主机,而输出操作将数据从主机传输到外围设备。

有三种主要的数据传输模式:中断批量同步。同步模式将在音频上下文中进一步讨论。

外围设备可能具有连接到外部世界的终端,超出外围设备本身。通过这种方式,外围设备用于在 USB 协议和“真实世界”信号之间进行转换。终端是功能的逻辑对象。

Android USB 模式

开发模式

开发模式自 Android 的初始版本以来就已存在。Android 设备作为 USB 外围设备出现在运行桌面操作系统(如 Linux、Mac OS X 或 Windows)的主机 PC 上。唯一可见的外围设备功能是 Android fastbootAndroid 调试桥 (adb)。fastboot 和 adb 协议分层在 USB 批量数据传输模式之上。

主机模式

主机模式在 Android 3.1(API 级别 12)中引入。

由于 Android 设备必须充当主机,并且大多数 Android 设备都包含不允许直接进行主机操作的 micro-USB 连接器,因此通常需要像这样的即时 (OTG) 适配器

OTG

图 1. 即时 (OTG) 适配器

Android 设备可能无法提供足够的电力来操作特定的外围设备,具体取决于外围设备需要多少电力,以及 Android 设备能够提供多少电力。即使有足够的电力可用,Android 设备电池的电量也可能会大大缩短。对于这些情况,请使用像这样的有源集线器

Powered hub

图 2. 有源集线器

配件模式

配件模式在 Android 3.1(API 级别 12)中引入,并向后移植到 Android 2.3.4。在此模式下,Android 设备作为 USB 外围设备运行,受另一个设备(如充当主机的底座)的控制。开发模式和配件模式之间的区别在于,除了 adb 之外,主机还可以看到其他 USB 功能。Android 设备从开发模式开始,然后通过重新协商过程过渡到配件模式。

配件模式在 Android 4.1 中扩展了其他功能,特别是下面描述的音频。

USB 音频

USB 类

每个外围设备功能都有一个相关的设备类文档,该文档指定了该功能的标准协议。这使类兼容的主机和外围设备功能能够互操作,而无需详细了解彼此的工作原理。如果主机和外围设备由不同的实体提供,则类兼容性至关重要。

术语免驱动类兼容的常用同义词,表示可以使用此类外围设备的标准功能,而无需安装特定于操作系统的驱动程序。可以假设,对于主要桌面操作系统,广告为“无需驱动程序”的外围设备将是类兼容的,尽管可能存在例外情况。

USB 音频类

在这里,我们只关注实现音频功能的外围设备,因此遵循音频设备类。USB 音频类规范有两个版本:类 1 (UAC1) 和 2 (UAC2)。

与其他类的比较

USB 包括许多其他设备类,其中一些设备类可能会与音频类混淆。大容量存储类 (MSC) 用于面向扇区的媒体访问,而媒体传输协议 (MTP) 用于对媒体进行完整文件访问。MSC 和 MTP 都可以用于传输音频文件,但只有 USB 音频类适合实时流式传输。

音频终端

音频外围设备的终端通常是模拟的。在外围设备的输入终端处呈现的模拟信号通过模数转换器 (ADC) 转换为数字信号,并通过 USB 协议传输以供主机使用。ADC 是主机的数据。类似地,主机通过 USB 协议将数字音频信号发送到外围设备,其中数模转换器 (DAC) 转换并呈现给模拟输出终端。DAC 是主机的接收器

通道

具有音频功能的外围设备可以包括源终端、接收器终端或两者兼有。每个方向可以有一个通道(单声道)、两个通道(立体声)或更多通道。具有两个以上通道的外围设备称为多声道。通常将立体声流解释为由通道和通道组成,并通过扩展将多声道流解释为具有与每个通道对应的空间位置。但是,不为每个通道分配任何特定的标准空间含义也是非常合适的(特别是对于 USB 音频而言,比HDMI 更合适)。在这种情况下,如何使用每个通道取决于应用程序和用户定义。例如,四通道 USB 输入流可能具有连接到房间内各种麦克风的前三个通道,以及接收来自 AM 收音机的输入的最后一个通道。

同步传输模式

USB 音频使用同步传输模式来实现其实时特性,但以牺牲错误恢复为代价。在同步模式下,带宽得到保证,并且使用循环冗余校验 (CRC) 检测数据传输错误。但是,如果发生错误,则没有数据包确认或重新传输。

同步传输发生在每个帧开始 (SOF) 周期。SOF 周期对于全速为 1 毫秒,对于高速为 125 微秒。每个全速帧最多可携带 1023 字节的有效负载,而高速帧最多可携带 1024 字节。将这些放在一起,我们计算出的最大传输速率为每秒 1,023,000 或 8,192,000 字节。这设置了音频采样率、通道计数和位深度的理论上限。实际限制较低。

在同步模式中,有三种子模式

  • 自适应
  • 异步
  • 同步

在自适应子模式下,外围设备接收器或源适应主机可能变化的采样率。

在异步(也称为隐式反馈)子模式下,接收器或源确定采样率,主机进行适应。异步子模式的主要理论优势在于,源或接收器 USB 时钟在物理和电气上更靠近(实际上可能与驱动 DAC 或 ADC 的时钟相同或源自该时钟)。这种邻近性意味着异步子模式应该不易受时钟抖动的影响。此外,DAC 或 ADC 使用的时钟可以设计为比主机时钟具有更高的精度和更低的漂移。

在同步子模式下,每个 SOF 周期传输固定数量的字节。音频采样率有效地从 USB 时钟导出。同步子模式不常用于音频,因为主机和外围设备都受 USB 时钟的支配。

下表总结了同步子模式

子模式 字节计数
每包
采样率
由...确定
用于音频
自适应 可变 主机
异步 可变 外围设备
同步 固定 USB 时钟

在实践中,子模式当然很重要,但也应考虑其他因素。

Android 对 USB 音频类的支持

开发模式

开发模式不支持 USB 音频。

主机模式

Android 5.0(API 级别 21)及更高版本支持 USB 音频类 1 (UAC1) 功能的子集

  • Android 设备必须充当主机
  • 音频格式必须是 PCM(接口类型 I)
  • 位深度必须是 16 位、24 位或 32 位,其中 24 位有用的音频数据在 32 位字的最有效位内左对齐
  • 采样率必须是 48、44.1、32、24、22.05、16、12、11.025 或 8 kHz
  • 通道计数必须是 1(单声道)或 2(立体声)

浏览 Android 框架源代码可能会显示超出支持这些功能所需的最少代码的其他代码。但是,此代码尚未经过验证,因此尚不声明更高级的功能。

配件模式

Android 4.1(API 级别 16)增加了对主机音频播放的有限支持。在配件模式下,Android 会自动将其音频输出路由到 USB。也就是说,Android 设备充当主机的数据源,例如底座。

配件模式音频具有以下功能

  • Android 设备必须由知识渊博的主机控制,该主机必须首先将 Android 设备从开发模式转换为配件模式,然后主机必须从适当的端点传输音频数据。因此,Android 设备对于主机而言不会显得“免驱动”。
  • 方向必须是输入,相对于主机而言
  • 音频格式必须是 16 位 PCM
  • 采样率必须是 44.1 kHz
  • 通道计数必须是 2(立体声)

配件模式音频尚未被广泛采用,目前不建议用于新设计。

USB 数字音频的应用

顾名思义,USB 数字音频信号由数字数据流表示,而不是通用 TRS 迷你耳机连接器使用的模拟信号。最终,任何数字信号都必须先转换为模拟信号才能被听到。在选择将转换放在何处时,需要权衡利弊。

两个 DAC 的故事

在下面的示例图中,我们比较了两种设计。首先,我们有一个移动设备,带有应用程序处理器 (AP)、板载 DAC、放大器和连接到耳机的模拟 TRS 连接器。我们还考虑了一个移动设备,该设备通过 USB 连接到外部 USB DAC 和放大器,也带有耳机。

DAC comparison

图 3. 两个 DAC 的比较

哪种设计更好?答案取决于您的需求。每种设计都有优点和缺点。

注意:这是一个人为的比较,因为真正的 Android 设备可能会同时提供这两种选项。

第一种设计 A 更简单、更便宜、功耗更低,并且在假设组件可靠性相同的情况下,将是更可靠的设计。但是,通常在音频质量与其他要求之间需要权衡。例如,如果这是一种大众市场设备,则其设计可能旨在满足普通消费者的需求,而不是发烧友的需求。

在第二种设计中,外部音频外围设备 C 可以设计为具有更高的音频质量和更大的功率输出,而不会影响基本大众市场 Android 设备 B 的成本。是的,这是一种更昂贵的设计,但成本仅由那些需要它的人承担。

移动设备以具有高密度电路板而闻名,这可能会导致更多串扰的机会,从而降低相邻的模拟信号。数字通信不太容易受到噪声的影响,因此将 DAC 从 Android 设备 A 移动到外部电路板 C 允许最终的模拟级在物理和电气上与密集且嘈杂的电路板隔离,从而实现更高的保真度音频。

另一方面,第二种设计更复杂,并且随着复杂性的增加,发生故障的机会也更多。USB 控制器也会产生额外的延迟。

主机模式应用

典型的 USB 主机模式音频应用包括

  • 音乐收听
  • 电话
  • 即时消息和语音聊天
  • 录音

对于所有这些应用,Android 会检测到兼容的 USB 数字音频外围设备,并根据音频策略规则自动路由音频播放和捕获。立体声内容在外围设备的前两个通道上播放。

没有特定于 USB 数字音频的 API。对于高级用法,自动路由可能会干扰 USB 感知的应用。对于此类应用,请通过设置 / 开发者选项的“媒体”部分中的相应控件禁用自动路由。

在主机模式下调试

在 USB 主机模式下,无法通过 USB 进行 adb 调试。有关替代方案,请参阅 Android 调试桥无线使用 部分。

实现 USB 音频

给音频外围设备供应商的建议

为了与 Android 设备互操作,音频外围设备供应商应

  • 设计为音频类兼容;目前 Android 的目标是类 1,但为类 2 做好计划是明智的
  • 避免怪癖
  • 测试与参考和流行的 Android 设备的互操作性
  • 清楚地记录支持的功能、音频类兼容性、功率要求等,以便消费者可以做出明智的决定

给 Android 设备 OEM 和 SoC 供应商的建议

为了支持 USB 数字音频,设备 OEM 和 SoC 供应商应

  • 设计硬件以支持 USB 主机模式
  • 通过 android.hardware.usb.host.xml 功能标志在框架级别启用通用 USB 主机支持
  • 启用所有需要的内核功能:USB 主机模式、USB 音频、同步传输模式
  • 及时了解最新的内核版本和补丁;尽管类兼容性的目标很高尚,但仍然存在具有怪癖的音频外围设备,并且最新的内核具有针对此类怪癖的解决方法
  • 启用如下所述的 USB 音频策略
  • 将 audio.usb.default 添加到 device.mk 中的 PRODUCT_PACKAGES
  • 测试与常见的 USB 音频外围设备的互操作性

启用 USB 音频策略

要启用 USB 音频,请在音频策略配置文件中添加一个条目。该文件通常位于此处

device/oem/codename/audio_policy.conf

路径名组件“oem”应替换为制造 Android 设备的 OEM 的名称,“codename”应替换为设备代码名称。

此处显示了一个示例条目

audio_hw_modules {
  ...
  usb {
    outputs {
      usb_accessory {
        sampling_rates 44100
        channel_masks AUDIO_CHANNEL_OUT_STEREO
        formats AUDIO_FORMAT_PCM_16_BIT
        devices AUDIO_DEVICE_OUT_USB_ACCESSORY
      }
      usb_device {
        sampling_rates dynamic
        channel_masks dynamic
        formats dynamic
        devices AUDIO_DEVICE_OUT_USB_DEVICE
      }
    }
    inputs {
      usb_device {
        sampling_rates dynamic
        channel_masks AUDIO_CHANNEL_IN_STEREO
        formats AUDIO_FORMAT_PCM_16_BIT
        devices AUDIO_DEVICE_IN_USB_DEVICE
      }
    }
  }
  ...
}

源代码

USB 音频的音频硬件抽象层 (HAL) 实现位于此处

hardware/libhardware/modules/usbaudio/

USB 音频 HAL 在很大程度上依赖于 tinyalsa,如 音频术语 中所述。尽管 USB 音频依赖于同步传输,但这已通过 ALSA 实现进行了抽象。因此,USB 音频 HAL 和 tinyalsa 无需关注 USB 协议的这一部分。

测试 USB 音频

有关 USB 音频的 CTS 测试信息,请参阅 USB 音频 CTS 验证程序测试