Multichannel Audio Devices and Linux (not a love story)

Something has been bothering me for some time since moving to PipeWire on my Linux boxes, and that is the way multichannel audio devices are handled. As we all know (and loath), Linux audio is complicated and terrible. That’s why we use it, because we hate ourselves. But the upshot is that it gives us a lot of control and the possibility of extremely low latency — critical to realtime audio recording, processing, programming, etc.

Anyway.

The Problem

You may find yourself on a new Linux box (or a fresh or updated install) and find that your multichannel audio device presents itself as a 2-channel duplex device (two-in, two-out.) Worse, it may just appear as a MIDI device. Worser (even worse than worse still), it might not appear at all. Such was the case when i plugged my RME Babyface Pro into my Arch Linux ThinkPad for the first time.

It. Simply. Didn’t. Exist.

Now you may have noticed that, when searching the internet for esoteric knowledge related to Linux and audio that few, if any, search examples remotely match your specific problem*. You also know those results are anywhere from 2-10 years old. Also, they all disagree with each other. (And they all have “solutions” that contradict each other. And the solutions are all for different versions of the programs…)

I’ll spare you the gory details of the troubleshooting I did as it probably won’t tell you anything that you don’t already know — Linux audio is awful. (And we love it!) Suffice to say, I have a Babyface interface where I can access inputs on line 3/4 and its usable in every way I need it to be. I have a few troubleshooting tips at the bottom that hint at my methodology. But first…

The Solution (to *my* problem…)

If you find yourself in the situation I did above, you might find your solution here:

https://wiki.archlinux.org/title/PipeWire#Troubleshooting

I use WirePlumber for my PipeWire session management, so I used this solution:

in ~/.config/wireplumber/main.lua.d/50-alsa-config.lua 
...
alsa_monitor.rules = {
    {
        ...
        apply_properties = {
            -- Use ALSA-Card-Profile devices. They use UCM or the profile
            -- configuration to configure the device and mixer settings.
            -- ["api.alsa.use-acp"] = true,
 
            -- Use UCM instead of profile when available. Can be
            -- disabled to skip trying to use the UCM profile.
            ["api.alsa.use-ucm"] = true,
...

By commenting out the ["api.alsa.use-acp"] = true line and uncommenting the ["api.alsa.use-ucm"] = true line my RME device automagically appeared with all channels present and accounted for (after a reboot…)

There is another way to do this that’s very straightforward if you are using a system that uses Pulse and therefore (probably) the pulseaudio control applet. If you have pulseaudio control (pavucontrol) you can open it and select the Babyface Pro and change it from 2-channel duplex to “Pro” mode, which exposes all the channels. (This Pro Audio setting is an ACM profile that exposes all I/O of the device.)

But what’s going on? Why the obfuscation? ALSA? PULSEAUDIO? I THOUGHT I WAS USING PIPEWIIIIIREEEEE!!!!!????

ALSA Card Profiles

This stuff gets really into the weeds, but essentially the ALSA Card Profile (or ACP) is a way of presenting your audio device to the system in a way that makes it maximally compatible with most use cases.

https://pipewire.pages.freedesktop.org/wireplumber/configuration/alsa.html#device-properties

Use the ACP (alsa card profile) code to manage the device. This will probe the device and configure the available profiles, ports and mixer settings. The code to do this is taken directly from PulseAudio and provides devices that look and feel exactly like the PulseAudio devices.

On Arch, these come from this package (https://archlinux.org/packages/extra/x86_64/alsa-card-profiles/) that gets installed along with PipeWire (and its dependencies.)

There are some side-effects here, however, especially if you don’t have or want PulseAudio on your system or want to minimize its presence. The skinny on this method of determining what to present to your system (of a device’s IO) is that, depending on your sound card, you basically get 2-in and 2-out no matter what.

The profiles also probe the card for the number of channels and their layout. It only supports up to 8 channels, so it doesn’t work for Pro Audio cards.

Safe(ish), but lazy. And in the case of multi-channel IO devices, almost certainly not what you want.

ALSA Use Case Configuration

An even better, newer, and more complicated (and therefore betterer still) way to do things is to use the UCM configs. The Use Case Configuration (https://alsa-project.org/alsa-doc//alsa-lib/group__ucm__conf.html) is a set of config files from the package alsa-ucm-conf that gets installed by default. (It’s required by alsa-lib.) What’s in those files, you ask?

Checking the installed files here (https://archlinux.org/packages/extra/any/alsa-ucm-conf/) shows a list of configurations for existing devices, some from companies that should be familiar to you…

usr/share/alsa/ucm2/USB-Audio/
usr/share/alsa/ucm2/USB-Audio/Arturia/
usr/share/alsa/ucm2/USB-Audio/Arturia/Minifuse-12-HiFi.conf
...
usr/share/alsa/ucm2/USB-Audio/Behringer/
usr/share/alsa/ucm2/USB-Audio/Behringer/Flow8-Recording-Hifi.conf
usr/share/alsa/ucm2/USB-Audio/Behringer/Flow8-Recording.conf
...
usr/share/alsa/ucm2/USB-Audio/Dell/
usr/share/alsa/ucm2/USB-Audio/Dell/Desktop-Front-Speaker-Headset.conf
usr/share/alsa/ucm2/USB-Audio/Dell/Desktop-Front.conf
...
usr/share/alsa/ucm2/USB-Audio/Digidesign/
usr/share/alsa/ucm2/USB-Audio/Digidesign/Digidesign-Mbox-3-HiFi.conf
usr/share/alsa/ucm2/USB-Audio/Digidesign/Digidesign-Mbox-3.conf
usr/share/alsa/ucm2/USB-Audio/Focusrite/
usr/share/alsa/ucm2/USB-Audio/Focusrite/Scarlett-2i-HiFi.conf
usr/share/alsa/ucm2/USB-Audio/Focusrite/Scarlett-2i.conf
...
usr/share/alsa/ucm2/USB-Audio/MOTU/
usr/share/alsa/ucm2/USB-Audio/MOTU/M2-HiFi.conf
usr/share/alsa/ucm2/USB-Audio/MOTU/M2.conf
usr/share/alsa/ucm2/USB-Audio/MOTU/M4-HiFi.conf
...
usr/share/alsa/ucm2/USB-Audio/Rane/
usr/share/alsa/ucm2/USB-Audio/Rane/SL-1-HiFi.conf
usr/share/alsa/ucm2/USB-Audio/Rane/SL-1.conf
usr/share/alsa/ucm2/USB-Audio/Realtek/
usr/share/alsa/ucm2/USB-Audio/Realtek/ALC1220-VB-Desktop-HiFi.conf
usr/share/alsa/ucm2/USB-Audio/Realtek/ALC1220-VB-Desktop.conf
usr/share/alsa/ucm2/USB-Audio/Realtek/ALC4080-HiFi.conf
usr/share/alsa/ucm2/USB-Audio/Realtek/ALC4080.conf
usr/share/alsa/ucm2/USB-Audio/Roland/
usr/share/alsa/ucm2/USB-Audio/Roland/BridgeCast-Hifi.conf
usr/share/alsa/ucm2/USB-Audio/Sony/
usr/share/alsa/ucm2/USB-Audio/Sony/Inzone-H9-H7-HiFi.conf
usr/share/alsa/ucm2/USB-Audio/Sony/Inzone-H9-H7.conf
usr/share/alsa/ucm2/USB-Audio/Steinberg/
usr/share/alsa/ucm2/USB-Audio/Steinberg/UR24C-HiFi.conf
usr/share/alsa/ucm2/USB-Audio/Steinberg/UR24C.conf
usr/share/alsa/ucm2/USB-Audio/Steinberg/UR44-HiFi.conf
usr/share/alsa/ucm2/USB-Audio/Steinberg/UR44.conf
usr/share/alsa/ucm2/USB-Audio/USB-Audio.conf

Interestingly enough, there is no entry for RME here at all. Turning off the ACP option results in a kind of “raw” reporting of IO, which explains the lack of sensical names for the input and output channels. This is probably why UCM isn’t enabled by default, but I’d rather see all my channels labeled weirdly than not see them at all! And, of course, if I had nothing better to do, I could write that config myself… maybe even submit it to help out the community… or at least stick it up on my GitHub page…

So why don’t I?? There’s a write-up here about creating ALSA UCM files for your devices. Have a look (god help you…)

https://wiki.postmarketos.org/wiki/Alsa_UCM

Troubleshooting tips (or: pulling apart the pie)

One of the most irritating parts of troubleshooting audio on Linux is you can never be quite sure where things are going wrong. If you aren’t seeing a device, or the right number of channels, is it a problem with PipeWire configuration? WirePlumber? ALSA? JACK?

Ultimately, you have to work your way down to find out. What I mean by that is determining at what level you stop or start seeing the hardware device (if you do at all.) You can get a quick high-level view of your audio devices and connections using either qjackctl or qpwgraph. If you do see your device, but it’s not connected to anything, you can simply connect inputs to outputs as you need to route audio as you like. If you don’t see your device here, or it has the wrong number of channels, you have to go down.

ALSA sits at the bottom of the Linux audio stack.

https://user-images.githubusercontent.com/45159366/142779615-d631251b-a2d6-48b4-8194-7985604a8563.png

If ALSA isn’t getting your device description right, nothing else can. Period. So starting with ALSA is a safe bet. There are many utilities built-in to most systems (or gotten by installing the alsa-utils package) for getting insights into what you have available to your system.

aplay -l

shows (among my other devices)

card 2: Pro70784666 [Babyface Pro (70784666)], device 0: 
USB Audio [USB Audio]   Subdevices: 1/1   Subdevice #0: subdevice #0

aplay -L

shows more:

sysdefault:CARD=Pro70784666
Babyface Pro (70784666), USB Audio
Default Audio Device

front:CARD=Pro70784666,DEV=0
Babyface Pro (70784666), USB Audio
Front output / input

surround21:CARD=Pro70784666,DEV=0
Babyface Pro (70784666), USB Audio
2.1 Surround output to Front and Subwoofer speakers

surround40:CARD=Pro70784666,DEV=0
Babyface Pro (70784666), USB Audio
4.0 Surround output to Front and Rear speakers

...

There are ways to test these devices by plugging in a combination of changed device names into aplay with the -D option.

You use aplay -l to get your cards, and use hw: followed by the card number (2) and then the device number (0) which looks like hw:2,0. Magical. Except this doesn’t work if you are using PipeWire — ALSA will give a ‘resource busy’ message. You can pipe through PipeWire if PipeWire has the device as default…

aplay -D pipewire TESTFILE.wav

… but that’s little use if the device is not seen. With a little more typing you can specify the device as long as PipeWire sees it. In this code from the WirePlumber documentation shows how you can record a file through a device and then play back through the same. Of course, you can always start with your own test sound.

wpctl status  # find the capture & playback endpoint ids

PIPEWIRE_NODE=<endpoint_id> arecord -D pipewire -f S16_LE -r 48000 test.wav

PIPEWIRE_NODE=<endpoint_id> aplay -D pipewire test.wav

// from here: https://pipewire.pages.freedesktop.org/wireplumber/testing.html

You can also use ‘play’ if you install the sox application, which I highly recommend anyway as it’s useful for a ton of things from batch processing to adding quick FX to files.

Last, I recommend turning it off and back on again. This is not a joke. Hot-plugging audio devices into running configurations (got qpwgraph open, Ardour, etc.) is a toss up. Save. Close things out. Turn off your machine. Plug your device in. Turn it back on. This is often enough to at least get ALSA to see your device and report to PipeWire. Use wpctl status as above to verify you can see your hardware.

Conclusion

If you are interested in a digestible, but comprehensive overview of the Linux Audio Stack, there’s a comprehensive and great (if now slightly outdated) write up here:

Making Sense of The Audio Stack On Unix

If you just want a fix NOW and don’t care to know much about your Linux audio subsystem 😖 then a good bet might be as easy as a subreddit for either your system or for Linux audio.

https://www.reddit.com/r/archlinux/ (my system)

https://www.reddit.com/r/linuxaudio/

I also really like Linux Musicians, but have to admit I have not done much solution shopping there.

https://linuxmusicians.com/

One last note. Above, when I link to programs, I’m just doing a quick Duckduckgo.com search and going with the home page for the project. *In almost all cases* you will want to install these packages using your package manager of choice. This is one lovely reason I prefer Arch: the AUR has everything. If it’s open source, it’s there and it works.

If you liked this article mash the subscribe button here. It might deliver an email to you when I post new content. It might not! I can’t tell! But hey, it’s worth a shot!