使用针对Drum Machine的setTimeout解决延迟

时间:2015-06-21 20:07:11

标签: javascript settimeout playback

我目前正在使用鼓机,我正在使用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完成的。调度分别在0,200,...,3200处对每列1-16进行检查。这就是创建音序器效果的原因。我还有一个setInterval,每3200重新运行一次这个过程,这就是运行完成的过程。

以编程方式,我的代码似乎有意义,我的希望是它会按时执行。事情是我的实际应用程序往往口吃很多,并且因为我部署它后更加口吃。 try with resources是我的应用的部署版本。

单击整行时,可以最好地听到这种口吃副作用。我的问题是,任何人都可以判断这种副作用是否是setTimeout时间不一致的结果,如果是这样,我怎么能解决这个问题呢?或者这与我遗漏的其他事情有关吗?

1 个答案:

答案 0 :(得分:1)

我认为口吃问题更多地与你没有预加载乐器而是在每次击中时加载它们,而不是与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);