これは、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) しようとする必要がありますか、それともより数学的に意味のある解決策がありますか?