Switch to a USB DAC automatically under pure ALSA

Share your own howto's etc. Not for support questions!

Switch to a USB DAC automatically under pure ALSA

Postby Head_on_a_Stick » 2020-10-11 14:17

PulseAudio will automatically switch the default sound output to a USB connected DAC but a system using pure ALSA will not do this.

Under pure ALSA we need to use a configuration file to set the default audio output device and a udev rule to apply the configuration file when the device is connected.

Setting the default output device

For this guide we are going to use an asound.conf file to apply the configuration system-wide.

First use this command without the device plugged in to see the available audio devices and their ID:
Code: Select all
find /proc/asound -type l -exec basename {} \;

Sample output:
Code: Select all
~$ find /proc/asound -type l -exec basename {} \;
Generic
Generic_1
~$

^ In this example my laptop has an analogue audio output (the laptop speakers, identified as "Generic_1") and an HDMI output (identified as "Generic").

Now plug in the USB DAC and run the command again. Here is the output from my system:
Code: Select all
~$ find /proc/asound -type l -exec basename {} \;
v1
Generic
Generic_1
~$

^ As you can see, the new device has been identified as "v1".

With this information we can create a configuration file to set v1 as the default device:
Code: Select all
pcm.v1 {
   type hw
   card "v1"
}
ctl.!default {
   type hw
   card "v1"
}
pcm.!default {
   type plug
   slave {
      pcm "v1"
      rate "unchanged"
   }
}

^ That is the file for my "v1" card, replace all instances of v1 with the correct identifier for your DAC (as determined by the previous find command).

Save this file to /etc/asound.conf.bak

Creating a udev rule

Now we need a udev rule to copy /etc/asound.conf.bak to /etc/asound.conf so that it is read by ALSA.

To do this we need to find the product name recognised by udev:
Code: Select all
udevadm info -a /sys/class/sound/$(readlink /proc/asound/v1) | grep ATTRS{product}

^ That example presumes that the device is identified as v1, change the identifier to match your DAC.

Sample output from my box:
Code: Select all
~$ udevadm info -a /sys/class/sound/$(readlink /proc/asound/v1) | grep ATTRS{product}
    ATTRS{product}=="AudioQuest DragonFly Cobalt v1.0"
    ATTRS{product}=="xHCI Host Controller"
~$

Now we can write the rule:
Code: Select all
SUBSYSTEM=="usb", ATTRS{product}=="AudioQuest DragonFly Cobalt v1.0", ACTION=="add", RUN+="/bin/cp /etc/asound.conf.bak /etc/asound.conf"
SUBSYSTEM=="usb", ATTRS{product}=="AudioQuest DragonFly Cobalt v1.0", ACTION=="remove", RUN+="/bin/rm /etc/asound.conf"

^ That example uses the product attribute found in the last command, change that to match the results from your system.

Save the rule to /etc/udev/rules.d/00-dac.rules

The rule copies /etc/asound.conf.bak to /etc/asound.conf when the device is added, this "activates" the configuration file. The second line deletes /etc/asound.conf when the device is removed thus "deactivating" the configuration and reverting to the usual audio output device.

See http://reactivated.net/writing_udev_rules.html for a more complete treatment of udev rule implementation.

Finally remove the device and reload the udev rules to apply the new addition:
Code: Select all
# udevadm control --reload

Use 'alsamixer' to confirm that the default output device is changed after the DAC is connected, wait a few seconds for udev to recognise the device and apply the rule.
Black Lives Matter

Debian buster-backports ISO image: for new hardware support
User avatar
Head_on_a_Stick
 
Posts: 12650
Joined: 2014-06-01 17:46
Location: /dev/chair

Re: Switch to a USB DAC automatically under pure ALSA

Postby Head_on_a_Stick » 2020-10-13 16:20

Bumping this because I've just noticed that ALSA resamples the output to 48kHz by default so I've changed the configuration file to prevent resampling and ensure that the audio is passed through unaltered.

If your DAC indicates the incoming sample rates you can check this is working by using this one-liner:
Code: Select all
for rate in 44100 48000 88200 96000; do speaker-test --rate $rate --nloop 1; done

^ That cycles through 44.1kHz (the Red Book standard, as used by music CDs), 48kHz (as used by DAT), 88.2kHz and 96kHz (commonly used for high definition music downloads).
Black Lives Matter

Debian buster-backports ISO image: for new hardware support
User avatar
Head_on_a_Stick
 
Posts: 12650
Joined: 2014-06-01 17:46
Location: /dev/chair


Return to Docs, Howtos, Tips & Tricks

Who is online

Users browsing this forum: No registered users and 7 guests

fashionable