由于旧的Webaudio脚本处理器自2014年以来已被弃用,而且Audioworklets在Chrome 64中出现,我决定尝试一下。但是我在移植我的应用程序时遇到了困难。我将从一个不错的article中给出两个例子以表明我的观点。
首先是脚本处理器方式:
1 886620 rs201016776 T A 1:886620-TG
1 879576 rs115979567 C T
1 886817 rs111748052;rs10465241 C CATTTT JHU_1.886816
1 889255 rs150003341 C T Variant37585
1 891659 rs116557519 G A JHU_1.891658
另一个填充缓冲区然后播放它的人:
var node = context.createScriptProcessor(1024, 1, 1);
node.onaudioprocess = function (e) {
var output = e.outputBuffer.getChannelData(0);
for (var i = 0; i < output.length; i++) {
output[i] = Math.random();
}
};
node.connect(context.destination);
两者之间的最大区别是第一个在播放期间用缓冲区填充新数据,而第二个在事先生成所有数据。
由于我生成了大量数据,所以我事先无法做到。 Audioworklet有很多examples,但它们都使用其他节点,人们可以在其上运行.start(),连接它并开始生成音频。当我没有这样的方法时,我无法绕过一种方法来做这件事。
所以我的问题基本上是如何在Audioworklet中执行上述示例,当数据在某个数组的主线程中连续生成并且该数据的回放发生在Webaudio线程中时。
我一直在阅读有关消息端口的事情,但我不确定这是否可行。这些例子并没有指出我会说的那个方向。我可能需要的是使用我自己的数据在AudioWorkletProcesser派生类中提供过程函数的正确方法。
我当前基于脚本处理器的代码位于github,特别是在vgmplay-js-glue.js中。
我一直在为VGMPlay_WebAudio类的构造函数添加一些代码,从示例转到实际结果,但正如我所说,我不知道现在要向哪个方向移动。
var node = context.createBufferSource(), buffer =
context.createBuffer(1, 4096, context.sampleRate), data = buffer.getChannelData(0);
for (var i = 0; i < 4096; i++) {
data[i] = Math.random();
}
node.buffer = buffer;
node.loop = true;
node.connect(context.destination);
node.start(0);
答案 0 :(得分:1)
所以我的问题基本上是如何在Audioworklet中进行上述示例,
对于您的第一个示例,已经有一个AudioWorklet版本: https://github.com/GoogleChromeLabs/web-audio-samples/blob/gh-pages/audio-worklet/basic/js/noise-generator.js
我不建议使用第二个示例(也称为缓冲区拼接),因为它会创建大量源节点和缓冲区,因此会导致GC干扰主线程中的其他任务。如果预定的开始时间不落在样本上,也可能在两个连续缓冲区的边界处发生不连续。话虽如此,在这个具体的例子中你不会听到毛刺,因为源材料是噪音。
当数据在某个数组的主线程中连续生成,并且该数据的回放发生在Webaudio线程中。
您应该做的第一件事是将音频发生器与主线程分开。音频发生器必须在AudioWorkletGlobalScope
上运行。这就是AudioWorklet系统的全部目的 - 更低的延迟和更好的音频渲染性能。
在your code中,
应在VGMPlay_WebAudio.generateBuffer()
回调中调用AudioWorkletProcessor.process()
来填充处理器的输出缓冲区。这与您的onaudioprocess
回调大致匹配。
我一直在阅读有关消息端口的事情,但我也不确定是否也是这样。这些例子并没有指出我所说的那个方向。我可能需要的是使用我自己的数据在AudioWorkletProcesser派生类中提供过程函数的正确方法。
我认为您的使用案例不需要MessagePort
。我已经在代码中看到了其他方法,但除了启动和停止节点之外,他们除了做很多事情之外还做不了什么。这可以通过在主线程中连接/断开AudioWorkletNode来完成。不需要跨线程消息传递。
最后的代码示例可以是AudioWorklet的设置。我很清楚,设置和实际音频生成之间的分离可能很棘手,但值得。
很少有人问你:
VGMPlay
类是否可以在工作线程上运行而不与主线程进行任何交互?除了启动和停止之外,我在代码中看不到任何交互。XMLHttpRequest
课程必不可少VGMPlay
?或者可以在其他地方完成吗?