Measure Audio Latency
This example shows how to measure the latency of an audio device. This example uses audiostreamer
to measure latency by cross-correlation, by playing and recording a brief sine sweep.
Introduction
In general terms, latency is defined as the time from when the audio signal enters a system until it exits. In a digital audio processing chain, there are multiple parameters that cause or influence latency:
Hardware (including A/D and D/A conversion)
Audio drivers that communicate with the system's sound card
Sampling rate
Samples per frame (buffer size)
Algorithmic latency (e.g. delay introduced by a filter or audio effect)
This example shows how to measure round-trip latency. That is, the latency incurred when playing audio through a device, looping back the audio with a physical loopback cable, and recording the loopback audio with the same audio device. To compute latency for your own audio device, you need to connect the audio out and audio in ports using a loopback cable.
Round-trip latency does not break down the measurement between output latency and input latency. It only measures the combined effect of the two. In the case of measurements using the audio device, the round-trip latency is the lower bound. If you add a microphone and loudspeaker, this latency will increase. For example, the time for sounds to propagate through the air from the loudspeaker to the microphone is added. In the case of audio processing, the order is different (input delay, processing, output delay), but the round-trip latency is still the lower bound. Any additional signal processing can only add delay.
Measuring Latency with the audiostreamer
Object
The audiostreamer
object is a tool for playing and/or recording audio. It includes a measureLoopbackLatency
method that makes it easy to measure the device round-trip latency.
First, set up the object in full-duplex mode and select the desired sample rate. On Windows, you can also select a driver (DirectSound, WASAPI, or ASIO). If you select the ASIO driver, the object will automatically set the Player
and Recorder
properties to the default ASIO device if any is found.
as = audiostreamer(Mode="full-duplex", SampleRate=96e3, Driver="ASIO")
as = audiostreamer handle with properties: Mode: 'full-duplex' Driver: 'ASIO' Recorder: 'ASIO MADIface USB' Player: 'ASIO MADIface USB' SampleRate: 96000 Show all properties
Now select the channel that will be used to play the sweep, and the channel used to record it back.
as.PlayerChannels = 3; % play on channel #3 as.RecorderChannels = 3; % record on channel #3
With ASIO devices, you can open the device control panel to make sure the device is set to the sample rate you want (ex: 96 kHz). You can also change other device settings to see how they impact latency. These are manufacturer settings, so they will differ from one brand to another.
asiosettings
By default, the audiostreamer
DeviceBufferSize
property is "auto"
. This will use the optimal buffer size according to the operating system (OS). For example, with ASIO, the "auto"
setting will use the buffer size set in the ASIO device's control panel.
Once you have setup the audiostreamer object and the device settings, make the measurement. Show the latency in samples and in milliseconds.
latencyInSamples = measureLoopbackLatency(as)
latencyInSamples = 221
latendyInMS = 1000*latencyInSamples/as.SampleRate
latendyInMS = 2.3021
You can make sure there were no dropouts during the measurement.
samplesDropped = getUnderrunCount(as)
samplesDropped = 0
It is a best practice to release the audio device when done. Make sure to do this before changing device settings for example (asiosettings
).
release(as)
Tips When Measuring Latency
Real-time processing on a general-purpose OS might require minimizing other tasks being performed by the computer. It is recommended to:
Close all other programs, particularly those that may use the audio device
When appropriate, set the default OS device to another device than the one used here
Use a larger buffer size to minimize any dropouts (device settings, or
DeviceBufferSize
if used)Ensure your hardware settings (buffer size, sampling rate) match the
audiostreamer
settingsAfter the measurement, check that no underruns/overruns occurred (
getUnderrunCount
)
On Windows, you can use the asiosettings
function to launch the dialog to control the hardware settings. On macOS, you should launch the Audio MIDI Setup app.
When using ASIO on Windows or CoreAudio on macOS, the latency measurements are consistent if no dropouts occur.
Measurements For Different Buffer Sizes
Use asiosettings
to set the buffer size to 64, then try different buffer size configurations with the audiostreamer
to see how latency is impacted.
as.DeviceBufferSize = "auto"; latencyMS = measureLoopbackLatency(as)*1000/as.SampleRate; if getUnderrunCount(as) > 0 error("An underrun has occurred.") end bufferSizes = [64;128;256;512;1024]; for ii = 1:numel(bufferSizes) as.DeviceBufferSize = bufferSizes(ii); latencyMS(ii+1) = measureLoopbackLatency(as)*1000/as.SampleRate; if getUnderrunCount(as) > 0 error("An underrun has occurred.") end end release(as)
Show the results in a table.
BufferSize = [{"auto"};num2cell(bufferSizes)]; table(BufferSize, latencyMS.', VariableNames={'Buffer Size','Latency (ms)'})
ans=6×2 table
Buffer Size Latency (ms)
___________ ____________
{["auto"]} 2.3021
{[ 64]} 2.3021
{[ 128]} 2.9688
{[ 256]} 4.3021
{[ 512]} 6.9688
{[ 1024]} 12.302
You could also try different samples rates. Generally, latency is lower for higher sampling rates.
For an example of how to generate your own sweep and play it to measure latency, see the Measure the Frequency Response of an Audio Device example.