这次的设备是 RME Babyface Pro 原版,通过光纤连接 ADI-2 DAC。同一套连接在 Windows 下正常,换到 Ubuntu 后,先是系统不显示声卡,装上社区驱动后又遇到了“播放器在播放、音频流也在运行,但 DAC 没有电平”的问题。
最终通过硬件内部回环和逐组寄存器实验,定位到了所用驱动版本的输出路由映射问题,并在本机完成修正。本文记录安装和排障过程,也把验证边界保留下来:以下补丁针对本文固定的社区驱动提交,在这台原版 Babyface Pro 上验证;不能直接推断所有固件、FS 型号和后续驱动版本都有相同问题。
环境与两条使用路径
| 项目 | 本次环境 |
|---|---|
| 系统 | Ubuntu 26.04.1 LTS |
| 内核 | 7.0.0-38-generic |
| 音频服务 | PipeWire 1.6.2 + WirePlumber |
| 声卡 | Babyface Pro,专用模式 USB ID 2a39:3fc0 |
| 数字连接 | Babyface 光纤 OUT → ADI-2 DAC Optical IN |
| 社区驱动基线 | babyface-pro-linux,提交 db4346b32ec83d852b6e7010a841c21d9ef5a17c |
| 图形面板 | TuxMix 0.3.2,提交 d0ba98a0cdee1af58d704f68fbb76d378b58dab0 |
Linux 下有两条不同的路径:
- CC(Class Compliant)模式:使用 Linux 自带的 USB 音频驱动。RME 的产品说明列出了 Linux 对 CC 模式的支持。
- PC 专用模式:本次使用社区项目 babyface-pro-linux,内核模块名为
snd-usb-babyface-pro。这不是 RME 官方 Linux 驱动。
最初检查时,lsusb 能看到 Babyface,但 lsusb -t 中对应接口没有绑定驱动,/proc/asound/cards 和 wpctl status 里也没有它。USB 枚举成功,只能说明设备接上了,不能说明音频驱动已经工作。
lsusb -d 2a39:3fc0
lsusb -t
cat /proc/asound/cards
wpctl status
本次机器已关闭 Secure Boot,并装有当前内核头文件。其他机器如果启用 Secure Boot,还需要处理外部内核模块的签名与信任问题;不能只看到编译成功就认为模块一定能加载。
专用驱动不会直接继承 Windows TotalMix 路由
这是安装前就应该知道的一点。
设备可能保留部分硬件状态,但本文使用的社区驱动在加载时会执行初始化,并主动写入默认混音配置。源码说明,驱动没有混音推子的硬件读回能力,依赖自己的控制缓存。它的默认策略是把各软件播放对送入各输出,模拟主输出和耳机主音量从较低电平起步。
因此,不能把“Windows 下 TotalMix 已经设置好了”当作 Linux 会自动沿用这些路由的保证。驱动加载、alsactl restore 和图形面板的场景恢复,都可能重新写入路由。
安装或大幅修改前,应在 Windows 中保存需要保留的 TotalMix 工作区或快照。Linux 驱动加载后,可以另外保存当前 ALSA 状态:
sudo alsactl -f "$HOME/babyface-before-change.state" store BabyfacePro
这份备份记录的是 Linux 驱动当前暴露的状态,并不能找回此前已经被覆盖的 Windows 配置。
为什么系统里最初只有一个立体声输出
驱动加载成功后,ALSA 能看到 BabyfacePro,但桌面声音设置最初只有一个 Babyface Pro Stereo。检查 PipeWire 后发现,当时选中的是通用双声道配置。
用下面的命令查看声卡及其可用 Profile:
wpctl status
pw-cli enum-params <声卡设备ID> EnumProfile
wpctl set-profile <声卡设备ID> <pro-audio对应的索引>
这里的 ID 和索引必须以自己的机器为准。切换到 Pro Audio 后,本机的播放节点暴露了 12 个通道:AUX0 到 AUX11。
但 12 通道设备不会自动变成桌面菜单里的六个立体声输出。为方便日常选择,本次使用 PipeWire 的 loopback 模块,将它拆成六对:
| 桌面输出 | 软件播放通道 | 预期硬件输出 |
|---|---|---|
| 主输出 | AUX0 / AUX1 | AN 1–2 |
| 耳机 | AUX2 / AUX3 | PH 3–4 |
| 数字输出 1 | AUX4 / AUX5 | AS 1–2,即 SPDIF 或 ADAT 1–2 |
| 数字输出 2 | AUX6 / AUX7 | ADAT 3–4 |
| 数字输出 3 | AUX8 / AUX9 | ADAT 5–6 |
| 数字输出 4 | AUX10 / AUX11 | ADAT 7–8 |
以耳机输出为例,配置放在 ~/.config/pipewire/pipewire.conf.d/ 下:
context.modules = [
{ name = libpipewire-module-loopback
args = {
capture.props = {
node.name = "rme_phones"
node.description = "Babyface Pro Headphones"
media.class = "Audio/Sink"
audio.position = [ FL FR ]
}
playback.props = {
node.name = "playback.rme_phones"
audio.position = [ AUX2 AUX3 ]
target.object = "替换为本机Babyface的pro-output-0节点名称"
stream.dont-remix = true
node.passive = true
node.dont-fallback = true
}
}
}
]
target.object 要使用 wpctl inspect <播放节点ID> 里实际的 node.name。硬件声卡也需要保持 Pro Audio 配置。完整参数可在本机 man libpipewire-module-loopback 中查阅。
软件拆分和硬件混音是两层配置。 即使桌面显示了六个输出,如果 Babyface 内部仍把所有播放通道混到所有输出,它们也不会真正独立。本次最终设置为 PB1 → 主输出、PB2 → 耳机、PB3 → SPDIF,其余播放对对应剩余数字输出,非对应交叉点归零。
这里的 12 通道验证是在 48 kHz 下完成的。更高采样率下 ADAT 可用通道数会变化,不能照搬这张表推断全部通道仍可用。
光纤线并不等于 SPDIF 格式
Babyface 的同一个光口可以发送 ADAT 或 SPDIF;光纤线本身不决定协议。ADI-2 DAC 官方手册说明,其 Optical 输入能够自动识别 SPDIF 或 ADAT。
本次用于双声道 DAC,选择 SPDIF:
amixer -c BabyfacePro cget "name='Optical Out Format'"
amixer -c BabyfacePro cset "name='Optical Out Format'" 'S/PDIF'
sudo alsactl store BabyfacePro
桌面输出选择对应 AS1/2 的虚拟输出,ADI-2 DAC 选择 Optical 输入。SPDIF 模式只传送这对数字声道,菜单里的其他 ADAT 虚拟输出即使仍然存在,也不会通过该光口输出独立 ADAT 通道。
“流正在运行”,为什么还是没有声音
切换 SPDIF 后,仍然没有声音,ADI-2 DAC 也没有电平。
当时已经确认:
- 浏览器连接到了正确的 SPDIF 虚拟输出。
- PipeWire 把声音送到了硬件节点的 AUX4 / AUX5。
- ALSA 播放状态是
RUNNING,格式为 12 通道、48 kHz、S32_LE。 - AS1/2 主音量为 0 dB,未静音,光口格式读回为 SPDIF。
此前做过静音播放测试,进程正常退出,但它只能验证流能够启动,无法证明实际音频抵达光口。这一步的验证范围必须说清楚。
进一步录制软件监视器后,能测到明显音频;打开 AS1/2 的硬件内部回环,捕获值却几乎为零。同一段音频临时路由到主输出或耳机时,内部回环又正常了。
在对照过程中,还有一个很关键的现象:把 PB3 同时送进驱动标为“主输出”的混音控制时,SPDIF 突然有声。 这条临时路由可以恢复声音,却让两个输出耦合,不能当作独立输出已经修好。
到这里,问题已经缩小到硬件混音寄存器的映射。还不能仅凭这些现象断言是原版与 FS 的差异,或者声卡、线缆损坏。
用可区分的实验定位寄存器映射
为了避免音乐内容变化影响判断,测试时暂停了正常播放,改用低电平、左右频率不同的已知信号。在保存原始设置后,每次只打开一组候选混音寄存器,同时观察 12 个内部回环通道,测试后恢复状态。
本机得到的对应关系如下。表中是混音交叉点的左声道块基址,不是 USB 端点地址,也不是主音量寄存器:
| 输出 | 实测块基址 |
|---|---|
| AN 1–2 | 0x0000 |
| PH 3–4 | 0x0034 |
| AS 1–2 | 0x0068 |
| ADAT 3–4 | 0x009C |
| ADAT 5–6 | 0x00D0 |
| ADAT 7–8 | 0x0104 |
各块步长为 0x34,右声道部分相对左声道偏移 0x1A,再叠加具体信号源索引。
所用驱动基线却将左基址设为 0x0034、右基址设为 0x004E,输出块顺序是 {1, 0, 2, 3, 4, 5},并对主输出额外写入一组所谓 low map 地址。放到本机实测映射中,主输出控制同时写到了主输出和 AS1/2,而数字输出控制又发生了错位。
本机补丁做了三项修改:
- 左、右块基址改为
0x0000、0x001A。 - 输出块顺序改为
{0, 1, 2, 3, 4, 5}。 - 普通交叉点写入只写对应输出,删除主输出的重复写入路径。
补丁没有改变 PCM 精度、USB 流传输或延迟参数。它修正的是这次实测定位的路由问题,并不代表社区驱动的全部 DSP、面板功能都已经验证。
补丁、版本固定与 DKMS 安装
可下载本次的本机路由修复补丁。SHA-256:
2a53315da84c70f7846bca37eb34fb0920d69ec1eb6288cb0813934a78f99e74
补丁只针对前述固定提交。后续上游代码可能变化,应用前先检查,不要直接覆盖未知版本:
git clone https://github.com/ismail-bahloul/babyface-pro-linux.git
cd babyface-pro-linux
git checkout db4346b32ec83d852b6e7010a841c21d9ef5a17c
curl -fLO https://driftnode.cn/article-assets/babyface-routing-local1.patch
sha256sum babyface-routing-local1.patch
git apply --check babyface-routing-local1.patch
git apply babyface-routing-local1.patch
本机将补丁版标记为 0.2.0.local1,通过 DKMS 安装:
sudo apt install build-essential dkms linux-headers-$(uname -r)
sudo cp -r tools/kernel /usr/src/snd-usb-babyface-pro-0.2.0.local1
sudo dkms add -m snd-usb-babyface-pro -v 0.2.0.local1
sudo dkms build -m snd-usb-babyface-pro -v 0.2.0.local1 -k "$(uname -r)"
sudo dkms install -m snd-usb-babyface-pro -v 0.2.0.local1 -k "$(uname -r)"
这是干净安装的命令示例。若已经加载旧模块,需要先保存混音状态、停止占用声卡的音频服务、卸载旧模块,再安装并加载新版,最后恢复服务。替换磁盘上的 .ko 不会自动替换正在运行的模块。
可以核对磁盘模块和已加载模块的源码版本标识:
modinfo -F srcversion snd-usb-babyface-pro
cat /sys/module/snd_usb_babyface_pro/srcversion
dkms status -m snd-usb-babyface-pro
本次两处 srcversion 一致,DKMS 显示 0.2.0.local1 已安装。旧版本的 DKMS 注册也已移除,保留源代码与备份,以免后续内核升级重新装回错误映射。
这次实际验证到了哪里
修正版加载后,删除了“PB3 同时送主输出”的临时方案,恢复六组一一对应路由,并做了以下检查:
- 上游四组音量、显示及 EQ 数值规律自测通过。
- 针对实际路由写入函数,验证 84 个输出/信号源组合都只写入对应输出块的左右寄存器。
- 六个 PipeWire 虚拟输出同时播放各自的左右测试音,经 USB、硬件混音、内部回环捕获全部 12 个通道。
- 12 个通道均出现预期频率;其余通道的测试频率相对目标频率低于 −40 dB,达到本次通道隔离检查阈值。
- 重新加载驱动并恢复已保存状态后,检查矩阵保持一一对应,SPDIF 格式保留,主输出上的临时 PB3 路由为零。
这不是模拟输出的专业串音指标测量:测试使用低电平信号,包含量化与数值分析误差。它的目的,是识别明显的路由串接、通道错位和左右混合。
验证边界是 48 kHz 下的内部回环。 并未逐一使用外部设备录制六组物理输出,也没有完成所有采样率、所有型号和固件版本的验证。ADI-2 DAC 的最终光纤链路仍应通过其输入锁定状态、电平和实际听音确认。
安装类似 TotalMix 的 Linux 面板:TuxMix
TuxMix 是社区的 TotalMix 风格控制面板,不是 RME 官方 TotalMix。它支持 ALSA 和直接 USB 两种后端。
本次已经由内核驱动管理声卡,因此固定使用 ALSA 后端。它通过驱动暴露的控制项操作混音,不直接套用用户态 USB 后端的寄存器映射。
Ubuntu 上的构建过程如下:
sudo apt install cargo rustc libasound2-dev pkg-config pulseaudio-utils
git clone https://github.com/ismail-bahloul/TuxMix.git
cd TuxMix
git checkout d0ba98a0cdee1af58d704f68fbb76d378b58dab0
cargo build --locked --release -p tuxmix-gui
./target/release/tuxmix-gui --backend alsa --view mixer
本机 Rust/Cargo 来自 Ubuntu 软件源,版本为 1.93.1。pulseaudio-utils 提供 pactl,TuxMix 的播放电平表用它发现 PipeWire 的声卡监视器;安装这个工具包不等于把音频服务切换回 PulseAudio。
面板中的对应关系是:
- AN1 / AN2:主模拟输出。
- PH3 / PH4:耳机输出。
- AS1 / AS2:SPDIF 或 ADAT 的第一对数字输出。
TuxMix 会自动保存场景到 ~/.local/share/tuxmix/scenes/auto.json,下次启动可能重新应用。因此,后续在其他工具里调整路由时,也要注意面板场景是否同步。
本次启动前后导出的 ALSA 状态完全一致;随后临时改变一个未使用的数字输出主音量,确认面板自动保存的状态能跟随变化,再恢复原值,最终 ALSA 状态再次与备份一致。日志也明确显示使用真实设备的 Proprietary 控制格式和 ALSA 后端,而非模拟设备。
还有一个实测限制:该版本的输入电平表尝试直接打开 ALSA 录音 PCM,当前被 PipeWire 占用时会失败,输入电平可能显示 N/A。播放电平表走 PipeWire 监视器,是另一条路径。不能仅凭输入电平表没有显示,就断言输入路由或话放已经损坏。
这次最有用的排障方法,是把“桌面选择的输出”“软件流里的实际样本”“硬件混音总线”“物理数字链路”分别验证。声音设置里出现设备、控制值读回正确、播放进程正常退出,都只是其中一层的证据。