gpt4 book ai didi

javascript - Web Audio API - 调度问题

转载 作者:行者123 更新时间:2023-11-28 03:14:33 25 4
gpt4 key购买 nike

我正在尝试构建一个循环音序器,它利用网络音频 API 和许多不同长度的不同音乐循环。一般的想法是循环是随机选择的(在一定程度上),然后以特定顺序播放开头、中间和结尾部分。有四个 channel - 贝司、鼓、主音和 FX。就在最后一部分结束之前,选择了一组新的样本并使用相同的公式回放。

然后我打算添加一个可视化工具,也许还有一些自动化 - 即可能为最后几个小节添加混响。

我必须尝试遵循“两个时钟的故事”方法,但由于我对编程和 javascript 还比较陌生,所以我很难实现它。我认为这可能会使事情变得比完成此任务所需的复杂。

我最初的想法是创建一个 for 循环,其中包含指定我希望循环播放的次数的 play 方法,但我发现样本会同时播放。根据“两个时钟的故事”,我尽可能避免使用 setTimeout() 和 setInterval(),因为这只会导致延迟。

我的第二个想法是一次调用所有播放方法,除了每个播放方法都在“歌曲”中的某个点提示,例如

START SECTION

playlead(time, buffer);

playdrums(time + length*2, buffer);

MIDDLE SECTION

playlead(time + length*10, buffer);

playdrums(time + length*10, buffer);

playlead2(time + length*10, buffer);

playbass(time + length*10, buffer);

等等。然而,这已经导致了它自己的一系列问题,而且似乎是一种相当低效的解决方法。

感觉好像缺少一个明显的解决方案,但经过相当多的研究,我仍然无法解决它。似乎最简单的做法是让我的 for 循环中的 playSound 函数等待样本完成,然后再迭代,但这比看起来要难得多。如果有人可以提供任何建议,我将不胜感激,因为我对此束手无策。提前致谢!

//补充一下,我在第二种方法中遇到的问题是,为了实际播放即使只是开始部分,代码也必须看起来像这样才能播放大约 30 秒:

///START SECTION ( for 30 seconds or so)

playlead(time, buffer);
playlead(time + length, buffer);
playlead(time + length*2, buffer);
playlead(time, + length*3, buffer);

playbass(time, buffer);
playbass(time + length, buffer);
playbass(time + length*2, buffer);
playbass(time, + length*3, buffer);

playlead1(time, buffer);
playlead1(time + length, buffer);
playlead1(time + length*2, buffer);
playlead1(time, + length*3, buffer);

playdrums(time, buffer);
playdrums(time + length, buffer);
playdrums(time + length*2, buffer);
playdrums(time, + length*3, buffer);

这是一次对 play() 方法的 16 次调用。要播放整首歌曲,在被重新缓冲并要求再次播放之前,很可能会有 4 个部分。也就是说,加载后直接同时至少有 16*4 (64) 个调用。我猜测使用光谱仪、自动音频参数和音量/效果 slider 可能会导致一些问题?谢谢。

////这是我的大部分问题都源于的代码示例:

function LeadStartSection
(buffer, time, gainNode, bufferList)
{

console.log("playing lead Start section");
var timer = setTimeout(function() { //checks when audiobuffer has finished
console.log('sample times out at' + timer);
}, buffer.duration * 1000);

var Length = buffer.duration;
console.log(Length);
var n = 1;

////Example of second method/////
playLead(buffer, time, gainNode,n, bufferList);
playLead(buffer, time + Length, gainNode, Length,n, bufferList);
playLead(buffer, time + Length*2, gainNode, Length,n, bufferList);
playLead(buffer, time + Length*3, gainNode, Length, n+2, bufferList);
}

///example of what I would like to do///

for (i=o; i<leadPlayCount; i++)
{
PlayLead(buffer, gainNode, Length, bufferList);
}

*在第一个示例中,n 被传递给函数,因为中间部分将在 n = n+2 时被提示。

*在第二个示例中,我在调用 playLead 时遇到了问题,因此每个循环都在循环结束之前的循环之后开始。相反,该方法一次被调用 4 次。这听起来不太好!我在想也许有一种方法可以让 for 循环在收到 playLead 方法的返回值之前不会继续,但看来我错了。

我希望这能让您对我所处的位置有更多的了解。请询问您是否希望我包括任何其他内容。感谢一百万的帮助!

最佳答案

好的,我认为您可能只是误解了循环的工作方式、音频 API 的工作方式或 JavaScript 的工作方式。如果你有这样的功能:

function playBuffer(time, buffer) {
var node = context.createBufferSource();
node.buffer = buffer;
node.connect(context.destination);
node.start(time);
}

然后,要连续多次播放同一个缓冲区,您可以这样做:

playBuffer(context.currentTime, buffer);
playBuffer(context.currentTime + buffer.duration, buffer);
playBuffer(context.currentTime + 2 * buffer.duration, buffer);
playBuffer(context.currentTime + 3 * buffer.duration, buffer);

或:

for (var i = 0; i < 4; i++) {
playBuffer(context.currentTime + i * buffer.duration, buffer);
}

两者是等价的

所以基本上你需要给 buffer.start 一个 future 的开始时间,即大于 context.currentTime,否则它会立即开始。无论是否从循环中调用,所有对 buffer.start 的调用都“现在”发生,但实际开始播放声音的时间由 buffer.start() 的第一个参数决定。

关于javascript - Web Audio API - 调度问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28883494/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com