在 Javascript 中模拟 MIDI 节拍时钟

发布于 2024-12-17 19:10:19 字数 504 浏览 0 评论 0原文

任务是在 js 中模拟 MIDI 播放器的工作,但只是为了模拟节拍之间的延迟。有一个包含节拍时钟格式的节拍开始时间的数组,例如 [960, 1280, 2200, ...],以及我用于计算每个节拍滴答声的毫秒时间的公式:

var beatTickTime = 60000 / (tempo * 96);

问题出在非常慢的滴答声中实时生成。即使我使用1秒的延迟,它仍然很慢。下面是它的实现方式:

var tickTimer = setInterval(function() {
     ...
     tickCount += 1; 
}, beatTickTime); // or just 1 ms

我应该通过 tickCount += someNumber 传递一些节拍滴答声吗?或者有更通用的方法来解决这个问题?另外,我不确定公式中的 96(PPQ * 4 次)。

PS 节拍刻度来自已解析的吉他专业文件

The task is to emulate the MIDI player work in js, but just for emulate delays between beats. There is an array with beat starting times in beat clock format, for example [960, 1280, 2200, ...], and the formula I'm using for calculate millisecond time for each beat tick:

var beatTickTime = 60000 / (tempo * 96);

The problem is in very slow tick real time generation. Even if I use 1 second delay, it is still very slow. Here is how it was implemented:

var tickTimer = setInterval(function() {
     ...
     tickCount += 1; 
}, beatTickTime); // or just 1 ms

Should I pass some beat ticks doing tickCount += someNumber? Or there is more common way to solve this problem? Also I'm not sure about 96 (PPQ * 4 time) in my formula.

P. S. beat ticks comes from parsed guitar pro file

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

思念绕指尖 2024-12-24 19:10:19

无法保证 setInterval() 会按照您要求的速度运行。即使超时设置为 1,您也不能指望该函数每秒被调用 1,000 次。

您很可能需要执行如下操作:

var startTime = (new Date()).getTime();
setInterval(function() {
  var relTime = (new Date()).getTime() - startTime;
  // relTime is now the number of ms since the script started

  /*
  In here, you'll need to see if relTime is large enough to indicate the next
  beat has been reached. So that means keeping some sort of external marker
  to indicate the most recent beat that has occurred -- when relTime is big
  enough to move that marker to the next beat, also run any code that is
  necessary to handle that beat.
  */
}, 1);

循环“尽可能快地”运行,但仍然比预期慢得多。它测量相对于脚本开始的当前时间,并确定每次迭代的差异。您可以将该时间除以歌曲的节奏,然后您就会知道您当前在歌曲中的位置。

There's no guarantee that setInterval() will run as fast as you ask it to. Even if the timeout is set to 1, you can't count on the function being called 1,000 times each second.

You'll most likely need to do something like the following:

var startTime = (new Date()).getTime();
setInterval(function() {
  var relTime = (new Date()).getTime() - startTime;
  // relTime is now the number of ms since the script started

  /*
  In here, you'll need to see if relTime is large enough to indicate the next
  beat has been reached. So that means keeping some sort of external marker
  to indicate the most recent beat that has occurred -- when relTime is big
  enough to move that marker to the next beat, also run any code that is
  necessary to handle that beat.
  */
}, 1);

The loop runs "as fast as it can" but still much more slowly than desired. It measures the current time relative to the start of the script, and determines the difference at each iteration. You could divide that time by the tempo of the song, and you'll have an indicator of where in the song you currently are.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文