我正在尝试构建一个循环音序器,它利用网络音频 API 和许多不同长度的不同音乐循环。一般的想法是随机选择循环(在一定程度上),然后以特定顺序播放开头、中间和结尾部分。有四个通道 - 贝司、鼓、主音和 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) 次调用。我猜想使用光谱仪、自动音频参数和音量/效果滑块,这可能会导致一些问题?谢谢。
//// 这是我的大部分问题都源于的代码示例:
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 方法的返回之前不会继续,但似乎我错了。
我希望这可以让您对我所处的位置有更多的了解。请询问您是否还希望我包括其他任何内容。感谢一百万的任何帮助!