Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/433.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript WebAudio计时是如何工作的?使用setInterval是一个糟糕的解决方案吗?_Javascript_Html_Timer_Web Audio Api_Synthesizer - Fatal编程技术网

Javascript WebAudio计时是如何工作的?使用setInterval是一个糟糕的解决方案吗?

Javascript WebAudio计时是如何工作的?使用setInterval是一个糟糕的解决方案吗?,javascript,html,timer,web-audio-api,synthesizer,Javascript,Html,Timer,Web Audio Api,Synthesizer,我正在尝试用WebAudio API制作一个合成器/音序器。主要是制作一些可以播放由音符和事件组成的歌曲的东西,比如MIDI,以控制合成器的多个通道。但我仍然需要解决时间方面的问题 我已经阅读了WebAudioAPI的教程,但我不太了解计时/调度/时钟是如何工作的。起初,我做了一个为按键弹奏音符的键盘,这不需要考虑时间。然后,我使用setInterval让振荡器以特定的时间间隔播放一系列音符。然而,我注意到,在过去在谷歌Chrome中切换标签时,播放速度明显减慢,我认为资源密集度较低,但其他sy

我正在尝试用WebAudio API制作一个合成器/音序器。主要是制作一些可以播放由音符和事件组成的歌曲的东西,比如MIDI,以控制合成器的多个通道。但我仍然需要解决时间方面的问题

我已经阅读了WebAudioAPI的教程,但我不太了解计时/调度/时钟是如何工作的。起初,我做了一个为按键弹奏音符的键盘,这不需要考虑时间。然后,我使用
setInterval
让振荡器以特定的时间间隔播放一系列音符。然而,我注意到,在过去在谷歌Chrome中切换标签时,播放速度明显减慢,我认为资源密集度较低,但其他synth库没有这个问题。此外,我只能假设使用
setInterval
对于平滑(缓冲的字是否正确?)播放不是很好,特别是考虑ADSR信封振荡器时

据我所知,WebAudio API有一个不断增加的
currentTime
timer变量。但是,如果笔记存储在一个数组中,我想以设定的速率循环它,那么如何操纵WebAudio计时器以设定的速率迭代数组?My根本不考虑WebAudio计时器,只需使用
setInterval
调用
voice()
来播放音符,覆盖最后播放的声音

除了
setInterval
,是否有更好或更有效的方法来播放/循环音符序列


只是一个澄清的更新:当我写这个问题时,我正在使用
setInterval
以固定的间隔播放一系列音符(例如,非计划的——不断启动/停止振荡器),并想知道更可靠的方式播放音符。我发现更好的解决方案是在
osc.frequency
上使用
setValueAtTime
以及
GainNode
。对于一个简单的原型synth来说,这很好,但是更高级的synth可以使用
osc.start
osc.stop
上的计时器。问题是循环播放歌曲。为了循环,我需要不断地安排更多的音符,以便在歌曲结束时重新开始。我可以使用
setInterval
来安排整个歌曲循环,但它仍然必须保持播放歌曲的时间,
setInterval
(甚至Web工作者的
onmessage
调用)可以在选项卡处于非活动状态时减慢。setInterval的时钟甚至不可靠,所以我只要每隔5毫秒检查一次
(currentTime>=songTime)
,如果条件满足,就安排时间。那种方法可能不太有效

几年前我写了这篇文章:。它进入网络音频定时器和设置间隔之间的差异;简而言之,您不能在web音频时钟中“操纵时间”,它是由声卡中的硬件时钟驱动的。不过,您可以将事件安排在其时间范围内,使用setInterval作为非常紧张/较慢的周期提醒来安排新事件

至于切换标签的问题,这是一个1Hz的速率限制器,大多数现代浏览器都必须避免使用setInterval作为渲染计时器(例如,setInterval以16ms的间隔尝试调度每一帧视频)的用户的功耗。您可以通过两种方式避免这种情况-使用Web Workers进行黑客攻击,我在metronome演示()中使用了这种方法,或者您可以在窗口失去焦点时(在窗口对象上触发模糊事件),开始一次调度超过1s的事件。唯一的问题是当窗口再次获得焦点时(onfocus事件在窗口对象上激发),您将在Web音频中安排多达一秒钟的事件-您无法切换回窗口并立即单击“停止”,例如


setInterval本身并不能很好地解决重复节奏的音乐计时问题,因为当主线程中有大量其他内容(包括垃圾收集)时,它会抖动(即延迟)。您将开始听到抖动,尤其是在性能较差的CPU上。

我感觉自己快要失去理智了。我无法再可靠地触发
setInterval
减速问题。只有在Chrome中,这种情况才会发生,很少和随机发生,更糟糕的是,在使用Web Worker黑客方法时,它甚至会减慢速度。我使用BLOBURI方法是因为Chrome无法在本地运行Web Workers(Firefox可以)。嗯,我不能用那个密码触发它。您的硬件/操作系统是什么?在2012 Intel i7 2770/16GB RAM/Win7和2015 Intel i5/8GB RAM/Win10上进行测试。如果不能人工触发,是否有方法在代码中检测是否发生了“节流”或“去同步”,这在webworker自己的线程中永远不会发生?因此有两件事:a)可能我必须触发节流。b) 当使用Web Worker时,常量
onmessage
在主线程中调用,这解释了为什么当我遇到节流时,它也会影响Web Worker。