这可以是 Javascript 或数学问题。
我正在尝试设置一个不会偏离系统时钟的间隔。我还需要能够在运行时更改间隔,因此大多数 cron 库都不能达到目的。我所说的时间尺度是 10-5000 毫秒。我关心的不是微精度计时,而是从长远来看零漂移。
我做了一个设置间隔的简单解决方案,回调函数比较间隔已经运行了多少次,并将它除以“间隔”已经运行的所有时间。总时间/迭代将给出迭代所产生的准确的总体漂移。这确保不会累积漂移。测量从上次运行迭代的时间并不能保证没有累积漂移。我的示例每“准确”间隔播放一个 MIDI 音符”。
测试应用:
var targetInterval=(60000/120)/4;
var lastDrift=0;
var jazz = require('jazz-midi');
var midi = new jazz.MIDI();
var name = midi.MidiOutOpen(0);
if(name){
console.log('Default MIDI-Out port:', name);
} else {
console.log('Cannot open default MIDI-Out port!');
}
var absoluteInterval=0;
var absoluteDrift=0;
var timeAnchor=0;
var iterations=0;
function a(){
var now=new Date();
var elapsed=now-timeAnchor;
console.log("tick");
iterations++;
absoluteInterval=(elapsed/iterations);
absoluteDrift=targetInterval-absoluteInterval;
setTimeout(function() {
a();
}, targetInterval+absoluteDrift);
console.log(" Interval:"+absoluteInterval);
console.log(" drift:"+absoluteDrift);
midi.MidiOut(0x99,(Math.random()*60)+40,100);
}
function changeRate(to){
targetInterval=to;
iterations=0;
timeAnchor=new Date();
}
function start(){
timeAnchor=new Date();
a();
}
start();
我现在的问题是当速率改变时,漂移恢复很慢。事实上,漂移恢复是无限的,因为 targetInterval-(elapsed/iterations); 总是接近零,但永远不会归零;因此,添加到间隔中的额外部分刚好不够。我尝试了乘法,但这会导致恢复间隔被夸大,并且仍然存在相同的数学原理,避免了总恢复。我应该尝试量化(ceil)恢复率,还是有一个更数学意义上的解决方案?