Linux 音频架构

最后更新: 2023-01-24 01:00:34 +0800 +0800
tags: Linux | Audio
原文以英文撰写。您正在阅读AI翻译版本。

Linux 音频由一组层次组成,而不是一个可互换的 API。ALSA 暴露内核声音设备和一个用户空间库。随后,PulseAudio 或 PipeWire 可以在应用程序之间共享这些设备、转换格式、混合音频流,并应用桌面路由策略。按照信号流顺序测试每一层,可以让故障排查成为确定性的过程。

ALSA:内核设备与 libasound #

ALSA 内核驱动程序注册声卡及其逻辑设备。用户空间通过 /dev/snd 看到声卡、设备和子设备标识符,而 /proc/asound 则暴露诊断状态。桌面音频涉及四类重要接口:

  • PCM 设备传输采样后的播放帧或采集帧。
  • 控制设备暴露混音器开关、增益、时钟、插孔状态以及其他声卡级控制项。
  • 原始 MIDI 和音序器设备承载 MIDI 数据和调度。
  • 定时器设备提供音频和 MIDI 客户端使用的计时功能。

一个 PCM 帧包含某一时刻每个声道的一个样本。在开始流式传输之前,客户端会协商访问模式、样本格式、声道数、采样率、周期大小和缓冲区大小。驱动程序和硬件通过环形缓冲区移动数据,而客户端读取或写入帧。如果播放端在客户端提供数据之前就已消费完数据,就会发生欠载;如果采集端覆盖尚未读取的帧,就会发生过载。ALSA 将两者都报告为 XRUN,通常对应 -EPIPE,而 snd_pcm_recover() 可以恢复受支持的情形。

libasound 提供 snd_pcm_* 和 snd_ctl_* API,以及配置层和插件层。不同设备名称具有不同语义:

  • hw:0,0 直接寻址硬件 PCM,并且只接受驱动程序支持的参数。另一个直接打开该设备的进程可能收到 EBUSY。
  • plughw:0,0 会在需要时插入 libasound 的格式、采样率或声道转换。
  • default 遵循 ALSA 配置,可能解析为软件混音器、PulseAudio 插件或 PipeWire 插件,而不是物理硬件。

因此,aplay -D hw:0,0 测试成功只能证明内核/ALSA 路径可用,不能证明桌面服务器、其选定路由或应用程序的服务器客户端配置正确。

在不更改配置的情况下检查 ALSA:

sh
cat /proc/asound/cards
aplay -l
arecord -l
aplay -L
amixer -c 0

小写 -l 列出硬件设备;大写 -L 列出已配置的 PCM 名称,其中包括插件。alsamixer 以交互方式暴露控制项。即使 PulseAudio 和 PipeWire 的软件音量非零,静音的硬件控制项也可能使它们没有声音。

PulseAudio 的服务器模型 #

PulseAudio 运行一个服务器,该服务器占用一个或多个 ALSA 设备,并通过 libpulse 或兼容插件接受客户端音频流。其术语以面向服务器的方向为准:

  • **接收端(sink)**消费播放流,通常写入输出设备。
  • **源端(source)**生成采集流,通常从输入设备读取。
  • **接收端输入(sink input)**是应用程序的播放流。
  • **源端输出(source output)**是应用程序的录音流。
  • **监听源(monitor source)**采集发送到某个接收端的音频。

服务器协商客户端格式,在采样率不同时重采样音频流,应用每条流的音量,混合播放流,并将生成的音频流写入 ALSA。采集过程沿相反路径进行。模块负责发现设备,并提供网络音频、虚拟设备、音频流恢复和策略集成等功能。

PulseAudio 被设计为按用户运行,因为路由、音量、蓝牙授权和应用程序音频流都属于登录会话。根据发行版和 PulseAudio 版本,用户级 systemd 服务/套接字或 libpulse 自动生成机制会启动它。系统级守护进程是一种具有不同安全性和设备访问权衡的专用配置,并非桌面环境的默认方式。

使用以下命令检查正在运行的服务器:

sh
pactl info
pactl list short cards
pactl list short sinks
pactl list short sources
pactl list short sink-inputs
pactl list short source-outputs

pacat 可以通过 PulseAudio 协议播放或录音;在提供该名称的安装中,其历史名称 pamon 是一个别名。pa-info 会收集更广泛的报告,用于调查 PulseAudio 缺陷。

发现、配置文件、端口与默认设备 #

物理控制器首先表现为 ALSA 声卡。随后,PulseAudio 的设备发现机制将其表示为带有配置文件和端口的声卡:

  • **配置文件(profile)**选择声卡级模式,例如立体声输出或输入/输出双工模式。硬件约束可能使配置文件相互排斥。
  • **端口(port)**表示配置文件内的一条路由,例如扬声器、耳机或麦克风插孔。
  • 接收端或源端是由所选配置文件创建的活动流式传输端点。

如果活动配置文件禁用了采集,或者活动端口指向未连接的路由,仅选择正确的声卡仍不够。使用 pactl list cards、pactl list sinks 和 pactl list sources 的详细输出检查可用性、配置文件、端口、静音、音量和样本规格。

PulseAudio 将默认设备称为后备设备,因为已保存的逐音频流策略可以覆盖它。新出现的音频流会前往后备接收端或源端,而 module-stream-restore 可以将已知应用程序的音频流送回其先前设备。使用以下命令设置后备设备:

sh
pactl set-default-sink SINK_NAME
pactl set-default-source SOURCE_NAME

现有音频流可能需要显式移动或重新打开。桌面控制面板或 pavucontrol 会更新相同的服务器端概念,而且移动实时音频流时往往更方便。

延迟、重采样与混音 #

延迟会在完整路径中累积:

  1. 应用程序将帧加入队列。
  2. 服务器缓冲区和调度量程保留待混音的数据。
  3. 重采样器或声道混音器可能转换音频流。
  4. ALSA 周期和硬件缓冲区保留额外的帧。
  5. 转换器、蓝牙编解码器或网络传输会增加设备特定的延迟。

更小的周期和缓冲区可以降低延迟,但要求应用程序和调度器更频繁地唤醒。错过截止时间会造成 XRUN 或服务器丢音。更大的缓冲区提高了对调度抖动的容忍度,代价是交互延迟增加。报告延迟时应同时给出采样率,因为包含 N 帧的缓冲区会贡献 N / sample_rate 秒的延迟。

混音需要统一的格式和采样率。因此,当音频流的采样率与图或硬件采样率不匹配时,PulseAudio 或 PipeWire 会对其重采样。ALSA 的 plug 插件也可以重采样,所以不明确的设备路径可能在多个层次执行转换。进行测量时,应识别客户端、服务器和 ALSA 端点协商得到的格式,而不要假设文件的采样率未经改变就到达了 DAC。

直接访问 ALSA 可以绕过桌面服务器的混音阶段,但可能独占设备并导致其他应用程序无法工作。低延迟取决于正确的调度、周期选择和硬件行为,而不只是绕过某个指定组件。

PipeWire 边界 #

PipeWire 可以取代 PulseAudio 的桌面服务器角色,但不会取代 ALSA。PipeWire 服务器使用 libasound 将 ALSA 设备暴露为图节点;应用程序提供节点和端口,链路在它们之间传输媒体。WirePlumber 通常负责会话策略:监控由 udev 支持的 ALSA 设备、选择配置文件和路由、选择默认设备并创建链路。

兼容服务保留了现有 API:

  • pipewire-pulse 实现 PulseAudio 协议,因此 libpulse、pactl 和 PulseAudio 应用程序可以操作由 PipeWire 管理的对象。
  • ALSA 和 JACK 兼容插件可以将客户端重定向到 PipeWire。
  • 原生 PipeWire 客户端直接使用 PipeWire 协议。

因此,pactl info 成功并不能证明 /usr/bin/pulseaudio 守护进程正在运行。应检查报告的服务器名称和活动的用户单元:

sh
systemctl --user status pipewire.service wireplumber.service pipewire-pulse.service
systemctl --user status pulseaudio.service pulseaudio.socket
wpctl status

会话套接字只应由一个 PulseAudio 协议服务器占用。在 PipeWire 系统上,wpctl status、wpctl inspect ID、pw-dump 和 pw-top 显示原生图和调度状态;pactl 显示兼容视图。

按信号流顺序排查故障 #

从最低层的故障边界开始,并避免同时更改多个层次:

  1. **内核发现:**确认 /proc/asound/cards、aplay -l 和 arecord -l 中存在该声卡。检查启动内核消息中与固件、探测、USB 或 HDMI 有关的错误。
  2. **ALSA 控制项:**使用 amixer 或 alsamixer 检查静音、增益和路由控制项。仅在停止占用该 PCM 的服务器后测试已知 PCM;否则,EBUSY 是预期结果,不具有诊断意义。
  3. **服务器健康状态:**确定会话由 PulseAudio 还是 pipewire-pulse 提供服务。检查用户单元日志,并确认服务器能够看到 ALSA 声卡。
  4. **配置文件和路由:**验证活动配置文件创建了所需的接收端或源端,并且其选定端口可用。
  5. **音频流路由:**确认存在实时的接收端输入或源端输出、没有被静音,并指向预期设备。已保存的逐应用程序路由可以覆盖后备设备。
  6. **格式和时序:**比较协商得到的采样率、声道、缓冲区大小和 XRUN 计数器。当丢音与调度负载相关时,在 PipeWire 上使用 pw-top,或查看 PulseAudio 详细日志。
  7. **物理路径:**在确认软件已将帧送达端点后,测试线缆、接收器、编解码器、麦克风偏置和硬件音量。

编辑配置之前,先捕获命令输出和日志。设备名称和 ID 可能在重启后改变,因此持久化规则应匹配稳定属性,而不是临时的数字声卡索引。

上游参考资料 #

评论

在 GitHub 上阅读或评论(发表评论需要登录)