# 9.1 音频设备配置

> **警告**
>
> KDE 6 桌面环境的 Ports 构建默认配置使用 PulseAudio（脉冲音频，PA）作为音频后端。PulseAudio 作为音频服务器会接管系统音频输出管理，形成全局音频路由。在未充分了解配置细节的情况下，请勿手动切换到其他音频后端（如 PipeWire），以免造成音频系统工作异常。该提示主要适用于使用 KDE 6 桌面环境的场景。

## 声音设置

`snd_hda` 是 FreeBSD 内核中用于支持 Intel High Definition Audio（HDA）规范声卡的驱动模块，适用于绝大多数现代集成声卡。该驱动通常会在系统启动时自动加载；若默认内核未包含或未自动加载该驱动，则需手动加载对应内核模块以启用音频功能。可使用 `kldstat` 命令检查驱动是否已加载。

为确认系统识别的音频设备，可使用以下命令查看当前声卡设备列表：

```sh
$ cat /dev/sndstat
Installed devices:
pcm0: <NVIDIA (0x0083) (HDMI/DP 8ch)> (play)
pcm1: <NVIDIA (0x0083) (HDMI/DP 8ch)> (play)
pcm2: <NVIDIA (0x0083) (HDMI/DP 8ch)> (play)
pcm3: <NVIDIA (0x0083) (HDMI/DP 8ch)> (play)
pcm4: <Realtek ALC892 (Rear Analog 5.1/2.0)> (play/rec) default
pcm5: <Realtek ALC892 (Front Analog)> (play/rec)
pcm6: <Realtek ALC892 (Rear Digital)> (play)
No devices installed from userspace.
```

输出中标注为 `default` 的设备是 OSS（Open Sound System，开放声音系统）的默认音频设备。OSS 是 FreeBSD 原生的音频子系统，提供直接的音频设备访问接口。若软件使用 OSS 作为音频输出接口且输出设备设置为默认值，音频将从该设备输出。

若需获取更详细的声卡信息用于深度诊断，可通过调整内核参数提高调试输出等级：

```sh
# sysctl hw.snd.verbose=4  # 设置 FreeBSD 声卡驱动调试输出等级为 4
```

该命令将声卡驱动的调试输出等级设置为 4。调试等级范围为 0 至 4，数值越高输出信息越详细，等级 4 会输出最完整的调试信息。此设置为临时生效，系统重启后将恢复默认值。

FreeBSD 中大部分软件的音频输出接口为 OSS。部分软件默认使用 PulseAudio（如 Firefox 浏览器），这些软件的相关设置请参见后文提示。Firefox 可通过 `about:support` 页面查看当前使用的音频后端。Firefox 支持多种音频后端，通常按 PulseAudio、OSS 的优先级顺序自动选择，也可通过配置手动指定。

以下命令可设置默认 OSS 音频设备单元号为 5，其中数字对应 `pcm` 后的设备编号：

```sh
# sysctl hw.snd.default_unit=5
```

该设置为临时生效，系统重启后将恢复默认值。永久生效，需将配置写入 `/etc/sysctl.conf` 文件。

上文中的 `pcm6: <Realtek ALC892 (Rear Digital)> (play)` 为数字输出接口。一般集成声卡的模拟接口采样率最高为 48 kHz，数字接口因避免了模拟信号的模数转换损耗，最高采样率可达到 192 kHz。若存在数字输出但机箱面板无对应接口，而主板提供 S/PDIF（Sony/Philips Digital Interface，索尼/飞利浦数字接口）插针，可安装 S/PDIF 挡板（通常包含光纤口和同轴口），连接后即可使用。

## man 示例

以下节选自 FreeBSD Project. snd\_hda\[EB/OL]. \[2026-03-25]. <https://man.freebsd.org/cgi/man.cgi?snd_hda> 官方手册页。

以下示例均需要将相关配置行写入 `/boot/device.hints` 文件中，该文件用于在系统启动时配置硬件设备提示信息。

```sh
/
├── boot/
│   └── device.hints # 硬件设备提示文件
└── dev/
    └── sndstat # 声卡设备状态文件
```

> **注意**
>
> 下文示例中的 `cad0` 为 HDA 控制器下的音频编解码器编号，应以 `cat /dev/sndstat` 的实际输出为准。

### 示例 1

```ini
hint.hdac.0.cad0.nid20.config="as=1"   # 配置声卡节点 20 的音频流为通道 1
hint.hdac.0.cad0.nid21.config="as=2"   # 配置声卡节点 21 的音频流为通道 2
```

此配置会交换 Line‑out（线路输出）接口与扬声器的功能。因此 **pcm0** 设备会将声音输出到线路输出和耳机插孔。当耳机插入时，线路输出会自动静音。

* **pcm0** 的录音输入来自两个外置麦克风和线路输入插孔。
* **pcm1** 的播放则会输出到内置扬声器。

### 示例 2

```ini
hint.hdac.0.cad0.nid20.config="as=1 seq=15 device=Headphones"   # 配置声卡节点 20 的音频流为通道 1，序列号 15，输出设备为耳机
hint.hdac.0.cad0.nid27.config="as=2 seq=0"                       # 配置声卡节点 27 的音频流为通道 2，序列号 0
hint.hdac.0.cad0.nid25.config="as=4 seq=0"                       # 配置声卡节点 25 的音频流为通道 4，序列号 0
```

此配置会将耳机和其中一个麦克风分离到独立的设备。

* **pcm0** 会将声音播放到内置扬声器和线路输出插孔，并且在耳机插入时自动静音扬声器。
* **pcm0** 的录音输入来自一个外部麦克风和线路输入插孔。
* **pcm1** 设备则完全用于前面板的耳机（耳机 + 麦克风）。

### 示例 3

```ini
hint.hdac.0.cad0.nid20.config="as=1 seq=0"                 # 配置声卡节点 20 的音频流为通道 1，序列号 0
hint.hdac.0.cad0.nid26.config="as=2 seq=0"                 # 配置声卡节点 26 的音频流为通道 2，序列号 0
hint.hdac.0.cad0.nid27.config="as=3 seq=0"                 # 配置声卡节点 27 的音频流为通道 3，序列号 0
hint.hdac.0.cad0.nid25.config="as=4 seq=0"                 # 配置声卡节点 25 的音频流为通道 4，序列号 0
hint.hdac.0.cad0.nid24.config="as=5 seq=0 device=Line-out" # 配置声卡节点 24 的音频流为通道 5，序列号 0，输出设备为 Line‑out
hint.hdac.0.cad0.nid21.config="as=6 seq=0"                 # 配置声卡节点 21 的音频流为通道 6，序列号 0
```

此配置会得到 4 个独立设备：

* **pcm0**（线路输出和线路输入）
* **pcm1**（耳机和麦克风）
* **pcm2**（通过重新定义后置麦克风插孔作为额外线路输出）
* **pcm3**（内置扬声器）

### 示例 4

```ini
hint.hdac.0.cad0.nid20.config="as=1 seq=0"                 # 配置声卡节点 20 的音频流为通道 1，序列号 0
hint.hdac.0.cad0.nid24.config="as=1 seq=1 device=Line-out" # 配置声卡节点 24 的音频流为通道 1，序列号 1，输出设备为 Line‑out
hint.hdac.0.cad0.nid26.config="as=1 seq=2 device=Line-out" # 配置声卡节点 26 的音频流为通道 1，序列号 2，输出设备为 Line‑out
hint.hdac.0.cad0.nid21.config="as=2 seq=0"                 # 配置声卡节点 21 的音频流为通道 2，序列号 0
```

此配置会得到 2 个设备：

* **pcm0**：用于 5.1 声道播放，通过 3 个后置接口（线路输出 + 重新定义的麦克风和线路输入），以及前面板的耳机（耳机 + 麦克风）。
* **pcm1**：用于内置扬声器播放。

当耳机插入时，后置接口会自动静音。

## 实例

```sh
# cat /dev/sndstat # 省略无用信息
pcm1: <Realtek ALC897 (Rear Analog Line-in)> at nid 26 on hdaa0
pcm0: <Realtek ALC897 (Analog)> at nid 27 and 26 on hdaa0
```

该设备并非 AUX 接口（即非扬声器与麦克风的二合一接口），当前仅插入了一台音响。在默认配置下，该设备不会输出声音。

可以通过以下命令实时调试音频配置（命令立即生效，但在系统重启后失效）：

```sh
# sysctl dev.hdaa.0.nid26_config="as=1 seq=0"   # 设置 HDA 声卡节点 26 的音频流为通道 1，序列号 0
# sysctl dev.hdaa.0.nid27_config="as=1 seq=15"  # 设置 HDA 声卡节点 27 的音频流为通道 1，序列号 15
```

* `as=1`：将两者放到同一个关联里。
* `seq=0`：主输出（扬声器）。
* `seq=15`：耳机，插入耳机时会自动静音扬声器。

此时发现已经有声音了，编辑 `/boot/device.hints` 文件，加入以下若干行，将其固化为永久设置：

```ini
hint.hdaa.0.nid26.config="as=1 seq=0"    # 配置 HDA 声卡节点 26 的音频流为通道 1，序列号 0
hint.hdaa.0.nid27.config="as=1 seq=15"   # 配置 HDA 声卡节点 27 的音频流为通道 1，序列号 15
```

## OSS 混音器

FreeBSD 提供多种 OSS 混音器工具，用于图形化或命令行环境下调整音频参数：

| GUI 环境 | Port            | 说明                          |
| ------ | --------------- | --------------------------- |
| kde5   | audio/dsbmixer  | 基于 Qt 的图形化混音器，适用于 KDE 桌面环境  |
| gtk    | audio/gtk-mixer | 基于 GTK 的图形化混音器，适用于 GTK 桌面环境 |
| 非图形化   | audio/mixertui  | 基于 TUI 的命令行混音器，适用于无图形化界面的环境 |

## 故障排除与未竟事项

部分特殊声卡需自行编译内核，请参考 Open Sound System. Open Sound System for FreeBSD\[EB/OL]. \[2026-03-25]. <http://www.opensound.com/freebsd.html>.

OSS 作为底层音频接口存在一定技术限制：其设计未提供音频流回环机制，因此在使用 `obs-studio` 等软件时无法直接录制 OSS 的输出音频。根据官方论坛说明，可使用 `virtual_oss` 工具模拟音频设备实现该功能（通过 `virtual_oss` 的 `-M` 参数进行声道路由，将 OSS 输出重定向到 OSS 输入）。

`obs-studio` 可录制 PulseAudio 的输出音频（默认的“桌面音频”输入源对应 PulseAudio 输出）。因此，部分软件可配置为使用 PulseAudio 作为音频输出接口。使用 PulseAudio 的软件，其音频输出不受上述 OSS 命令控制，需使用 PulseAudio 混音器进行设备管理。

在 KDE 5 环境中，自带的音频控制器在切换设备时，实际上是在控制 PulseAudio 的配置。

官方打包的部分多媒体软件支持 PulseAudio，但其中大多数软件默认未启用对应的编译选项。如果需要录制软件的音频输出，可以在 Ports 中启用相应的编译选项并自行编译。在软件中设置 PulseAudio 作为音频驱动输出即可。

## AMD CPU mode 2 reset

已知在使用 AMD APU（加速处理单元，Accelerated Processing Unit）上使用 drm‑kmod 图形驱动时，打开未加载媒体内容的空播放器窗口可能会触发显示驱动的 mode 2 reset 报错，即驱动重置机制，严重时可能导致 Kernel Panic（内核恐慌）。该问题与驱动对空渲染上下文初始化有关。

请避免打开未加载任何媒体内容的播放器窗口或音频播放器窗口。

音频文件建议通过终端中的命令行方式进行播放。

由于样本数量不足，目前尚未提交相关 Bug（缺陷）报告。

## 课后习题

1. 查找 virtual\_oss 源代码，构建并配置它以实现 OBS Studio 录制 OSS 输出音频的功能，验证录制结果并分析该方案如何绕过 OSS 的录制限制。
2. 选取文中某声卡配置示例（如示例 3），在 QEMU 中重现该配置并验证声音输出。
3. 修改默认的 PulseAudio 全局占用策略（如禁用 KDE 6 的 PulseAudio 默认绑定），尝试切换到 PipeWire 后端，验证其是否能正常工作。
