Transitioning to Pipewire on Arch Linux



Published March 31, 2021

May you live in interesting times. Or, alternatively: Good luck getting professional audio properly configured on Linux. At least, this used to be the predicament. Getting ALSA to work together with Jack to work together with PulseAudio is an esoteric business worthy of the deepest forms of black magic. Now, however, the clever human beings at the Gnome project are working on something that might just bring us from the dark ages into an era of enlightenment, at least as far as the end user is concerned: pipewire.

The pipewire promise is one of easy, plug-and-play configuration of all your audio devices. No more worrying about whether your application supports jack, PulseAudio or both. Now you should be able to just run your application, and sound will magically appear from your speakers. Just like that. Last week I decided it was time to check out this fabulous new invention, and so I set about making it work for me. Here’s a preliminary tour of what I found out:

Installation

I wanted the full integration, so I ran:

paru -S pipewire pipewire-{alsa,jack,media-session,pulse,jack-dropin}

All the packages except pipewire-jack-dropin are in the extra repo. pipewire-jack-dropin is in AUR. However, if you prefer, you could simply remove your existing jack/jack2 packages instead of installing the dropin. Replace paru with your preferred AUR helper.

If you, like me, run jack on login, then make sure to disable whatever script you’re currently running. Reboot and you should be good to go.

First Impressions

In short: this is very, very promising. pipewire emulates jack whenever a jack client is launched. No need to manually start a server. Also: For the first time since I abandoned macOS for Linux my computer automatically swapped sound card when I plugged in my Fireface UCX. No fiddling around with custom-made scripts to switch between internal and external interfaces.

I might have gotten a bit more xruns than I would normally gotten, but not show-stoppingly so.

Configuration

There is very little need for any specific configuration, which was almost shocking for a long-time Linux musician. Currently the samplerate of pipewire is fixed globally, and can be set in /etc/pipewire/pipewire.conf. Uncomment this line:

default.clock.rate = 48000

and set it to whatever you want it to be, provided your hardware supports it.

Slightly confusingly, you can also set this for jack in /etc/pipewire/jack.conf, in the jack.properties section.

jack.properties = {
     node.latency = 256/48000
     ...
}

This will give you a default buffer size of 256 samples at a samplerate of 48khz. If your audio interface is not stellar, you’d probably want to go for 512 or even 1024 samples to avoid xruns at the expense of higher latency. If your interface is excellent you might go lower, into the warp speed area of 64 or even 32 samples.

The buffer size can also be set in the client itself. In ardour I was able to set this in the settings. Alternatively you can set an environment variable before running your application:

PIPEWIRE_LATENCY=256/48000 your_application

Notice that this will only change the ratio between buffer size and samplerate. It is not (yet) possible to change samplerate at runtime, so if you try something like this while the jack.properties node.latency is set to 48000:

PIPEWIRE_LATENCY=256/96000 your_application

… you will end up with a buffer size of 128 and a samplerate of 48k. Ratios, ratios, ratios.

Pipewire will resample audio as required to get PulseAudio, jack and ALSA working together.

So, in short: set the samplerate globally, mess around with buffer sizes per application. More details on configuration can be found here

Access All Your I/Os

The default configuration is of the consumer kind, which means stereo in and stereo out. If you invested big money in 18 channels I/O this seems a bit sad. The remedy is to activate the pro profile. I haven’t figured out how to do this on the command line yet, but it’s very easy to do this in PulseAudio Volume Control (PAVU). Go to the Configuration tab, click on the Profile drop-down menu under your card, select Pro Audio and you should be good to go. All the channels should now be available.

Setting External Audio Interface as Default

For some reason all my jack applications insisted on playing back on the internal soundcard by default. The solution was, yet again, found in the PAVU application. Go to the Output Devices tab, find the interface you want to use as default, click on the green checkbox on the right side to make this your default output. Repeat the same steps in the Input Devices.

Individual Control of Channel Levels

The Fireface UCX is a brilliant soundcard in many ways, but on Linux you will only get the class-compliant experience, which means zero control over levels of individual input and output channels on the software side. To set the levels you have to use the rotary encoder in the front of the soundcard, an encoder that has died on me more than once. A very unfortunate weakness, in other words. Now, however, this problem can be mitigated through PAVU. Next to the previously mentioned green checkbox in the Output and Input Devices there is a padlock button. Click on this, and voila! All your input and output stream levels become individually accessible! Of course, it is possible to pull off this kind of trick in any number of jack mixing applications, but the option to do this directly in a central configuration application makes life just a bit easier.

Audacity Troubles

So far, the only major trouble I’ve encountered was that audacity no longer recognized my external audio interface. After a bit of redditing around it turns out that pipewire has issues with long descriptors that mess with its regex capabilities. The solution was to rename the offending piece of hardware. This has the additional benefit of a cleaner namespace in all your mixers, patchbays, whatnot. The procedure goes like this: Figure out what pipewire calls your interface by running pw-cli list-objects. You probably want to pipe this through to less and search for the node.name attribute of your device. In my case this was called “alsa_output.usb-RME_Fireface_UCX__23815246__F9C767BDDD2EEC8-00.pro-output-0”. Which, I agree, does not roll off the tongue. The remedy was to stick this into the bottom of the rules array in /etc/pipewire/media-session.d/alsa-monitor.conf:

    {
        matches = [
            {
                node.name = "~alsa_input.usb-RME_Fireface_UCX.*"
            }
            {
                node.name = "~alsa_output.usb-RME_Fireface_UCX.*"
            }
            ]
            actions = {
                update-props = {
                    node.nick = "Fireface UCX"
                    node.description = "Fireface UCX"
                }
            }
    }

Notice the ~ in front of the alsa_etc. This seems to be necessary for some reason.

I restarted pipewire by issuing

systemctl --user restart pipewire.service

and audacity now saw my Fireface!

Checking For Xruns

I haven’t yet found an easy way to check the xrun count, but pipewire helpfully posts any information about this to the systemd logs. So, to keep an eye on the state of your pipewire instance in real time, you could simple run this in a separate terminal:

journalctl -f | grep pipewire 

This will give you a running commentary on the state of your audio stack. An xrun will look something like this:

Apr 01 10:44:04 t480s pipewire[10997]: (alsa_output.usb-RME_Fireface_UCX__23815246__F9C767BDDD2EEC8-00.pro-output-0-49) client too slow! rate:256/48000 pos:294748928 status:triggered
Apr 01 10:44:04 t480s pipewire[10997]: (alsa_output.usb-RME_Fireface_UCX__23815246__F9C767BDDD2EEC8-00.pro-output-0-49) XRun! rate:256/48000 count:19 time:23386594654 delay:22444 max:22444

EDIT on 4 April 2021: after publishing this, I was made aware of an extremely handy tool that comes bundled with pipewire: pw-top. This lets you monitor all your sinks and sources; their samplerates and buffer sizes, xrun counts, process ids and more. Very useful! Next on my todo-list is to write an xrun-counter for my sway/i3 status bar.

Video Conference

Zoom seems to work without issues or further configuration. I had some trouble getting Jitsi up and running in Firefox. In the Chromium-base Qutebrowser I could make it work after a restart and a segfault in pipewire.

Verdict

It is still early days of development, and hickups are to be expected. However, my overall feeling is that this is a massive improvement on the user experience over what used to be the labyrinthine tangle that professional audio Linux users have had to suffer over the years. I am looking forward to pipewire-native ways of setting samplerates, buffer sizes and so on at runtime, preferably using the command line.

Resources

Pipewire wiki
Arch Linux wikipage on pipewire