如何创建和正确调度 AudioBufferSource 节点
How to create and properly schedule AudioBufferSource nodes?
我正在尝试使用Javascript开发节拍器。我按照本文中的说明创建了一个调度程序,该调度程序每隔一段时间就会被调用并调度"ticks",这些"tick"存在于一个名为 ticksInQueue
的数组中。我希望"滴答声"是节拍器的实际声音,而不是振荡器产生的频率。
振荡器
function scheduler() {
while (nextTickTime < audioContext.currentTime + lookahead) { // while there are notes that will need to play before the next interval
ticksInQueue.push({tick: currentTick, time: nextTickTime}); // push the note on the queue, even if we're not playing.
//create an oscillator
var osc = audioContext.createOscillator();
osc.connect(audioContext.destination);
osc.frequency.value = 440.0;
osc.start(nextTickTime);
osc.stop(nextTickTime + 0.1);
nextTickTime += 60.0 / tempo; // Add beat length to last beat time
currentTick = currentTick + 1; // Advance the beat number, wrap to zero
if (currentTick === 5) {
currentTick = 0;
}
}
}
按照有关如何创建AudioBufferSource
节点的视频教程,我编写了这段在加载窗口时执行的代码。
audioContext = new AudioContext();
request = new XMLHttpRequest();
request.open("GET", "tick.mp3", true);
request.responseType = "arraybuffer";
function onDecoded(buffer) {
bufferSource = audioContext.createBufferSource();
bufferSource.buffer = buffer;
bufferSource.connect(audioContext.destination);
}
request.onload = function () {
// audio data is in request.response
audioContext.decodeAudioData(request.response, onDecoded);
};
request.send();
但是,如果我用缓冲区替换振荡器,如下所示,控制台会告诉我" Uncaught InvalidStateError: Failed to execute 'start' on 'AudioBufferSourceNode': cannot call start more than once.
"
音频缓冲源
function scheduler() {
while (nextTickTime < audioContext.currentTime + lookahead) {
ticksInQueue.push({tick: currentTick, time: nextTickTime});
//Changed code
bufferSource.start(nextTickTime);
bufferSource.stop(nextTickTime + 0.1);
nextTickTime += 60.0 / tempo; // Add beat length to last beat time
currentTick = currentTick + 1; // Advance the beat number, wrap to zero
if (currentTick === 5) {
currentTick = 0;
}
}
}
是的,你需要为每个"tick"创建一个 BufferSource。 (它们共享缓冲区,但缓冲区源是一次性节点。
所以,像这样:
var the_buffer=null;
function onDecoded(buffer) {
the_buffer=buffer;
}
function playTick() {
if (the_buffer) { // make sure it's been decoded
var bufferSource = audioContext.createBufferSource();
bufferSource.buffer = the_buffer;
bufferSource.connect(audioContext.destination);
bufferSource.start(0);
// bufferSource will get auto-garbage-collected when it's done playing.
}
}
现在,将调度器中的振荡器代码替换为对 playTick() 的调用;
相关文章:
- 调度没有'无法立即更新组件
- 在dhtmlx调度程序中多次触发OnEventSave
- Redux-正确调度操作
- 如果在对象上触发了dispatchEvent,我如何才能找到如何侦听它以及在哪里调度事件
- 如何在解析服务器上用kue调度作业
- casperjs-css选择器存在,但当单击它时会引发“”;CasperError:无法在不存在的选择器“”上调度mou
- 查找与锁定和更新调度相关的一个或两个节点模块
- reactJs redux:如何对用户事件调度操作并将操作与化简器和存储链接
- 不需要的异步事件调度
- React/flux - 子组件用户事件 - 是否应通过调度程序路由所有内容
- 如何克隆或重新调度 DOM 事件
- 如何从 on 调用调度更改反应路由器路由
- Web Audio API-调度问题
- dhtmlx多个调度器不工作错误”;调度程序未定义”;
- Web音频-AudioParam调度功能不起作用
- 更新时React Redux调度导致递归错误
- React,Flux,React路由器调度错误-可能的批更新解决方案
- 根据React中的调度循环取消反弹调用
- 如何从React Redux中的子组件进行调度
- Node.js随机调度