如何在 Android 上使用 AudioTrack.getTimestamp() 来计算延迟?
How to use AudioTrack.getTimestamp() on Android to calculate latency?
我看到许多资源建议在现代 Android 版本上使用 AudioTrack.getTimestamp()
来计算 audio/video 同步的音频延迟。
例如:
https://developer.amazon.com/docs/fire-tv/audio-video-synchronization.html#section1-1
https://groups.google.com/forum/#!topic/android-platform/PoHfyNK54ps
但是,其中 none 解释了 如何 使用时间戳来计算延迟?我正在努力弄清楚如何处理时间戳的 framePosition/nanoTime 来得出延迟数。
因此在此 API 之前,您将使用 AudioTrack.getPlaybackHeadPosition()
,这只是一个近似值。因此,为了考虑延迟,您必须使用两种隐藏方法之一的延迟值来抵消该值:AudioManager.getOutputLatency()
或 AudioTrack.getLatency()
.
使用新的 AudioTrack.getTimestamp()
API,您可以在给定时间直接在输出处获取播放头位置的快照。因此,它是完全准确的,并且已经考虑了设备延迟。因此,现在无需调用任何其他 API 来达到 add/remove 延迟。
需要注意的是,这个时间戳只是一个快照,文档建议您不要经常调用这个新方法。所以获得 "current" 位置的技巧是使用你的最后一个快照并线性插值当前值应该是什么:
playheadPos = timestamp.framePosition +
(System.nanoTime() - timestamp.nanoTime) * samplerate / 1e9;
然后可以通过维护另一个每次 AudioTrack.write()
完成时递增的计数器,将此位置与您写入 AudioTrack
的帧数进行比较:
int bytesWritten = track.write(...);
writtenPos += bytesWritten / pcmFrameSize;
如果您正在使用 ENCODING_AC3
,AudioTrack
报告的播放头位置仍然是样本。您需要将其转换为字节,或者将您写入的字节数转换回样本。无论哪种方式,您都需要知道 AC3 流的比特率(即 384000bps
)
int bytesWritten = track.write(...);
writtenPos += bytesWritten * samplerate / (bitrate / 8);
我看到许多资源建议在现代 Android 版本上使用 AudioTrack.getTimestamp()
来计算 audio/video 同步的音频延迟。
例如:
https://developer.amazon.com/docs/fire-tv/audio-video-synchronization.html#section1-1
https://groups.google.com/forum/#!topic/android-platform/PoHfyNK54ps
但是,其中 none 解释了 如何 使用时间戳来计算延迟?我正在努力弄清楚如何处理时间戳的 framePosition/nanoTime 来得出延迟数。
因此在此 API 之前,您将使用 AudioTrack.getPlaybackHeadPosition()
,这只是一个近似值。因此,为了考虑延迟,您必须使用两种隐藏方法之一的延迟值来抵消该值:AudioManager.getOutputLatency()
或 AudioTrack.getLatency()
.
使用新的 AudioTrack.getTimestamp()
API,您可以在给定时间直接在输出处获取播放头位置的快照。因此,它是完全准确的,并且已经考虑了设备延迟。因此,现在无需调用任何其他 API 来达到 add/remove 延迟。
需要注意的是,这个时间戳只是一个快照,文档建议您不要经常调用这个新方法。所以获得 "current" 位置的技巧是使用你的最后一个快照并线性插值当前值应该是什么:
playheadPos = timestamp.framePosition +
(System.nanoTime() - timestamp.nanoTime) * samplerate / 1e9;
然后可以通过维护另一个每次 AudioTrack.write()
完成时递增的计数器,将此位置与您写入 AudioTrack
的帧数进行比较:
int bytesWritten = track.write(...);
writtenPos += bytesWritten / pcmFrameSize;
如果您正在使用 ENCODING_AC3
,AudioTrack
报告的播放头位置仍然是样本。您需要将其转换为字节,或者将您写入的字节数转换回样本。无论哪种方式,您都需要知道 AC3 流的比特率(即 384000bps
)
int bytesWritten = track.write(...);
writtenPos += bytesWritten * samplerate / (bitrate / 8);