Skip to content

Most visited

Recently visited

navigation

Audio Latency

Video

Audio latency: buffer sizes

Video

Building great multi-media experiences on Android

Latency is the time it takes for a signal to travel through a system. These are the common types of latency related to audio apps:

This page describes how to develop your audio app with low-latency input and output, and how to avoid warmup latency.

Measuring latency

It is difficult to measure audio input and output latency in isolation since it requires knowing exactly when the first sample is sent into the audio path (although this can be done using a light testing circuit and an oscilloscope). If you know the round-trip audio latency, you can use the rough rule of thumb: audio input (and output) latency is half the round-trip audio latency over paths without signal processing.

Round-trip audio latency varies greatly depending on device model and Android build. You can get a rough idea of round-trip latency for Nexus devices by reading the published measurements.

You can measure round-trip audio latency by creating an app that generates an audio signal, listens for that signal, and measures the time between sending it and receiving it. Alternatively, you can install this latency testing app. This performs a round-trip latency test using the Larsen test. You can also view the source code for the latency testing app.

Since the lowest latency is achieved over audio paths with minimal signal processing, you may also want to use an Audio Loopback Dongle, which allows the test to be run over the headset connector.

Best practices to minimize latency

Validate audio performance

The Android Compatibility Definition Document (CDD) enumerates the hardware and software requirements of a compatible Android device. See Android Compatibility for more information on the overall compatibility program, and CDD for the actual CDD document.

In the CDD, round-trip latency is specified as 20 ms or lower (even though musicians generally require 10 ms). This is because there are important use cases that are enabled by 20 ms.

There is currently no API to determine audio latency over any path on an Android device at runtime. You can, however, use the following hardware feature flags to find out whether the device makes any guarantees for latency:

The criteria for reporting these flags is defined in the CDD in sections 5.6 Audio Latency and 5.10 Professional Audio.

Here’s how to check for these features in Java:

boolean hasLowLatencyFeature =
    getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_LOW_LATENCY);

boolean hasProFeature =
    getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_PRO);

Regarding the relationship of audio features, the android.hardware.audio.low_latency feature is a prerequisite for android.hardware.audio.pro. A device can implement android.hardware.audio.low_latency and not android.hardware.audio.pro, but not vice-versa.

Make no assumptions regarding audio performance

Beware of the following assumptions to help avoid latency issues:

A consequence of potentially independent audio clocks is the need for asynchronous sample rate conversion. A simple (though not ideal for audio quality) technique for asynchronous sample rate conversion is to duplicate or drop samples as needed near a zero-crossing point. More sophisticated conversions are possible.

Minimizing input latency

This section provides suggestions to help you reduce audio input latency when recording with a built-in microphone or an external headset microphone.

Minimizing output latency

Use the optimal sample rate when creating your audio player

To obtain the lowest latency, you must supply audio data that matches the device's optimal sample rate and buffer size. For more information, see Design For Reduced Latency.

In Java, you can obtain the optimal sample rate from AudioManager as shown in the following code example:

AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
String sampleRateStr = am.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE);
int sampleRate = Integer.parseInt(sampleRateStr);
if (sampleRate == 0) sampleRate = 44100; // Use a default value if property not found

Once you know the optimal sample rate, you can supply it when creating your player. This example uses OpenSL ES:

// create buffer queue audio player
void Java_com_example_audio_generatetone_MainActivity_createBufferQueueAudioPlayer
        (JNIEnv* env, jclass clazz, jint sampleRate, jint framesPerBuffer)
{
   ...
   // specify the audio source format
   SLDataFormat_PCM format_pcm;
   format_pcm.numChannels = 2;
   format_pcm.samplesPerSec = (SLuint32) sampleRate * 1000;
   ...
}

Note: samplesPerSec refers to the sample rate per channel in millihertz (1 Hz = 1000 mHz).

Use the Optimal Buffer Size When Enqueuing Audio Data

You can obtain the optimal buffer size in a similar way to the optimal sample rate, using the AudioManager API:

AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
String framesPerBuffer = am.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER);
int framesPerBufferInt = Integer.parseInt(framesPerBuffer);
if (framesPerBufferInt == 0) framesPerBufferInt = 256; // Use default

The PROPERTY_OUTPUT_FRAMES_PER_BUFFER property indicates the number of audio frames that the HAL (Hardware Abstraction Layer) buffer can hold. You should construct your audio buffers so that they contain an exact multiple of this number. If you use the correct number of audio frames, your callbacks occur at regular intervals, which reduces jitter.

It is important to use the API to determine buffer size rather than using a hardcoded value, because HAL buffer sizes differ across devices and across Android builds.

Avoid adding output interfaces that involve signal processing

Only these interfaces are supported by the fast mixer:

These interfaces are not allowed because they involve signal processing and will cause your request for a fast-track to be rejected:

When you create your player, make sure you only add fast interfaces, as shown in the following example:

const SLInterfaceID interface_ids[2] = { SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_VOLUME };

Verify you're using a low-latency track

Complete these steps to verify that you have successfully obtained a low-latency track:

  1. Launch your app and then run the following command:
  2. adb shell ps | grep your_app_name
    
  3. Make a note of your app's process ID.
  4. Now, play some audio from your app. You have approximately three seconds to run the following command from the terminal:
  5. adb shell dumpsys media.audio_flinger
    
  6. Scan for your process ID. If you see an F in the Name column, it's on a low-latency track (the F stands for fast track).

Minimizing warmup latency

When you enqueue audio data for the first time, it takes a small, but still significant, amount of time for the device audio circuit to warm up. To avoid this warmup latency, you can enqueue buffers of audio data containing silence, as shown in the following code example:

#define CHANNELS 1
static short* silenceBuffer;
int numSamples = frames * CHANNELS;
silenceBuffer = malloc(sizeof(*silenceBuffer) * numSamples);
    for (i = 0; i<numSamples; i++) {
        silenceBuffer[i] = 0;
    }

At the point when audio should be produced, you can switch to enqueuing buffers containing real audio data.

Note: Constantly outputting audio incurs significant power consumption. Ensure that you stop the output in the onPause() method. Also consider pausing the silent output after some period of user inactivity.

Additional sample code

To download a sample app showcasing audio latency, see NDK Samples.

For more information

  1. Audio Latency for App Developers
  2. Contributors to Audio Latency
  3. Measuring Audio Latency
  4. Audio Warmup
  5. Latency (audio)
  6. Round-trip delay time
This site uses cookies to store your preferences for site-specific language and display options.

Get the latest Android developer news and tips that will help you find success on Google Play.

* Required Fields

Hooray!

Follow Google Developers on WeChat

Browse this site in ?

You requested a page in , but your language preference for this site is .

Would you like to change your language preference and browse this site in ? If you want to change your language preference later, use the language menu at the bottom of each page.

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.

Take a short survey?
Help us improve the Android developer experience.
(Sep 2017 survey)