jn_pdx jn_pdx - 6 months ago 76
Java Question

How do you determine the audio latency (AudioTrack) on Android?

I have an app in which I use an

AudioTrack
in streaming mode to play dynamically generated audio. The app doesn't have to respond instantaneously to inputs, so the latency issues don't bother me for that side of the program.

The problem is that I have an animation that needs to be as precisely 'in-sync' as possible with the audio and it seems that different devices have different amounts of time between when the
AudioTrack
stops blocking the
write()
call and asks for more data, and when that audio is played from the speaker.

My current solution gets me most of the way there -- I count the number of frames I've passed in to the
AudioTrack
so far, and compare it to
getPlaybackHeadPosition()
. It looks basically like:

long currentTimeInFrames = 0;
while(playingAudio) {
currentTimeInFrames += numberOfFramesToWrite;
long delayInFrames = (currentTimeInFrames - audioTrack.getPlaybackHeadPosition());
audioTrack.write(frameBuffer,0,sampleSize);
doAnimationAfterDelay(delayInFrames);
}


However, there's still some latency that
getPlaybackHeadPosition()
doesn't seem to account for that varies by device.

Is there a way to poll the system for the latency of the AudioTrack?

Answer

Consider driver's latency. There's hidden function AudioManager.getOutputLatency(int) to get this.

Call it like this:

AudioManager am = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
try{
   Method m = am.getClass().getMethod("getOutputLatency", int.class);
   latency = (Integer)m.invoke(am, AudioManager.STREAM_MUSIC);
}catch(Exception e){
}

I get about 45 - 50 ms on different devices. Use the result in your calculations.

Comments