【发布时间】:2013-05-10 12:12:02
【问题描述】:
我正在创建鼓机,但在输出 MIDI 节拍时钟时遇到了一些问题。 为简单起见,我通过调用 Thread.sleep(_time) 将内部时钟设置为运行,其中 _time 是通过以下代码计算的十六分音符的时间量:
/**
* Calculates the length of a semiquaver in the sequencer
* @return the time of a semiquaver in milliseconds
*/
private void calculateTempo()
{
Log.i(DEBUG_TAG , "Calculated tempo.");
/**
* Fjärdedelsnot
*/
_quarterNote = 60000/_tempo;
/**
* Sextondel
*/
_sixteenthNote = (_quarterNote/4);
}
_tempo 是 BPM 的整数值。 正如我所说,我的鼓机运行良好,但是在输出节拍时钟时我遇到了问题。 从属设备中的节拍时钟预计每四分音符接收 24 个脉冲,这给我们提供了每十六分音符 6 个脉冲的速率。 我正在使用 timer.scheduleAtFixedRate 将消息添加到输出队列。
假设我们的速度为 120 BPM,这给了我们每四分音符 60000/120 = 500 的时间,即每十六分音符 125 毫秒。 每个十六分音符应该有六个脉冲,125 / 6 = 20.83333.. 你可以明白为什么这让我有点吃惊。 scheduleAtFixedRate 只需要毫秒作为参数,所以我必须制作一个精度更高的计数器,但即使我使用纳秒,一段时间后事情也会开始漂移..
我真的一直在梳理 Java MIDI api,试图找到可以帮助我的东西,但我似乎找不到为此设计的任何方法。 如果您有任何建议,请告诉。
干杯。 /M
【问题讨论】:
-
20.8333ms比这些计时器要准确得多。您需要的是一个尽可能频繁地运行的计时器,用于检查微时间。如果经过的时间是>= 20.8ms,则发送时钟滴答。重要的是,从长远来看,您是准确的。如果你最后 24 个时钟的节拍与你的节奏平均一致,那么你就没事了。这就是为什么您应该在开始发送时钟滴答时保留初始偏移量,并在计时器中与它进行比较。 -
这真的有问题吗?每次节拍你会偏离 0.0016%。这相当于每 365 天只损失 14 小时。对于只打鼓的东西来说,这似乎是一个合理的损失。
标签: java asynchronous midi outputstream