Low latency howto
Low latency audio with Linux 2.6
Real-time audio work is a relative idea, latency is inherent when processing audio in the digital domain, however it is possible to get latencies far below perceptible levels. The steps needed to get such results is what this article will address.
The kernel is critical, since it has to respond quickly to interrupts. Much of the configuration needed for low latency audio is done within the kernel.
For the sake of being recent and for ease of use, this article will use the 2.6 kernel source.
Be familiar with building custom kernels. It is easy to stop the system from booting. Read up on the steps needed to build a kernel that will boot on the system with necessary drivers.
Get, Extract, Patch
To build a new kernel, get the source to it. This can be had from Kernel.org (at the time of writing the latest stable version is 2.6.22). Next get the corresponding real-time kernel patch by Ingo Molnar, which is available from his website. Download the latest version for the choice of kernel version. For example, patch-2.6.22-rt9 for kernel version 2.6.22. Next un-gzip the patch in the directory of the kernel source and apply it. This is usually done with patch -p1 -i patch-2.6.xx.x-rtx.
# gunzip patch-2.6.22-rt9.gz # patch --strip 1 < patch-2.6.22-rt9
Config, Build, Boot
Configure the newly patched kernel. Use the make menuconfig command on a text console, or make xconfig for a GUI.
Make sure that the drivers needed to boot the system are built in. Usually this is an IDE driver and ext3 file system support. Configure other drivers such as network and video as well as USB/firewire/parallel drivers.
Some prefer leaving the ALSA drivers for their sound card out of the initial kernel configuration, as they like to download the latest version from the ALSA website and build them later. Enable sound card support within “Device Drivers”. Building and installing the ALSA drivers will be covered later.
Navigate to the “Processor type and features” category. There will be an option “Preemption mode”. Set this to “Complete Preemption (Real Time)”.
There are also some additional tweaks which are commonly recommended by the Linux Audio Users community:
- enable deadline as the default IO scheduler (Block Layer -> IO Schedulers),
- enable HPET timer support (Processor type and features),
- enable enhanced real time clock support (Device Drivers -> Character Devices),
- disable priority inheritance debugging (Device Drivers -> Character Devices), and
- enable the high precision event timer (Device Drivers -> Character Devices).
After changes are made, exit and save the configuration.
Build the kernel. Exactly how to do this depends on the Linux distribution, but on Debian or Ubuntu use make-kpkg like this:
# make-kpkg kernel_image
which makes a package that you can then install.
After installing the kernel, reboot, and the system should be real-time capable.
Even though the kernel may be real-time capable, jackd may not run with a frame size of 16, which is 0.667ms latency with 2 periods/buffers. Further tweaking is needed.
Build the ALSA sound drivers (and libraries if necessary) for the new kernel.
The latest version is on the ALSA project website.
Note: if this is the first time ALSA has been installed on this system, install the libraries and utilities from the ALSA website as well. After extracting the drivers package navigate into the new directory (alsa-driver-1.0.14 at the time of writing) and issue the following command:
# ./configure –-with-sequencer=yes –-with-oss=yes –-with-cards=<drivers>
replace <drivers> in the above command to include a comma separated list of the drivers for the sound card(s) on the system. ./configure –-help will give a full list of drivers and options, or find out which driver is needed through the sound card matrix Matrix:Main.
Once the ALSA system is configured type the make command to build it.
Then, as root type make install to install the ALSA modules into the /lib/modules/<kernel version> directory.
Then, install the libraries and utilities (if necessary) by typing ./configure && make && make install commands.
Reboot to allow the drivers to be loaded, or load them manually.
To verify, use the alsamixer utility to adjust settings and volumes. alsamixer may not show settings unless the correct drivers are loaded.
After ALSA is installed modify the PAM security system to allow regular users to operate software at a high priority (real time) level. Edit /etc/security/limits.conf as root (in Debian based systems). Add the following lines to limits.conf:
@audio - rtprio 95 @audio - memlock 512000 @audio - nice -19
This is from Florian Schmidt's website and is a starting point only, though it should work nicely for any system. The rtprio setting is the maximum priority a user of the audio group can run a task. The memlock setting is the maximum amount of memory that a member of the audio group can lock with a realtime task. This should be less than the maximum physical amount of memory, some recommend it to be half. nice is the minimum “nice level” a task can be run as (the willingness of a task to give up it's cpu time). These settings will get jackd, ardour and other RT capable programs runing at higher priorities, but there is still a bit more to do.
The next and final step is to set a few thread priorities. The real time patch should have created several IRQ threads as well as added a “hrtimer” thread. These can be viewed with ps -e. Use the chrt command to set thread priorities (in Debian this is part of the schedutils package). It doesn't matter which order the priorities are set. Scan the output of the ps -e command looking for threads like “softirq-timer” and “softirq-hrtimer”, taking note of the pid of each one (on a dual core system there are two of each, one for each CPU). Find the pid of the IRQ thread that the sound card resides on. Looking at the output of cat /proc/interrupts should reveal this. Set new priorities for each thread:
chrt -f -p 99 6 chrt -f -p 99 12 chrt -f -p 99 818
These will set the threads identified (6, 12, and 818) to a real-time priority level (99). That high of a priority may not be necessary and a bit insecure, feel free to tweak as you see fit. These commands are the last settings that need to be changed and allow the kernel timers to operate on a much higher priority, thus insuring more satisfactory scheduling latencies.
The priorities of these processes will need to be reset after each reboot, so a simple init script would suffice for doing this as the pids shouldn't change. Or use the pgrep command to locate the threads:
# chrt -f -p 99 `pgrep softirq-timer`
A more detailed explanation of thread priorities can be found over at the ffado project's wiki: IRQ priotiries How-To
Now start recording and making music. It should now be possible to jackd with much lower frame sizes than before and much fewer xruns. Enjoy!
Notes on APIC
It is a common problem to experience problems of many types when dealing with APIC enabled kernels and motherboards. These can range from dificulties in setting IRQs to full system lockups when using certain IRQs. If you experience any new problems after booting a real-time patched kernel try adding the noapic boot option to grub and see if that solves the problem, also, if the processor is single core, or there is no need for a kernel optimized for dual core processors then you can try disabling IO-APIC in the kernel config.