使用鼓机的设置超时解决延迟问题

Resolving latency with setTimeout for Drum Machine

本文关键字:解决 延迟 问题 超时 设置 鼓机      更新时间:2023-09-26

我目前正在研究一台鼓机,我正在使用setTimeout来使其运行。这是代码的核心:

      var sequencerRun = function(){    
      var currentTime = 0 
      var starting = 200;
      for(var k = 0; k < 16; k++){
        $(".instrument td .beat" + k).each(function(){
          setTimeout(blinker, currentTime,$(this));
        })
        currentTime += starting;
        }
      }
      var timerId, setInt;
      var runSeq = function(){
        setInt = setInterval(sequencerRun,3200);
      }
      $('.play').click(function(){
        stopped = false
        sequencerRun();
        runSeq();
      })
      $('.stop').click(function(){
        clearInterval(setInt);
        stopped = true;
      })

鼓机具有使用table构建的矩阵HTML结构。单击.play时,将发生调度过程,该过程封装在 sequencerRun 中。这涉及运行我的矩阵的列,以确定是否应该有鼓击。这是通过 blinker .调度在每列 1 - 16 上分别在 0,200,...,3200 上创建检查。这就是创建音序器效果的原因。我还有一个setInterval,每 3200 次重新运行此过程,这就是完成运行的方式。

以编程方式,我的代码似乎有意义,我希望它能按时执行。问题是我的实际应用程序往往会卡顿很多,自从我部署它以来,它更加卡顿。这是我的应用的已部署版本。

当您单击整行时,可以最好地听到这种口吃的副作用。我在这里的问题是,谁能判断这种副作用是否是setTimeout的时间不一致的结果,如果是这样,我该如何解决这个问题?还是这与我缺少的其他东西有关?

我认为卡顿问题更多地与您没有预加载乐器有关,而是在每次点击时加载它们,而不是与设置超时有关。

无论如何,我想我会以不同的方式解决这个问题。与其为每个节拍设置新的超时,不如创建一个节拍超时并将逻辑放在那里。类似的东西(伪代码式的,很多东西只缺少一般的想法):

var MAX_BEATS = 16; // I think you had 16 beats in your example?
var BPM = 200; 
var preloadedInstruments = [];
function preloadInstruments(){
  for(i of myInstruments) { // myInstruments would be a list of your instruments (probably just strings with a filename)
     preloadedInstruments.push(new instrument(i)); // You need an instrument class, that would preload the sound and provide a play function
  }
}
var currentbeat = 1;
function beat() {
  var activeInstruments = getActiveInstruments(currentbeat); // You could cache this also for every beat, but I think a simple loop here would be quick enough
  for(instrument of activeInstruments) {
     preloadedInstruments[instrument].play(); // play method of the instrument class called
  }
  currentbeat++;
  if (currentbeat > MAX_BEATS) { 
    currentbeat = 1;
  }
}
setInterval(beat, 60e3 / BPM);