Professional audio

Professional audio

For audio production and processing, a system needs to be optimized for low latency using a sound server, such as PipeWire chosen in the Desktop Environment section of the Xfce guide, and audio hardware compatible with ALSA1 (refer to the ALSA SoundCard Matrix).

Today class-compliant2 USB audio interfaces are supported out of the box and most professional audio applications use JACK for low latency operation and signal routing. PipeWire supports these JACK clients. Linuxaudio.org provides extensive but partly outdated documentation about the system configuration, which may help to understand some principles and general guidelines when trying to setup a professional audio environment in general. One of the primary goals is to reduce latency3.

In this guide, I focus the following tasks:

  1. Perform #Preparations to inspect and adapt the system
  2. Optimize the #System configuration to reduce latency
  3. Setup a #Sound server using an USB audio interface
  4. Install and configure a #DAW with:
    1. #Latency tuning,
    2. my favorite #Plugins and
    3. public domain #Samples.

Preparations

⚠️
The adaptions in this guide require you to have or gain some knowledge on technical details of your hardware and understanding of the software that is going to be used. Considering the scope and depth of this guide ask yourself, if you are willing and if you can take the time to follow this guide for setting up a system of your own or if you just want to start creating music without taking a closer look at pro audio from the technical side of things. I encourage you to rather begin with a preconfigured distribution such as Ubuntu Studio, if you are new to this topic.

Based on the preconfigured Xfce desktop and a basic setup of the Sound system as described in the guide on Multimedia and web the first step in building a pro audio environment is to analyze the current system configuration to identify required adaptions. Some settings need to be tweaked for using full system resources and improving the performance for hardware access. Most of these optimizations are documented in the Professional audio article of the ArchWiki and rtcqs can check which of them are required.

Proaudio repository

Though there is an AUR package for rtcqs, I prefer and suggest to use the unofficial proaudio repository by OSAMC. I add the following lines to the /etc/pacman.conf file:

/etc/pacman.conf
[proaudio]
Server = https://arch.osamc.de/$repo/$arch

I download, import and sign the current signing key:

curl https://arch.osamc.de/proaudio/osamc.gpg | sudo pacman-key --add -
sudo pacman-key --lsign-key 762AE5DB2B38786364BD81C4B9141BCC62D38EE5

System analysis

Finally, I can install the rtcqs package via the OSAMC proaudio repo:

yay -Syu rtcqs
ℹ️
Browse the list of packages to find other packages available in the proaudio repo.

And execute it afterwards:

rtcqs

The tool provides a detailed overview on the system configuration regarding the latency and suggests adapations or refers to documentation for optimization.

System configuration

In my case, the rtcqs tool reported a WARNING for:

The next sections describe the above warnings more detailed and evaluate, if adaptions to the system configuration are necessary or have to be traded off.

Group limits

User resources are limited through PAM4 by /etc/limits.conf. However, the default settings are to low for typical audio applications and tools. Instead of manually adapting the configuration file I can escelate to install the package realtime-privileges, which creates a realtime group:

sudo pacman -S realtime-privileges

Afterwards I can add myself to this new group using:

sudo gpasswd -a thisven realtime

and must re-login to apply changes immediatly.

CPU frequency scaling

CPU frequency scaling is used to save power or improve the performance on demand. However, switiching between different profiles during a recording can lead to xruns5. For this reason best practice is to statically set the scaling governor to performance. I prefer to use cpupower, a user space frequency scaler, to change the scaling governor in scripts extecuted before starting JACK and after shutting it down. I install the cpupower package:

sudo pacman -S cpupower

The command to set the scaling governor to performance is:

sudo cpupower frequency-set -g performance

and the following command sets it back to powersave:

sudo cpupower frequency-set -g powersave

I add its commands for setting the scaling governor to performance and powersave as a passwordless cmd in the /etc/sudoers file right below the existing line configured in the Sudo, not su section of the Basic configuration guide:

/etc/sudoers
# Allow group wheel to set cpupower governor
%wheel ALL= NOPASSWD: /usr/bin/cpupower frequency-set -g performance,/usr/bin/cpupower frequency-set -g powersave
ℹ️
You may want to append other commands to automatically stop Wi-Fi, for example. For more information about how other applications could interfere see further tips in the ArchWiki.

Preempt RT

Since kernel version 6.0 there’s no need for Realtime kernel (RT kernel) as the mainline kernel can be configured to provide the level of preemption necessary to achieve lower latencies.

Kernel parameter threadirqs

Though threaded interrupt handlers are a specific feature of the Realtime kernel, the mechanism can be enabled for a mainline kernel at boot time. I add the parameter threadirqs to the options line in the loader file, which has been created in the Systemd-boot installation section of the System preparation guide. My final /boot/loader/entries/linux.conf looks like this:

/boot/loader/entries/linux.conf
title   Linux
linux   /vmlinuz-linux
initrd  /initramfs-linux.img
options cryptdevice=UUID=<MyUuid>:lvg resume=/dev/lvg/swap root=/dev/lvg/root quiet rw threadirqs

Note that <MyUuid> is just a placeholder for the actual UUID of my LUKS partition and the threadirqs parameter is appended to the end of line. Reboot to enable threaded interrupt handlers before proceeding!

ℹ️
Alternatively, you can install and switch to booting a full RT kernel. However, a realtime kernel may induce delayed updates due to patching and there are some features missing on purpose handy for other use cases. See pros and cons in the ArchWiki for more information.

Manual IRQ handling

To adjust priorities of IRQ handling threads I install the rtirq package and the rtapp package from the AUR:

sudo pacman -S rtirq
yay rtapp

The rtirq service must be started and enabled manually:

sudo systemctl start rtirq
sudo systemctl enable rtirq

I connect my USB audio interface and wait for its initialization before using the following command:

sudo rtcards

In the output two devices are identified as AUDIO CARDS and in the USB INTERRUPTS AND DEVICES section my USB audio interface appears at USB3 IRQ=151 identified by a fragment of its NAME.

As this USB device is a xHCI host controller the configuration file /etc/rtirq.conf needs to be adjusted to for realtime priority. I change the RTIRQ_NAME_LIST line to:

/etc/rtirq.conf
RTIRQ_NAME_LIST="xhci"

and restart the rtirq service:

sudo systemctl restart rtirq

In the output of the command:

sudo rtstatus

the IRQ 151 of the USB audio interface should now get a higher priority.

Spectre/Meltdown mitigations

I choose to ignore this warning as the security of my system is more important than gaining some performance. The capabilities of modern CPUs are sufficient anyway.

RT priorities

This warning will be gone as I already configured #group limits as described before.

Swappiness

The swappiness6 (aka swap frequency) is a parameter to control when the Linux kernel escalates to disk space for swapping opposed to dropping pages from the system page cache. Setting it a lower value, such as 10, makes the system wait much longer before trying to swap to disk. I reduce swappiness, increase inotify watches, and the RTC intermath: truerupt frequency by installing realtime-generic-setup from the AUR:

yay realtime-generic-setup

Afterwards the service has to be enabled and started:

sudo systemctl enable realtime
sudo systemctl start realtime

Filesystems

The boot partition is mounted at /boot as configured in the System preparation guide (Formatting and mounting section) this warning can be ignored. This is also a good example of outdated information on linuxaudio.org as in the reference on filesystems the advice is to simply not use disk encryption at all to save CPU resources. Today these bottlenecks are rather negligible.

Power Management

Different sleep states and the wakening process in modern CPUs can cause latency and a #DAW can take advantage of controlling registering a value of 0 to tell the CPU to never got to sleep in order to avoid these latencies. For this reason a udev7 rule from the Ardour project is saved in /etc/udev/rules.d:

sudo curl --output /etc/udev/rules.d/99-cpu-dma-latency.rules https://raw.githubusercontent.com/Ardour/ardour/master/tools/udev/99-cpu-dma-latency.rules

If you want to review the rules first, check the file contents at: https://github.com/Ardour/ardour/blob/master/tools/udev/99-cpu-dma-latency.rules

To make this rule work I verify that I am a member of the audio group:

groups | grep audio
ℹ️

If there is no output, I need to add myself to the audio group using:

sudo gpasswd -a thisven audio

I reload the udev rules afterwards to immediatly apply the changes:

sudo udevadm control --reload-rules
sudo udevadm trigger

Sound server

In the center of audio applications the JACK audio server guarentees low latency operation, signal routing and connection management. The different versions of JACK8 originate from its history and may be one reason for a lot of confusion in this use case. However, since PipeWire supports JACK clients and is a drop-in replacement to it a best practice is to not install any JACK packages but keep working with the applications (the JACK clients). In the next sections I will refer to JACK a lot of times. Keep in mind that “under the hood” PipeWire or more specific pipewire-jack, which has been installed in the Desktop environment section of the Xfce desktop guide, is managing audio as a sound server in the context of the sound system9.

ℹ️
It’s not strictly necessary to configure a sound server for a #DAW as it can directly use ALSA. In terms of complexity, it might be easier to go this way at first glance, gain experience with recording in your desired DAW and incorporate a sound server later. However, keep in mind that the DAW will access your audio interface excusively in this case. This means that you are not able to playback and record sounds from other applications!

PipeWire profile

With the Xfce panel applet xfce4-pulseaudio-plugin and pavucontrol installed in the #Sound system section of the Multimedia and web guide I can set the Pro Audio Profile for my audio interface in the Configuration tab of the mixer window. This profile preconfigures several hardware-related options10 and eases the process of #Reducing the quantum later to achieve a low latency.

pavucontrol configuration profile

Setting a profile for audio interfaces in pavucontrol

Latency evaluation

The hardest part in achieving low latency is to evaluate optimal parameters depending on the capabilities of the audio interface. You should be familiar with the details about how latency occurs when using audio interfaces as Audio-to-Digital Converter (ADC) and Digital-to-Audio Converter (DAC).

The main parameters regarding to latency (frames, periods, sample rate) are described by this function:

$L = \frac{n \times p}{f}$

$L:$ Latency in miliseconds (ms),
$n:$ Frames11 or Quantum (multiples of 2, starting at 16),
$p:$ Periods (automatically set to 1 by PipeWire to reduce latency12),
$f:$ Sample or Clock rate in Hertz (Hz).

The capabilities of an audio interface define working combinations. You have to trial and error to find a working setup. The task is to find optimal settings to reduce latency as much as possible without xruns (audio drop-outs).

Using a high clock rate

Sure, it’s a trade-off between xrun prevention and higher latency, but most recent audio interfaces can be used at high sample rates (up to 384 kHz) decreasing the resulting latency through a high denominator value in the aforementioned function.

I can retrieve the sample rates for playback and capture of my plugged in USB audio interface using:

grep -E 'Playback|Capture|Rates' /proc/asound/card1/stream0
ℹ️
My built-in audio interface is detected as the first ALSA device (card0). Keep in mind that your audio interfaces may be detected in a different order.

In comparison with the product specification of my audio interface the supported sample rates are indeed: 44100 Hz, 48000 Hz, 88200 Hz, and 96000 Hz. PipeWire uses a sample rate of 48000 Hz (48 kHz) per default. I can verify this with:

pw-metadata --name settings | grep clock.rate

However, to allow the other sample rates I create a /etc/pipewire/pipewire.conf.d/custom.conf file containing:

/etc/pipewire/pipewire.conf.d/custom.conf
context.properties = {
    default.clock.allowed-rates = [ 44100 48000 88200 96000 ]
}

To actually change the default sample rate to 96 kHz this command can be used:

pw-metadata --name settings 0 clock.rate 96000

Reducing the quantum

The frames or buffer size is another parameter in relation to latency that needs to be tuned. In the context of PipeWire it is called Quantum. The default value of 1024 is rather high and can be read using:

pw-metadata --name settings | grep clock.quantum

As the default behaviour of PipeWire is to dynamically adapt the quantum size during runtime the clock.min-quantum and clock.max-quantum values define the range. However, PipeWire does not use this strategy for JACK clients. It rather leaves this task to the application itself or to the user. Consequently, each JACK client needs to be capable of changing these parameters when using pipewire-jack. Though this seems to be counter-intuitive when you are already used to the concept of a JACK server that guarantees fixed frames, periods and sample rate parameters, this allows you to run JACK applications more flexible.

You can either change and lock the buffer size to a fixed value, such as 128, by using:

pw-metadata --name settings 0 clock.force-quantum 128

or set the environment variable PIPEWIRE_QUANTUM=128/48000 to start the application using a sample rate of 48 kHz and a buffer size of 128. To further evaluate which quantum value is a good trade-off it is a best practice to simulate a recording session in the following section, for example.

Systemic latency

For recording overdubs in a #DAW the systemic latency13 must be set. It adds to the round-trip time (RTT) of an audio interface and can be measured through a loopback. Using a cable to feed the output to the input of the audio interface I can create a loopback to measure RTT and systemic latency.

First close Ardour opened in the previous section for #Quantum evaluation, and use the pw-metadata command to force the previously evaluated quantum size as parameter. For exmaple, I use this command:

pw-metadata --name settings 0 clock.force-quantum 128

The measurement is done using the jack_iodelay utility, which is part of the jack-example-tools package and installed via:

sudo pacman -S jack-example-tools

I use an instrument cable with 6.3 mm mono jacks on both sides as my USB audio interface only provides jack outputs. If your device has XLR outputs but a headphone jack, you may use this output to create the physical side of the loopback. In my case the instrument cable is plugged in into input 1 and output 1 (left output). I double check the gain and volume controls to ensure that sound can actually pass through.

Audio interface loopback

Physical loopback connection of input 1 and output 1 (left outoput)

Next, I open two terminals or two terminal tabs and first start jack_iodelay without any parameters:

jack_iodelay

It will repeatedly report Signal below threshold... as there is no connection from a physical in- and output to the in- and ouput of the utility. For this reason, I use the second terminal window or tab for invoking:

jack_lsp

to list all available JACK clients and create the loopback as follows:

graph LR;
    input1-->jack_iodelay-->output1-->input1
ℹ️
You can also use qpwgraph installed in the Controls and routing section of the Multimedia and web guide to graphically list the in- and ouputs and draw a connection between the physical jacks and the in- and ouputs of jack_iodelay.

In my case input 1 and output 1 of the audio interface are listed as AMS-24 Pro:capture_AUX0 and AMS-24 Pro:playback_AUX0 and the input and output of jack_iodelay are listed as jack_delay:in and jack_delay:out. I use the following command to create the appropriate connections:

jack_connect "AMS-24 Pro:capture_AUX0" "jack_delay:in"
jack_connect "AMS-24 Pro:playback_AUX0" "jack_delay:out"

In the terminal window that is running jack_iodelay, it now repeatedly reports the total roundtrip latency and extra loopback latency. I can interrupt it using the keystroke <Ctrl>+<C> and note the recommended value to be used “for the backend arguments -I and -O”.

In my case jack_iodelay reported:

   406.000 frames      8.458 ms total roundtrip latency
	extra loopback latency: 150 frames
	use 75 for the backend arguments -I and -O

In order to set these up I need to find out the node.name property of the playback (output) and capture (input) device in PipeWire. The USB audio interface is managed by ALSA. For this reason, I can use the following command to list all values containing alsa_ followed by either input or output and ending with .usb plus a variable string:

pw-cli list-objects | grep -E 'alsa_(input|output).usb*'

The command reports two candidates providing the devices:

 		node.name = "alsa_output.usb-ZOOM_Corporation_AMS-24-00.pro-output-0"
 		node.name = "alsa_input.usb-ZOOM_Corporation_AMS-24-00.pro-input-0"

I can set the ProcessLatency to the value reported by jack_iodelay for each node using their names, respectively:

pw-cli set-param alsa_output.usb-ZOOM_Corporation_AMS-24-00.pro-output-0 ProcessLatency {rate: 75}
pw-cli set-param alsa_input.usb-ZOOM_Corporation_AMS-24-00.pro-input-0 ProcessLatency {rate: 75}

Afterwards, I can check the total latency (configured quantum size + systemic latency):

jack_lsp --total-latency

In my case it reports 203 frames ($128 + 75 = 203$) per playback and capture device. You can double check by running the jack_iodelay step again. It should now advise “use 0 for the backend arguments -I and -O”.

⚠️
The ProcessLatency parameters are not persistent across reboots! For this reason, they will be later incorporated into the #Startup script of the DAW. If you want to use another approach, consider the WirePlumber session manager to apply ALSA extra latency properties via rules.

DAW

A Digital Audio Workstation14 is primarily used to record, edit, and mix music. It integrates a lot of features, such as a multi-track recorder and digital mixing console, to provide a professional audio studio environment. I use Ardour provided by the ardour package, which is installed by:

sudo pacman -S ardour
ℹ️
When starting Ardour for the first time you have to complete a system setup wizard. You can change these configurations at any time in the preferences.

In the preferences, I like to change the Virtual Keyboard Layout to German QWERTZ. And in the Media tab of the Session properties the File type can be set to FLAC in order to save disk space. If you want to apply this setting as default for new sessions, use the Button Use these settings as defaults in the Misc tab.

Latency tuning

⚠️
The following steps are advanced. If your confidence gets lost during the next sections, revert the changes and rather use ALSA directly and the Calibrate Audio button in the I/O Setup dailog to run a wizard and get started quickly.

After installation of the Ardour DAW it can be used to evaluate the optimal quantum size in a recording session. The following sections deal with this evaluation by creating a startup script and trying different quantum sizes with the PIPEWIRE_QUANTUM environment variable. Additionally, the #Systemic latency of the audio interface is going to be analyzed and compensated. There is much information about latency and latency compensation in the Ardour manual, which I recommend to read to gain some background knowledge.

Startup script

I create a file called daw-rec to toggle the CPU governor as described in the #CPU frequency scaling section and setting the #Systemic latency before using the environment variable method to start the DAW:

daw-rec
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#!/bin/bash
#
# Toggle CPU governor and start DAW using a fixed low buffer size

UDID=usb-ZOOM_Corporation_AMS-24-00
INPT=alsa_input.$UDID.pro-input-0
OUPT=alsa_output.$UDID.pro-output-0
SMPL=75
BUFF=128
RATE=48000
LATE=PIPEWIRE_QUANTUM
APP1=ardour8
NULL=/dev/null

if [ ! -e /dev/snd/by-id/$UDID ]
then
  echo "ERROR: Device $UDID not found. Is it plugged in?"
  exit 1
fi

sudo cpupower frequency-set -g performance > $NULL

echo "INFO: Setting ProcessLatency to $SMPL."
for DEV in $INPT $OUPT
do
  pw-cli set-param $DEV ProcessLatency {rate: $SMPL} > $NULL
done

export $LATE=$BUFF/$RATE
echo "INFO: Starting $LATE=$BUFF/$RATE $APP1"
$APP1 > $NULL
unset $LATE

echo "INFO: Resetting ProcessLatency to 0."
for DEV in $INPT $OUPT
do
  pw-cli set-param $DEV ProcessLatency {rate: 0} > $NULL
done

sudo cpupower frequency-set -g powersave > $NULL

exit 0
ℹ️
If you also want to start other applications, add them after line 31. And keep in mind to change the APP1 variable in line 12, if the Ardour version increases.

I make the script executable and run it:

chmod +x daw-rec
./daw-rec

Quantum evaluation

In Ardour I create some audio tracks, organize the routing and start recording to create load on the system. Refer to the manual or watch some tutorials to learn using Ardour. The task here is to watch the DSP percentage and the xruns number in braces next to it in the status bar while focussing on any noticeable audio drop-outs during recording.

In case of xruns I can increase the buffer size in Ardour’s I/O setup—keep in mind that this reconfiguration provokes a xrun while reconnecting as a JACK client—or close Ardour, double the value of BUFF=128 in the script above. Another strategy for compensation may be #Using a high clock rate. Remember to also repeat the measurement of the #Systemic latency and adapt the value of SMPL=75 to the number of samples jack_iodelay suggests before re-running the #Startup script.

ℹ️
In a mixing session and/or if you don’t plan to use live processing and recording with software monitoring in your DAW, the quantum value can be higher as there might be more processing power (DSP) needed for #Plugins over realtime performance capabilities. You might copy and adjust the bash script above or just go with the default quantum value of 1024.

For instance, I’m using a quantum size of $p=128$, a systemic latency of $75$ samples for playback and capture, and the default clock rate of $f=48000$. Recalling the function for #Latency evaluation I’m recording at a total roundtrip latency ($L_R$) of:

$L_R = \frac{(128 + 75) \times 1}{48000 Hz} + \frac{(128 + 75) \times 1}{48000 Hz} = \frac{406}{48000 Hz} = 8.458 ms$

In a mixing only setup I just go with PipeWire’s defaults and if I don’t have my USB audio interface at hand I can use my built-in audio interface.

Plugins

This is a comprehensive topic by itself and I won’t go into the details. I rather list my favorite LV215 plugins with a description based on how I use them:

Package name Description More info
cardinal-lv2 Virtual modular synth https://cardinal.kx.studio/
guitarix Guitar gear emulation https://guitarix.org/
lsp-plugins-lv2 Compressors, EQs, etc. https://lsp-plug.in/
sfizz-lv2 Load sampled instruments https://sfz.tools/sfizz/
x42-plugins-lv2 Meters, limiters, etc. https://x42-plugins.com/x42/

To install all of these packages use the following command:

sudo pacman -S cardinal-lv2 guitarix lsp-plugins-lv2 sfizz-lv2 x42-plugins-lv2
⚠️
Note that I prefer sticking with the bundled plugins (ACE) of the #DAW as much as possible. For this reason, the plugins I use in addition provide rather advanced controls.

If you are looking for more easy to use or special plugins consider the following projects:

Find more plugins ready to install by listing the packages of the group lv2-plugins using:

sudo pacman -Sg lv2-plugins

Samples

An alternative to synthesizing sounds is to use sampling16. I use CC0 (public domain) samples for the following instruments:

After installation I can open their SFZ17 files using the sfizz-lv2 plugin installed in the #Plugins section before.

Drums

For acoustic drums I like to use the Tchimera Drum Kit. The installation can be done by cloning the repository:

git clone https://github.com/michaelwillis/tchimera-drum-kit

Alternatively, download an archive of the master and extract it using unzip, for example.

Piano

The Salamander Grand Piano provides a realistic piano sound and is public domain as of 2022-03-0418. I prefer the sound bank containing the samples in FLAC format to save disk space. I use curl to download the archive using the current direct link (as of writing this guide):

curl --output SalamanderGrandPiano-SFZ+FLAC-V3+20200602.tar.gz https://freepats.zenvoid.org/Piano/SalamanderGrandPiano/SalamanderGrandPiano-SFZ+FLAC-V3+20200602.tar.gz

The content of the archive can be extracted using:

tar afx SalamanderGrandPiano-SFZ+FLAC-V3+20200602.tar.gz
ℹ️
If you are low on resources for sample playback or looking for a CC0 upright piano sound bank have a look at the Upright Piano KW instrument.

Orchestra

Public domain orchestral instruments (brass, percussions, strings, woodwinds, etc.) are available in the Community Edition of the Versilian Studios Chamber Orchestra library. I retrieve the samples and SFZ using git:

git clone --branch SFZ https://github.com/sgossner/VSCO-2-CE

Alternatively, download the source code archive of the most current version at the releases page.

You can find various other virtual instruments at FreePats, sfz instruments or in the list of this article by Nils.

To conclude this guide, remember to keep evaluating and improving your setup. Building your personal pro audio environment is a process. You may proceed with setting up a professional video environment. Or, if this is not your use case, go back to the overview and select another guide.


  1. Advanced Linux Sound Architecture in the ArchWiki ↩︎

  2. USB device classes in the Wikipedia ↩︎

  3. Latency (audio) in the Wikipedia ↩︎

  4. PAM in the ArchWiki ↩︎

  5. xruns in the ALSA wiki ↩︎

  6. Swappiness in the Wikipedia ↩︎

  7. udev in the ArchWiki ↩︎

  8. FAQ: what are the differences between JACK1 and JACK2 ↩︎

  9. Sound system in the ArchWiki ↩︎

  10. What is the Pro Audio Profile in the PipeWire wiki ↩︎

  11. FramesPeriods in the ALSA wiki ↩︎

  12. ALSA properties section in the pipewire-devices man page ↩︎

  13. Systemic latency configuration by Robin Gareus ↩︎

  14. Digital audio workstation in the Wikipedia ↩︎

  15. Project site of the LV2 plugin standard ↩︎

  16. Sampling (music) in the Wikipedia ↩︎

  17. SFZ (file format) in the Wikipedia ↩︎

  18. Blog post by Alexander “rytmenpinne” Holm ↩︎

Last updated on