javascript-窗口最小化时的AudioContext计时问题

我按照this article中的说明进行操作,并创建了Javascript节拍器.它利用Web Audio API并以audioContext.currentTime为核心,以实现精确的计时.

我的版本是this plunker,它是克里斯·威尔逊(Chris Wilson)制造的版本的非常简化版本,版本是here.为了使我的版本正常工作,因为它使用的是实际的音频文件,并且不会通过振荡器合成声音,因此来下载插件和this audio file,并将其放置在根文件夹中(这是节拍器的“滴答”声,但您可以使用任何想要的声音).

它的工作原理就像一种魅力-如果不是因为用户将窗口最小化,否则非常精确的节拍器会立即开始打ic.我真的不明白这是什么问题.

Java脚本

var context, request, buffer;
var tempo = 120;
var tickTime;

function ticking() {
    var source = context.createBufferSource();
    source.buffer = buffer;
    source.connect(context.destination);
    source.start(tickTime);
}

function scheduler() {
    while (tickTime < context.currentTime + 0.1) {  //while there are notes to schedule, play the last scheduled note and advance the pointer
        ticking();
        tickTime += 60 / tempo;
    }
}

function loadTick() {
    request = new XMLHttpRequest();                 //Asynchronous http request (you'll need a local server) 
    request.open('GET', 'tick.wav', true);          //You need to download the file @ http://s000.tinyupload.com/index.php?file_id=89415137224761217947
    request.responseType = 'arraybuffer';
    request.onload = function () {
        context.decodeAudioData(request.response, function (theBuffer) {
            buffer = theBuffer;
        });
    };
    request.send();
}

function start() {
    tickTime = context.currentTime;
    scheduleTimer = setInterval(function () {
        scheduler();
   }, 25);
}

window.onload = function () {
    window.AudioContext = window.AudioContext || window.webkitAudioContext;
    context = new AudioContext();
    loadTick();
    start();
};

解决方法:

是的,这是因为当窗口失去焦点时,浏览器会将setTimeout和setInterval设置为每秒一次. (这样做是为了避免由于开发人员使用setTimeout / setInterval进行可视化动画而导致的CPU /功耗下降,并且在选项卡失去焦点时不会暂停动画.)

有两种解决方法:

1)将“向前看”(在您的示例中为0.1秒)增加到大于一秒,例如1.1秒.不幸的是,这将意味着您不能在没有超过一秒钟的延迟的情况下进行更改(例如停止播放或更改速度).因此,您可能只想在窗口上触发模糊事件时才增加该值,而在窗口焦点事件触发时将其更改回0.1.还是不理想.

2)避免节流. :)事实证明您可以执行此操作,因为Web Workers中不会限制setTimeout / setInterval! (这种方法最初是由某人在我的原始文章http://www.html5rocks.com/en/tutorials/audio/scheduling/#disqus_thread中的注释线程中提出的.)我在https://github.com/cwilso/metronome中为节拍器代码实现了这一点:看一下js / metronome.js和js / metronomeworker.js. Worker基本上只是维护计时器,然后将消息封送回主线程.特别看看https://github.com/cwilso/metronome/blob/master/js/metronome.js#L153,看看它是如何开始的.您可以修改该代码段,并按原样使用metronomeworker.js来解决此问题.

上一篇:javascript – setTimeout在Uncaught TypeError中返回错误:Chrome中的AudioContext中的非法调用


下一篇:python制作卡点视频