3

I'm using an external USB sound adapter on a laptop that has an internal sound card. There are some issues:

  • The applications by default continue to use internal sound card. I can work around this manually by opening pavucontrol: going to "output devices", finding the adapter output and clicking on "set as fallback", and sometimes finding an already playing application in "Playback" tab and changing its sink.

  • The keyboard volume buttons still operate on the internal sound card, not the external adapter.

  • The adapter has physical volume-up,down and toggle-mute buttons. When pressed, the system performs the expected actions, but on the internal sound card, not the external adapter. Also a microphone mute button, untested.
  • Setting volume of the external adapter using pavucontrol works but if set below 35% there's no sound at all. Since the volume is very loud, 35% is just okay for quiet sound sources, unacceptable for loud sources. I can work around this manually by setting per-application volume limiting (clicking in pavucontrol window), but it's tedious and has to be redone whenever an application starts a new stream.

How to have:

  • (1) applications play to that adapter by default
  • (2) the keyboard volume buttons work on a chosen sound card (here, the adapter)
  • (3) the physical adapter buttons work on a chosen sound card (here, the adapter)
  • (4) volume setting for the adapter that can go below 35% without going straight to silence

System is Ubuntu 14.10 running XFCE 4.10. Adapter is "ID 0d8c:000c C-Media Electronics, Inc. Audio Adapter"

2 Answers 2

5

I have an experimental workaround.

First get adapter sink name

First one has to figure out the sink name for the adapter. Open a shell. We'll assume bash and prevent any localization issue by switching to the default locale:

export LC_ALL=C 

To get a list of sinks:

pacmd list-sinks | grep name:

You can read the output and copy-paste manually the name into a command line: ADAPTER_SINK_NAME=name_in_your_setup

More automatically, the line below finds the name of the first non-pci adapter, which will work for me and should work in many cases.

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

Alternative using pactl (but do run the export line above or it won't find anything in non-default locales):

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

Get partial fix (1) (2) (3)

Now this will provide points (1) (2) (3) of the question:

pactl set-default-sink $ADAPTER_SINK_NAME

Interestingly, I first used pacmd set-default-sink ... (pacmd instead of pactl) which provided (2) and (3) but not always (1).

Get full fix (1) to (4)

It's based on Can I use PulseAudio to playback music on two sound cards simultaneously? though the principle is rather to play on "one sound card simultaneously". ;-)

pacmd load-module module-combine sink_name=adapter-soft-volume slaves=$ADAPTER_SINK_NAME
pactl set-default-sink adapter-soft-volume

Now everything works as requested in the question.

Clean-up.

If you run the commands above several times, there will be several combine sinks and the first one will be used, not the last one. If for any reason you want to start over, first run this to clean up the combined sink:

pacmd unload-module module-combine

Don't use the cleanup now if you want to continue

Bonus: move currently playing streams to the adapter

Command above work for new streams, not those already playing. This will adjust what's needed:

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

It will try to move all sink inputs, including the combined one which would cause a circular path. Fortunately, pulseaudio will do the right thing and print Failure: Invalid argument once to indicate that.

Automate the thing

Here's the script providing benefits (1) to (4). You might want to add the move-sink-input from above. It might be interesting to have it run whenever the adapter is plugged it.

#!/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
5
  • 1
    Yeah, many thanks for this. I finally get volume buttons with my external USB sound card. However, it seems there is a typo in the final script the definition of ADAPTER_SINK_NAME is not the same that is explained previously in the answer. It worked with ADAPTER_SINK_NAME=$( pactl list sinks | sed -n 's/^.*Name: \(.*\.usb.*\)$/\1/p' | head -n 1 ) not ADAPTER_SINK_NAME=$( pacmd list-sinks | sed -n 's/^.*name: ]*\.usb[^>]*\)>$/\1/p' | head -n 1 )
    – mperrin
    Aug 31, 2015 at 16:06
  • @mperrin Thank you for your comment. Both variants worked for me, I'd like to know why one did not work for you. What's your system ? Can you show the output of pactl list sinks and pacmd list-sinks ? Thanks. Sep 1, 2015 at 6:25
  • There was a typo in ADAPTER_SINK_NAME=$( pactl list sinks | sed -n 's/^.*Name: \(.*\.usb.*\)$/\1/p' | head -n 1 ), the \) is not matched with a \(. Dec 16, 2016 at 17:50
  • Anyway, thanks for your solution. It fixes my USB sound card. Dec 16, 2016 at 17:54
  • 1
    Wow, there was a problem that looked like a typo. Subtly, SO behaves differently whether you surround your code with PRE HTML tag or indent it four-space. The former would interpret any less-than character as HTML tag, the latter would not. Switched to the latter. Thanks to commenters. Dec 17, 2016 at 5:37
1

In response to point 4, no sound below 35% volume.

Same issue, different distribution (Fedora, not Ubuntu). The commands explained in the existing answer (set-default-sink...) unfortunately don't help in this case.

On Fedora 22, modifying a config file did the job:

Config file: /usr/share/pulseaudio/alsa-mixer/paths/analog-output.conf.common

Look for the [Element PCM] section:

[Element PCM]
switch = mute
volume = merge
override-map.1 = all 
override-map.2 = all-left,all-right

Replace the "volume = merge" line with these two lines:

volume = ignore
volume-limit = 0.01

Reload pulseaudio:

$ pulseaudio -k

Restart your audio player and try again.

From: https://chrisjean.com/fix-for-usb-audio-is-too-loud-and-mutes-at-low-volume-in-ubuntu/

(See bug 1248649.)

However, this workaround does not seem to help anymore with Fedora 23 (pulseaudio 7.1) - or maybe different values have to be used.

Hopefully, this will be helpful to someone.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .