PortAudio Implementation - Start/Stop

# PortAudio Latency

This page discusses the issues of audio latency for PortAudio . It offers suggestions on how to lower latency to improve the responsiveness of applications.

> What is Latency?
> PortAudio and Latency
> Macintosh
> Unix
> WIndows

By Phil Burk, Copyright 2002 Phil Burk and Ross Bencina

## What is Latency?

Latency is basically longest time that you have to wait before you obtain a desired result. For digital audio output it is the time between making a sound in software and finally hearing it.

Consider the example of pressing a key on the ASCII keyboard to play a note. There are several stages in this process which each contribute their own latency. First the operating system must respond to the keypress. Then the audio signal generated must work its way through the PortAudio buffers. Then it must work its way through the audio card hardware. Then it must go through the audio amplifier which is very quick and then travel through the air. Sound travels at abous one foot per millisecond through air so placing speakers across the room can add 5-20 msec of delay.

The reverse process occurs when recording or responding to audio input. If you are processing audio, for example if you implement a software guitar fuzz box, then you have both the audio input and audio output latencies added together.

The audio buffers are used to prevent glitches in the audio stream. The user software writes audio into the output buffers. That audio is read by the low level audio driver or by DMA and sent to the DAC. If the computer gets busy doing something like reading the disk or redrawing the screen, then it may not have time to fill the audio buffer. The audio hardware then runs out of audio data, which causes a glitch. By using a large enough buffer we can ensure that there is always enough audio data for the audio hardware to play. But if the buffer is too large then the latency is high and the system feels sluggish. If you play notes on the keyboard then the "instrument" will feel unresponsive. So you want the buffers to be as small as possible without glitching.

## PortAudio and Latency

The only delay that PortAudio can control is the total length of its buffers. The Pa_OpenStream() call takes two parameters: numBuffers and framesPerBuffer. The latency is also affected by the sample rate which we will call framesPerSecond. A frame is a set of samples that occur simultaneously. For a stereo stream, a frame is two samples.

The latency in milliseconds due to this buffering is:

> `latency_msec = 1000 * numBuffers * framesPerBuffer / framesPerSecond`

This is not the total latency, as we have seen, but it is the part we can control.

If you call Pa_OpenStream() with numBuffers equal to zero, then PortAudio will select a conservative number that will prevent audio glitches. If you still get glitches, then you can pass a larger value for numBuffers until the glitching stops. if you try to pass a numBuffers value that is too small, then PortAudio will use its own idea of the minimum value.

PortAudio decides on the minimum number of buffers in a conservative way based on the frameRate, operating system and other variables. You can query the value that PortAudio will use by calling:

> `int Pa_GetMinNumBuffers( int framesPerBuffer, double sampleRate );`

On some systems you can override the PortAudio minimum if you know your system can handle a lower value. You do this by setting an environment variable called PA_MIN_LATENCY_MSEC which is read by PortAudio when it starts up. This is supported on the PortAudio implementations for Windows MME, Windows DirectSound, and Unix OSS.

## Macintosh

The best thing you can do to improve latency on Mac OS 8 and 9 is to turn off Virtual Memory. PortAudio V18 will detect that Virtual Memory is turned off and use a very low latency.

For Mac OS X the latency is very low because Apple Core Audio is so well written. You can set the PA_MIN_LATENCY_MSEC variable using:

> `setenv PA_MIN_LATENCY_MSEC 4`

## Unix

PortAudio under Unix currently uses a backgroud thread that reads and writes to OSS. This gives you decent but not great latency. But if you raise the priority of the background thread to a very priority then you can get under 10 milliseconds latency. In order to raise your priority you must run the PortAudio program as root! You must also set PA_MIN_LATENCY_MSEC using the appropriate command for your shell.

## Windows

Latency under Windows is a complex issue because of all the alternative operating system versions and device drivers. I have seen latency range from 8 milliseconds to 400 milliseconds. The worst case is when using Windows NT. Windows 98 is a little better, and Windows XP can be quite good if properly tuned.

The underlying audio API also makes a lot of difference. If the audio device has its own DirectSound driver then DirectSound can often provide better latency than WMME. But if a real DirectSound driver is not available for your device then it is emulated using WMME and the latency can be very high. That's where I saw the 400 millisecond latency. The ASIO implementation is generally very good and will give the lowest latency if available.

You can set the PA_MIN_LATENCY_MSEC variable to 50, for example, by entering in MS-DOS:

> `set PA_MIN_LATENCY_MSEC=50`

If you enter this in a DOS window then you must run the PortAudio program from that same window for the variable to have an effect. You can add that line to your C:\AUTOEXEC.BAT file and reboot if you want it to affect any PortAudio based program.

For Windows XP, you can set environment variables as follows:

1. Select "Control Panel" from the "Start Menu".
2. Launch the "System" Control Panel
3. Click on the "Advanced" tab.
4. Click on the "Environment Variables" button.
5. Click "New" button under User Variables.
6. Enter PA_MIN_LATENCY_MSEC for the name and some optimistic number for the value.
7. Click OK, OK, OK.

### Improving Latency on Windows

There are several steps you can take to improve latency under windows.

1. Avoid reading or writng to disk when doing audio.
2. Turn off all automated background tasks such as email clients, virus scanners, backup programs, FTP servers, web servers, etc. when doing audio.
3. Disconnect from the network to prevent network traffic from interrupting your CPU.

Important: Windows XP users can also tune the OS to favor background tasks, such as audio, over foreground tasks, such as word processing. I lowered my latency from 40 to 10 milliseconds using this simple technique.

1. Select "Control Panel" from the "Start Menu".
2. Launch the "System" Control Panel
3. Click on the "Advanced" tab.
4. Click on the "Settings" button in the Performance area.
5. Click on the "Advanced" tab.
6. Select "Background services" in the Processor Scheduling area.
7. Click OK, OK.

Please let us know if you have others sugestions for lowering latency.