我正在研究一个节奏游戏,这意味着我希望屏幕元素显示在节拍上。为此,我需要能够告诉我当前音乐的时间轴上的位置。我正在使用Naudio库(ASIO更具体),我知道我可以调用CurrentTime
我正在播放的WaveStream
字段,以了解自音乐播放以来已经过了多少时间开始播放,然而Field似乎不是非常准确(至少不够精确到流畅地显示移动的屏幕元素),因为它只是基于每秒平均字节数的近似值。这就是我尝试将StopWatch
同步到音乐的原因。然而,无论我尝试什么,我总是得到一个抵消。我目前的设置是这样的:
var audioFileReader = new AudioFileReader("music.mp3");
var waveChannel32 = new WaveChannel32(audioFileReader); //
var asioOut = new AsioOut(0);
var stopWatch = new Stopwatch();
asioOut.Init(waveChannel32);
asioOut.Play();
Task.Delay(1000).Wait();
waveChannel32.Position = 0;
stopWatch.Start();
如果我然后将stopWatch.Elapsed
与waveChannel32.CurrentTime
进行比较,看起来stopWatch
就在现场(它跳了大约ms10ms,因为后者不准确,但平均来说它们大致相等但是,如果我把它与其他节奏游戏中的文件进行比较(注意节拍时间戳),我的StopWatch
提前50分25秒。现在有人可能会说这些文件可能不准确或者其他节奏游戏有抵消,但在几个游戏中检查了无数文件之后我觉得可以说我已经排除了它。
导致我的偏移的原因是什么?如何解决?
编辑:
我正在测量这样的偏移量:无论何时我按下一个键,我都会发出一声咔哒声(在节奏游戏中被称为“hitsount”)并且标签与试图同步的歌曲不是我的键盘输入放置得到的hitsound与节拍并测量我的平均偏移量。这样我就不需要考虑硬件和音频驱动程序的延迟。当然,我不是一个机器人,因此不完全准确,但我的不准确性通常会传播,所以我可以拿平均值,即使没有它,我至少准确到足以告诉那些错误。