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

tmm*_*mm1 3 audio android audiotrack

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

例如:

/sf/answers/2633805401/

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

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

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

tmm*_*mm1 5

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

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

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

playheadPos = timestamp.framePosition + 
              (System.nanoTime() - timestamp.nanoTime) * samplerate / 1e9;
Run Code Online (Sandbox Code Playgroud)

AudioTrack然后可以通过维护另一个每次完成时递增的计数器来将该位置与写入的帧数进行比较AudioTrack.write()

int bytesWritten = track.write(...);
writtenPos += bytesWritten / pcmFrameSize;
Run Code Online (Sandbox Code Playgroud)

如果您使用ENCODING_AC3,则 报告的播放头位置AudioTrack仍以样本形式表示。您需要将其转换为字节,或者将写入的字节数转换回样本。无论哪种方式,您都需要知道 AC3 流的比特率(即384000bps

int bytesWritten = track.write(...);
writtenPos += bytesWritten * samplerate / (bitrate / 8);
Run Code Online (Sandbox Code Playgroud)