Javascript 修正区间漂移

Javascript 修正区间漂移,javascript,math,timer,drift,Javascript,Math,Timer,Drift,这可能是Javascript或数学问题 我正在尝试创建一个不会偏离系统时钟的间隔。我还需要能够在运行时更改时间间隔,因此大多数cron库都不能达到这个目的。我说的时间尺度是10-5000毫秒。我关心的不是微精度定时,而是长期零漂 我做了一个简单的解决方案,设置了一个间隔,回调函数比较了间隔运行的次数,并将其除以“间隔”运行的所有时间。总时间/迭代次数将给出迭代所产生的准确的总体漂移。这可确保不会累积任何漂移。从迭代的最后一次运行开始测量时间并不能保证没有累积漂移。我的示例每“精确”一个音程播放一

这可能是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-(经过/迭代次数);总是接近零,但它永远不会达到零;因此,添加到间隔中的额外值刚好不足。我尝试了乘法,但这会导致夸大的恢复间隔,并且仍然存在相同的数学原理,以避免总恢复。我是否应该尝试量化(ceil)恢复率,或者是否有更具数学意义的解决方案?

你看过web音频API吗?我很确定它有一种稳定音乐计时的机制
setInterval()
没有长时间的漂移。只是由于JavaScript的运行时限制,每个回调都不能得到保证,因为它是单线程的,并且可能有其他东西正在执行。@PatrickHund谢谢!希望我不用添加依赖项就可以离开。我忘了提到我正在使用Node@PatrickRoberts是的,spe特别是在节点中。但遗憾的是,它不允许在rate@Joaquin更改速率的方法是存储对
let ref=setInterval(…);
输出的引用,然后在需要更改时,确保
clearInterval(ref)
,然后再将其设置为新的。这样,您可以利用JavaScript内置的漂移缓解功能,同时具有运行时可配置的速率。