2

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

我已阅读有关 WebAudio API 的教程,但我不太了解计时/调度/时钟的工作原理。起初我做了一个复音合成器,它可以为按键播放音符,这不需要任何时间考虑。然后我使振荡器在特定时间间隔播放一组音符,使用setInterval. 但是我过去注意到谷歌浏览器中切换标签时,播放速度显着减慢,我认为资源密集型较少 - 但其他合成库没有这个问题。此外,我只能假设使用setInterval对于平滑(缓冲正确的词?)播放不是很好,尤其是在考虑 ADSR 包络振荡器时。

从我正在阅读的内容来看,WebAudio API 有一个不断增加的currentTime计时器变量。但是,如果笔记存储在一个数组中并且我想以设定的速率循环它,那么如何操纵 WebAudio 计时器以按照设定的速率迭代数组?我的setInterval 解决方案(音量警告)根本不考虑 WebAudio 计时器,只是调用voice()withsetInterval来播放音符,覆盖最后播放的声音。

是否有更好或更有效的方法来播放/循环除 之外的一系列音符setInterval

只是更新澄清一下:当我写这个问题时,我setInterval习惯于以固定的间隔播放一系列音符(例如,不定期的 - 不断启动/停止振荡器)并且想知道更可靠的方式来播放音符。我发现更好的解决方案是使用setValueAtTimeonosc.frequencyGainNode. 对于一个简单的原型合成器,这很好用,但更高级的合成器可以使用定时器 onosc.startosc.stop。问题是循环播放歌曲。为了循环,我需要不断地安排更多的音符,以便在歌曲结束时重新开始。我可以用它setInterval来安排整个歌曲循环,但它仍然必须保持播放歌曲的时间,并且setInterval(甚至是 Web Workers'onmessage例如,当标签不活动时,可以放慢速度)。setInterval 的时钟甚至不可靠,所以我只需每 5 毫秒检查一次是否(currentTime >= songTime)满足条件,并安排时间。这种方法可能效率不高。我到目前为止所拥有的

4

1 回答 1

4

几年前我写了这篇文章:https ://www.html5rocks.com/en/tutorials/audio/scheduling/ 。它进入了网络音频计时器和 setInterval 之间的区别;简而言之,您不能在网络音频时钟中“操纵时间”,它是由声卡中的硬件时钟驱动的。不过,您可以安排事件在其时间范围内发生,使用 setInterval 作为非常紧张/较慢的周期提醒来安排新事件。

至于您的切换选项卡问题,这是一个 1Hz 速率限制器,大多数现代浏览器都必须避免人们使用 setInterval 作为呈现计时器(例如 setInterval 以 16ms 的间隔尝试调度每一帧视频)的电力成本。您可以通过两种方式避免它 - 使用 Web Workers 的 hack,我在我的节拍器演示 ( https://github.com/cwilso/metronome ) 中使用它,或者您可以在窗口失去焦点时挂钩(onblur 事件触发在窗口对象上)开始一次调度超过 1 秒的事件。唯一的问题是当窗口再次获得焦点时(在窗口对象上触发 onfocus 事件),您将在 Web Audio 中安排多达一秒钟的事件 - 您无法切换回窗口并立即点击“停止”,例如

setInterval 本身对于重复节奏的音乐计时并不是一个很好的解决方案,因为当主线程中发生大量其他事情(包括垃圾收集)时,它会抖动(即延迟)。您将开始听到抖动,尤其是在功能较弱的 CPU 上。

于 2017-02-08T22:23:31.787 回答