带有外部声音适配器的 Pulseaudio:解决损坏的声音

Sté*_*hon 3 ubuntu xfce pulseaudio audio-volume

我在带有内置声卡的笔记本电脑上使用外置 USB 声音适配器。有一些问题:

  • 默认情况下,应用程序继续使用内部声卡。我可以通过打开pavucontrol:转到“输出设备”,找到适配器输出并单击“设置为后备”,有时在“播放”选项卡中找到已经在播放的应用程序并更改其接收器来手动解决此问题。

  • 键盘音量按钮仍然在内部声卡上工作,而不是在外部适配器上。

  • 该适配器具有物理音量增大、减小和切换静音按钮。按下时,系统会执行预期的操作,但会在内部声卡上执行,而不是在外部适配器上执行。还有一个麦克风静音按钮,未经测试。
  • 使用pavucontrol工作设置外部适配器的音量,但如果设置低于 35%,则根本没有声音。由于音量很大,35%对于安静的声源就可以了,对于响亮的源是不可接受的。我可以通过设置每个应用程序的音量限制(在pavucontrol窗口中单击)来手动解决此问题,但它很乏味,并且每当应用程序启动新流时都必须重做。

如何拥有:

  • (1) 应用程序默认播放到该适配器
  • (2) 键盘音量按钮适用于选定的声卡(此处为适配器)
  • (3) 物理适配器按钮适用于选定的声卡(此处为适配器)
  • (4) 适配器的音量设置可以在不直接静音的情况下降到 35% 以下

系统是运行 XFCE 4.10 的 Ubuntu 14.10。适配器是“ID 0d8c:000c C-Media Electronics, Inc. 音频适配器”

Sté*_*hon 5

我有一个实验性的解决方法。

首先获取适配器接收器名称

第一个必须找出适配器的接收器名称。打开一个壳。我们将bash通过切换到默认语言环境来假设并防止任何本地化问题:

export LC_ALL=C 
Run Code Online (Sandbox Code Playgroud)

要获取接收器列表:

pacmd list-sinks | grep name:
Run Code Online (Sandbox Code Playgroud)

您可以读取输出并将名称手动复制粘贴到命令行中: ADAPTER_SINK_NAME=name_in_your_setup

更自动地,下面的行会找到第一个非 pci 适配器的名称,这对我有用,并且在许多情况下都可以使用。

ADAPTER_SINK_NAME=$( pacmd list-sinks | sed -n 's/^.*name: <\([^>]*\.usb[^>]*\)>$/\1/p' | head -n 1 )
echo $ADAPTER_SINK_NAME
Run Code Online (Sandbox Code Playgroud)

替代使用pactl(但请运行export上面的行,否则在非默认语言环境中将找不到任何内容):

ADAPTER_SINK_NAME=$( pactl list sinks | sed -n 's/^.*Name: \(.*\.usb.*\)$/\1/p' | head -n 1 ) 
echo $ADAPTER_SINK_NAME
Run Code Online (Sandbox Code Playgroud)

获得部分修复 (1) (2) (3)

现在这将提供问题的 (1) (2) (3) 点:

pactl set-default-sink $ADAPTER_SINK_NAME
Run Code Online (Sandbox Code Playgroud)

有趣的是,我首先使用pacmd set-default-sink ...(pacmd而不是pactl) 它提供了 (2) 和 (3) 但并不总是 (1)。

获得完整的修复 (1) 到 (4)

它基于我可以使用 PulseAudio 同时播放两个声卡上的音乐吗?虽然原则是“同时在一张声卡上播放”。;-)

pacmd load-module module-combine sink_name=adapter-soft-volume slaves=$ADAPTER_SINK_NAME
pactl set-default-sink adapter-soft-volume
Run Code Online (Sandbox Code Playgroud)

现在一切都按照问题中的要求工作。

清理。

如果多次运行上面的命令,将会有多个组合接收器,并且将使用第一个,而不是最后一个。如果出于任何原因您想重新开始,请首先运行此命令以清理合并的接收器:

pacmd unload-module module-combine
Run Code Online (Sandbox Code Playgroud)

如果你想继续,现在不要使用清理

奖励:将当前播放的流移动到适配器

上面的命令适用于新流,而不是那些已经在播放的流。这将调整所需的内容:

for SINK_ID in $(pactl list sink-inputs | sed -n 's/^Sink Input #\([0-9]*\)$/\1/p')
do
    echo Sink $SINK_ID
    pactl move-sink-input $SINK_ID $ADAPTER_SINK_NAME
    pactl move-sink-input $SINK_ID adapter-soft-volume
done
Run Code Online (Sandbox Code Playgroud)

它将尝试移动所有接收器输入,包括会导致圆形路径的组合输入。幸运的是,pulseaudio 会做正确的事情并打印Failure: Invalid argument一次以表明这一点。

自动化的东西

这是提供好处 (1) 到 (4) 的脚本。您可能想move-sink-input从上面添加。每当插入适配器时让它运行可能会很有趣。

#!/bin/bash

export LC_ALL=C

ADAPTER_SINK_NAME=$( pacmd list-sinks | sed -n 's/^.*name: <\([^>]*\.usb[^>]*\)>$/\1/p' | head -n 1 )

if [[ -z "${ADAPTER_SINK_NAME:-}" ]]
then
    ADAPTER_SINK_NAME=$( pactl list sinks | sed -n 's/^.*Name: \(.*\.usb.*\)$/\1/p' | head -n 1 ) 
fi

echo will plug on $ADAPTER_SINK_NAME

# partial fix, can be run anyway to provide partial benefit if later steps fail
pactl set-default-sink $ADAPTER_SINK_NAME

pacmd unload-module module-combine # not useful first, used to clean things up if run several times

pacmd load-module module-combine sink_name=adapter-soft-volume slaves=$ADAPTER_SINK_NAME
pactl set-default-sink adapter-soft-volume
Run Code Online (Sandbox Code Playgroud)