0

这可以是 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)恢复率,还是有一个更数学意义上的解决方案?

4

0 回答 0