java - 录制带有准确时间戳的音频
问题描述
我想在 Android Wear 设备上录制原始音频,并将其与其他传感器数据(例如加速度计)精确同步。要录制原始音频,我使用AudioRecord
,但如何确定音频流任何部分的正确时间戳?
基本问题是我从缓冲区获取原始音频帧,没有关于这些帧在缓冲区中的时间长短、丢失了多少帧等信息。
因此,要获取我在循环中调用的帧数据AudioRecord.read()
,但我如何判断何时记录了特定帧?
我可以看到三种确定时间戳的方法,在我看来,所有这些方法都是错误的:
AudioRecord.startRecording()
通过调用获取调用前后的当前系统时间SystemClock.elapsedRealtimeNanos()
,然后根据采样率和帧大小计算每个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()
其中哪一个是确定与字节数组中的数据对应的时间戳的最准确方法?
是否有不同的方法来检索具有准确时间戳的原始音频数据?
解决方案
您需要创建一个相关的音频和加速度计信号 - 您可能还会将手电筒、相机和扬声器等放入混合中。
您需要测试哪些参与者和传感器具有哪些延迟和抖动,以找到能够关联事件以计算接收到的音频延迟和抖动的最佳解决方案(不使用外部设备)。
推荐阅读
- scala - 根据 Scala 中的条件从同一集合的元素创建 Map
- c++ - 如何为模块化应用程序实现 C++ 插件系统?
- css - 使用 css 媒体打印抑制首页标题
- node.js - 错误:SyntaxError:JSON 输入意外结束
- c++ - 通用参考左值不复制对象
- php - 尊重 unique_constraint 而不更新主键
- modal-dialog - Ionic 5 Modal over modal 缺少离子背景
- google-apps-script - 将单个 Google 表格导出到 CSV 文件
- javascript - 在 JS 中发送 POST 正文参数
- python - 在数字列表python中查找特定数字