在我想要创建的应用程序中,我面临一些技术障碍.我在应用程序中有两个音乐曲目.例如,用户将音乐背景导入为第一曲目.第二路径是由用户记录到由扬声器设备(或耳机)播放的第一轨道的节奏的语音.此刻我们面临延迟.在应用程序中录制和回放之后,用户听到轨道之间失去同步,这是由于麦克风和扬声器延迟而发生的.
首先,我尝试通过过滤输入声音来检测延迟.我使用android的AudioRecord类和方法read().这个方法用音频数据填充我的短数组.我发现这个数组的初始值是零,所以在我开始将它们写入输出流之前我决定将它们删除.因此我将这些零视为麦克风的"预热"延迟.这种方法是否正确?这个操作给出了一些结果,但它没有解决问题,在这个阶段,我远离那个.
但最糟糕的情况是启动扬声器和播放音乐之间的延迟.这种延迟我无法过滤或检测.我试图创建一些计算延迟的校准功能.我通过扬声器发出"嘟嘟"的声音,当我开始播放时,我也开始测量时间.然后,我开始录制并听取麦克风检测到的声音.当我在应用程序中识别出这个声音时,我会停止测量时间.我重复这个过程几次,最终值是这些结果的平均值.这就是我尝试测量设备延迟的方法.现在,当我有这个值时,我可以简单地向后移动第二个轨道以实现两个记录的同步(我将丢失一些初始毫秒的记录,但我跳过这种情况,现在,有一些可能来解决它) .我认为这种方法可以解决问题,但事实证明这并不像我想象的那么简单.我在这里发现了两个问题:1.同时播放两首曲目时延迟2.设备音频延迟随机.
第一个:我使用AudioTrack类播放两首曲目,我运行如下方法play():
val firstTrack = //creating a track
val secondTrack = //creating a track
firstTrack.play()
secondTrack.play()
Run Code Online (Sandbox Code Playgroud)
此代码导致播放曲目阶段的延迟.现在,我甚至不必考虑录制时的延迟; 我不能同时播放两首曲目而没有延迟.我用一些外部音频文件测试了这个(没有记录在我的应用程序中) - 我使用上面的代码启动相同的音频文件,我可以看到延迟.我也尝试使用MediaPlayer类,我也有相同的结果.在这种情况下,我甚至尝试在回调OnPreparedListener调用时播放曲目:
val firstTrack = //AudioPlayer
val secondTrack = //AudioPlayer
second.setOnPreparedListener {
first.start()
second.start()
}
Run Code Online (Sandbox Code Playgroud)
它没有帮助.我知道Android还提供了一个名为SoundPool的类.根据文档,它可以更好地同时播放曲目,但我不能使用它,因为它只支持小音频文件,这不能限制我.我该如何解决这个问题?如何在同一时间精确地开始播放两首曲目?
第二个:音频延迟不是确定性的 - 有时它更小,有时它很大,而且它不在我的手中.因此,测量设备延迟可以再次帮助 - 它无法解决问题.
总结一下:有没有任何解决方案可以为我提供每个设备(或应用会话?)或其他检测实际延迟的触发器的确切延迟,以便在同时回放两个轨道时提供最佳同步?
先感谢您!