【发布时间】:2020-08-17 20:46:18
【问题描述】:
我想在 Android Wear 设备上录制原始音频,并将其与其他传感器数据(例如加速度计)精确同步。
为了录制原始音频,我使用AudioRecord,但是如何确定音频流任何部分的正确时间戳?
基本问题是我从缓冲区获取原始音频帧,而没有关于这些帧在缓冲区中的时间长短、丢失了多少帧等信息。
所以要获取我在循环中调用AudioRecord.read() 的帧数据,但是我如何判断特定帧何时被记录?
我可以看到三种确定时间戳的方法,但在我看来,所有这些方法都是错误的:
-
通过调用
SystemClock.elapsedRealtimeNanos()获取调用AudioRecord.startRecording()之前或之后的当前系统时间,然后根据采样率和帧大小计算每个chunk的时间。但是根据我的测试,在录制实际开始之前,会有很大的延迟。每当某些帧丢失时,时间也会不同步,例如当处理暂停片刻时。 -
获取
AudioRecord.read()之前或之后的当前系统时间。但这可能不是记录这些数据的时间,那可能发生得更早一些。如果还没有数据可用,read() 将阻塞,之前获取的时间戳将完全错误。 -
AudioRecord.getTimestamp()给出当前正在录制的帧的时间。但这不一定是我目前正在阅读的帧,我可能落后了几帧,或者我可能错过了一些帧。并且根据初始测试,在开始后的一段时间内,时间戳只是零。
这会给我留下 6 个可能错误的时间戳,如下面的代码所示。其中任何一个甚至接近准确吗?
recorder = new AudioRecord(...)
// timeBeforeStart = SystemClock.elapsedRealtimeNanos()
recorder.startRecording()
// timeAfterStart = SystemClock.elapsedRealtimeNanos()
...
// timeBeforeRead = SystemClock.elapsedRealtimeNanos()
// recorder.getTimestamp(frameTimeBeforeRead, AudioTimestamp.TIMEBASE_BOOTTIME)
recorder.read(myArray, 0, mySize);
// recorder.getTimestamp(frameTimeAfterRead, AudioTimestamp.TIMEBASE_BOOTTIME)
// timeAfterRead = SystemClock.elapsedRealtimeNanos()
在确定字节数组中数据对应的时间戳时,哪种方法最准确?
是否有不同的方法来检索具有准确时间戳的原始音频数据?
【问题讨论】:
-
也许 this google repo 可以帮助你(查看名为 AudioTimestampPoller 的类)
-
如果我解释 AudioTimeStampPoller 正确,它可以解决 getTimestamp() 的一些棘手行为,但我仍然不太明白如何将该时间戳与当前读取的帧对应( ) 调用从缓冲区返回,而不是当前正在录制的帧。所以我不太明白它如何比当前系统时间更准确甚至不同
-
跳出框框思考 - 不能您只是在扬声器上创建可以与其他音频一起记录并用于随后像 PLL 一样同步帧的高频光点或尖峰?
-
这可能会起作用,但是我需要获得准确的音频输出时间戳,在排队音频和实际扬声器之间存在未知延迟,不确定这是否更容易。另一种选择当然是点击手表,这将产生相关的音频和加速度计信号,但我真的希望有一个更优雅的解决方案。
-
@HugoRune 你有没有找到一个可以接受的解决方案?我现在正在研究类似的想法,很想知道您是否在 7 个月后发现了什么。
标签: java android wear-os audio-recording audiorecord