January 12, 2021•581 words
When threadirqs is enabled in the kernel command-line, Linux only acknowledges the triggered interrupt with preemption disabled, and right after that assigns a thread for the interrupt handler, thus reducing the overall latency.
rtirq-init package contains rtirq initialization script, which assigns a real-time priority to all interrupt handlers according to the rules in the /etc/default/rtirq configuration file. The default configuration is geared towards audio, giving the highest priority for the sound card and the USB host controller:
$ ps -T -o comm,policy,rtprio -p $(pgrep -w -d ',' irq) | egrep '(snd|hci)'
irq/126-xhci_hc FF 85 irq/143-snd_hda FF 90
CPU frequency scaling
One of the first things to tune, when aiming towards a stable audio latency, is the CPU frequency scaling. More precisely, it should preferably be constant.
Downscaling occurs when the operating frequency of a CPU is decreased. By default kernel uses the powersave governor, which proactively downscales the operating frequency when the overall utilization is lower, in order to save power.
It can be substituted with the performance governor, which keeps the operating frequency at maximum, as follows:
echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
Upscaling occurs when the operating frequency is temporarily increased above the maximum. Intel x86 CPU's have a feature called Turbo Boost, which causes the CPU to automatically upscale when the demand for processing is high enough.
Turbo Boost can be disabled as follows:
echo 1 | sudo tee /sys/devices/system/cpu/intel_pstate/no_turbo
Popular audio software, such as JACK and Reaper, can often take the advantage of real-time scheduling and memory locking, if such resources are available for the application process.
In order to protect a system from misbehaving or malicious software, it is better to create a new group only for users, who require these capabilities, e.g.:
sudo groupadd realtime sudo gpasswd -a $USER realtime
Then, just create /etc/security/limits.d/realtime.conf:
@realtime - memlock 8388608 # 8 GB @realtime - rtprio 49
It's not advisable to set memory locking unlimited, but rather set an appropriate fixed limit to fit to your requirement, because a privileged user could also be running software that is misbehaving.
rtprio should be always capped below the IRQ priorities, because failing to serve the external hardware in time could potentially damage the system.
JACK Audio Connection Kit (JACK)
JACK Audio Connection Kit (JACK) is a low-latency audio server for sharing the available audio devices for multiple application processes. It is centered around a command-line tool called jack_control, which is a command-line interface for the jackdbus daemon process.
jackdbus takes care of:
- managing the jackd daemon process, which is the actual audio server and connection end point for the JACK clients.
- providing JACK sink and source for PulseAudio.
Here's a simple configuration script for configuring JACK:
#!/bin/bash SOUND_CARD=$1 SAMPLE_RATE=$2 FRAMES_PER_INT=$3 FRAME_SIZE=$4 # Use the ALSA backend. jack_control ds alsa # Enable rtprios. jack_control eps realtime true # Configure the sound card. jack_control dps device $SOUND_CARD jack_control dps capture $SOUND_CARD jack_control dps playback $SOUND_CARD jack_control dps rate $SAMPLE_RATE jack_control dps nperiods $FRAMES_PER_INT jack_control dps period $FRAME_SIZE
The configuration is written into ~/.config/jack/conf.xml. JACK can be started with jack_control start and stopped with jack_control stop. The runtime log of jackdbus is stored into ~/.log/jack/jackdbus.log.
Sampling a web browser to Reaper using JACK
JACK gives quite convenient tools to sample audio from a web browser, or any other desktop application, which is sometimes so much convenient than trying to save it as a file. It's just a trivial matter of re-routing PulseAudio interconnections:
$ jack_connect "PulseAudio JACK Sink:front-left" REAPER:in1 $ jack_connect "PulseAudio JACK Sink:front-right" REAPER:in2 $ jack_disconnect "PulseAudio JACK Sink:front-left" system:playback_1 $ jack_disconnect "PulseAudio JACK Sink:front-right" system:playback_2
Now desktop audio can be only heard when monitored from Reaper and can be trivially record to any track.