2

我真的很快就会开始为www.daveconservatoire.org 开发一系列基于音乐的应用程序。

目前阻碍我的是,通过阅读各种文章/帖子等,我无法确定使用 javascript 在应用程序中产生准确的计时是否现实。我们所说的正确时间可能只有 10 毫秒。

例如,一个更简单的应用程序是节拍器,它可以设置为以给定的间隔滴答声 - 例如,60BMP 将要求每秒播放一次滴答声。

这可以通过 javascript/html5 实现吗?我发现的所有节拍器示例都是用 Flash 编写的,大概是因为在 JS 中很难使用准确的计时。

4

2 回答 2

3

我发现你的问题很有趣,所以我决定自己做一个小测试。Javascript 的 setInterval 函数似乎不足以做一个节拍器类型的应用程序。所以我建立了一个使用当前时间的自定义“类”,它似乎在 +-3 毫秒内是准确的。你的旅费可能会改变。代码在这里:http: //jsfiddle.net/66YJz/

// Custom timer class

// f = function to call
// m = ms
function timer(f, m)
{
    var target_time = (new Date()).getTime() + m;
    var margin = 3;

    setInterval(function(){
        var now = (new Date()).getTime();
        var dif = target_time - now;
        // If within acceptable timeframe, call function
        if (dif <= margin && dif >= -margin) {
            target_time = now + m + dif;
            f();
        }
        // For some reason we missed the time frame.
        // Skip and move on to next
        if (dif < -margin ) {
           target_time += m;
           //margin += 1;
        }
    },
    1);
}

我只是把它掀了起来,所以我相信还有很大的改进空间。

于 2012-10-31T15:58:55.990 回答
0

JavaScript 中的高分辨率时间有一个正在进行中的规范。

但是,在它有用之前,情况会更加棘手。

我找到了一个关于这个主题的有趣教程:http: //www.html5rocks.com/en/tutorials/audio/scheduling/

它详细介绍了所涉及的各种问题,并提出了一些看似合适的方法,特别是如果您想要对 WebAudio 进行排序。我自己还没有对其进行测试,但这里有一些文章中的重要引述来描述这些问题以及如何有效地解决这些问题的概述:

JavaScript 计时 API 最糟糕的部分是,尽管 Date.now() 的毫秒精度听起来不错,但 JavaScript 中计时器事件的实际回调(通过 window.setTimeout() 或 window.setInterval)布局、渲染、垃圾回收、XMLHTTPRequest 和其他回调很容易被扭曲数十毫秒或更长时间——简而言之,主执行线程上发生的任何事情。

...

[给定示例] 设法允许速度控制同时保持坚如磐石的计时方式是一种协作:一个每隔一段时间触发一次的 setTimeout 计时器,并在未来为单个音符设置 Web 音频调度。setTimeout 计时器基本上只是检查是否需要根据当前速度“很快”安排任何音符,然后安排它们......

他们还建议可以使用 requestAnimationFrame 代替 setTimeout,从而实现与图形的精确同步;这将是游戏的自然方法。

本教程不涵盖如果不是 WebAudio 尝试排序的人可能会做什么。在我有点模糊的情况下,我实际上想通过网络控制 SuperCollider 的一个实例。为了使其工作,我可以调整建议的方法,将执行时间指定为每个 OSC 消息的一部分,并允许 scsynth 调度程序代替 WebAudio 调度程序。

但是,可能还有其他不太容易适应的情况:例如,使用音符消息控制普通 MIDI 合成器将无法使用这种方法。WebMIDI 规范草案的作者预计它将与我在此答案开头提到的高分辨率时间 API 一起使用。

于 2013-11-03T20:05:17.003 回答