Mike Wilson's Blog


I was a MA/MST student at Stanford's Center for Computer Research in Music and Accoustics.

This is my weblog.

Click here for my main page.



2013-03-01

Now that I've finally settled into my new life, I'm starting to think
about how I can continue to contribute here.  I think I will try to do
weekly posts about Linux audio.  That's reasonably CCRMA-related I
think, especially since I run PlanetCCMRA.

So for the first post in this series: how I configure my machine for
low-latency audio.


Step 1:  Processor scaling governors

Modern CPUs have power saving features that let them change their
clock speeds.  This is generally a good thing, but certain CPU scaling
modes can introduce a lot of latency.

You can read more about the available CPU scaling options here:

http://docs.fedoraproject.org/en-US/Fedora/17/html/Power_Management_Guide/cpufreq_governors.html

The bottom line is that when doing real-time audio, you should use the
"performance" governor.

You can check which governor you are using by running, for example:

cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor

And you can set the performance governor as follows:

su -c 'echo performance > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor'

If you have multiple CPUs you should repeat the process for each of
them.  I wrote a shell script to do it for all my CPUs.

Another option is to turn off power saving in your BIOS, but this has
the obvious drawback of using more power.


Step 2: USB audio interface -- using the best USB port

Now that you have your processors operating at maximum speed, you
should be able to find your minimum latency by adjusting your Jack
settings.  However, if you are using a USB audio interface you may
occasionally experience huge latency spikes if there are other devices
sharing the same USB bus.

To find out what devices is on which bus, type the following:

lsusb | sort

Here's my output:

Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 001 Device 003: ID 04f2:b217 Chicony Electronics Co., Ltd 
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 002 Device 003: ID 0926:0202  
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 003 Device 002: ID 17ef:100a Lenovo ThinkPad Mini Dock Plus Series 3
Bus 003 Device 003: ID 5332:2100  
Bus 003 Device 004: ID 17f6:0709 Unicomp, Inc Model M Keyboard
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub

The "Bus" parameter is important.  I'm not 100% sure, but I believe
that each bus gets a single IRQ.  Thus, if you have a lot of devices
on one bus they have to share the same interrupt, and if one of them
is slow and the other one is your USB audio interface you can get
audio xruns.

You should try to plug your audio interface into a port which doesn't
share the bus with anything else.  There may be multiple devices that
identify themselves as hubs, especially if you have USB 2.0 or 3.0
ports.  These should be fine to share with, but everything else is a
potential source of latency spikes.  Of course you should not plug
your USB audio interface into a physical USB hub; that will also add
latency.  Plug it directly into the computer.

In my case, Bus 001 Device 003 is my integrated webcam.  This is a
common occurrence in laptops: integrated devices run on a USB bus (and
there's no way to change which bus).  I figured out which physical
ports on my laptop correspond to which bus by simply unplugging
everything, then plugging my keyboard into each port consecutively.  I
found out that everything on my docking station along with one
physical port run on Bus 003, and the remaining two physical ports are
on Bus 001 and Bus 002, respectively.  Since the webcam is on Bus 001,
I plugged the USB audio interface into Bus 002 and no longer
experience random latency spikes (Bus 002 Device 003 in the above
readout is my soundcard).  All my less-time-critical devices, such as
keyboard and mouse, go to Bus 003.


Step 3: Real-time kernel

Now that you have the hardware situation under control, it's time to
update your kernel!  There are at least two options:

1) Get an actual real-time kernel.  For Fedora, the easiest option is
   to install PlanetCCRMA:

http://ccrma.stanford.edu/planetccrma/software/

2) Add the parameter "threadirqs" to the boot string of a standard
   kernel, in /boot/grub2/grub.cfg (for Fedora).  This will give you
   many of the benefits of a real-time kernel, but you probably won't
   be able to get quite the same latencies as you would with the
   PlanetCCRMA kernel.


Step 4: Jack settings

Now that you have the hardware and kernel settings taken care of, it's
time to find the lowest latency possible!

I like to do this by adjusting settings in qjackctl.  There are a lot
of opinions about how to configure jack, some of which conflict, so I
will add my own opinion to the mix:

Realtime: checked.  This is necessary for realtime audio.

No Memory Lock / Unlock Memory: unchecked.  But I have tons of memory
on my machine.

Priority: 75.  Setting this too high is actually bad; the Jack
watchdog process runs at some offset of priority higher than this but
usually user processes can only run up to 89.  If you set this
priority to 89 the watchdog process can end up at a lower priority
than the other jack processes, which can cause all sorts of issues.
72 is probably fine.  80 is probably too high.

Periods/Buffer: Many interfaces need 3 for this.  Some can get by with
2.  It requires experimenting.

Frames/Period, Sample Rate: Set the sample rate you want first, then
play with frames/period and periods/buffer until you don't get xruns.
I don't know any automatic way to figure this out; it's soundcard and
configuration-dependent.

MIDI Driver: if you're only using ALSA MIDI or only using Jack MIDI
you can set this to "none".  If you're using MIDI hardware and Jack
MIDI software, you can set it to "raw" which lets Jack take direct
control of all ALSA MIDI handling.  If you want to use ALSA MIDI
software with Jack software you can set it to seq, or you can keep it
as "raw" or "none" and run a2jmidid in the background to expose the
MIDI ports to Jack.


Conclusion:

And there you have it.  There are a few other tweaks that can help,
but I believe these steps have the most impact.  Make sure you use the
full power of your CPU.  Configure your hardware so your soundcard has
its own IRQ.  Use a real-time kernel.  Set up Jack correctly.  Then
enjoy a stable, low-latency experience!

For reference, qjackctl reports 4ms latency for my configuration (48k,
3 periods per buffer, 64 frames per period) and I pretty much never
see xruns unless I have a bug in my own software.  For a USB soundcard
I think that's pretty good.

As much fun as it is to tweak your system it's pretty much always
beter to make some music.  Hopefully this post will help you spend
more time on the latter!


email mwilson@alumni.caltech.edu
Disclaimer: the views herein are my own and do not represent the views of Stanford University. All material copyright Michael J. Wilson.