如何在Android上使用AudioTrack.getTimestamp()来计算延迟?

时间:2018-03-30 20:31:38

标签: android audio audiotrack

我看到很多资源建议在现代Android版本上使用AudioTrack.getTimestamp()来计算音频/视频同步的音频延迟。

例如:

https://stackoverflow.com/a/37625791/332798

https://developer.amazon.com/docs/fire-tv/audio-video-synchronization.html#section1-1

https://groups.google.com/forum/#!topic/android-platform/PoHfyNK54ps

但是,这些都没有解释如何使用时间戳来计算延迟?我正在努力想弄清楚如何处理时间戳的framePosition / nanoTime来提出延迟数字。

1 个答案:

答案 0 :(得分:1)

因此,在此API之前,您将使用AudioTrack.getPlaybackHeadPosition(),这只是一个近似值。因此,为了考虑延迟,您必须使用两种隐藏方法之一的延迟值来抵消该值:AudioManager.getOutputLatency()AudioTrack.getLatency()

使用新的AudioTrack.getTimestamp() API,您可以直接在输出中获取给定时间播放头位置的快照。因此,它完全准确并且已经考虑了设备延迟。因此,现在无需调用任何其他API来添加/删除延迟。

需要注意的是,此时间戳只是一个快照,文档建议您不要经常调用此新方法。因此获得“当前”位置的技巧是使用您的上一个快照并线性插入当前值应该是:

playheadPos = timestamp.framePosition + 
              (System.nanoTime() - timestamp.nanoTime) * samplerate / 1e9;

然后可以将此位置与您在AudioTrack中写入的帧数进行比较,方法是维护另一个计数器,该计数器每次AudioTrack.write()完成时递增:

int bytesWritten = track.write(...);
writtenPos += bytesWritten / pcmFrameSize;

如果您正在使用ENCODING_AC3AudioTrack报告的播放头位置仍然是样本。您需要将其转换为字节,或将您写入的字节数转换回样本。无论哪种方式,您都需要知道AC3流的比特率(即384000bps

int bytesWritten = track.write(...);
writtenPos += bytesWritten * samplerate / (bitrate / 8);