gpt4 book ai didi

javascript - 使用 Web Audio API 安排示例播放

转载 作者:行者123 更新时间:2023-11-30 06:21:07 31 4
gpt4 key购买 nike

我正在尝试构建一个使用样本而不是振荡器的鼓机,只是为了学习。但是,我无法安排声音在前两个节拍中按节奏播放。发生的情况是前两个节拍不同步,而其余节拍似乎按预期节奏播放。播放振荡器而不是样本时不会出现此问题。

我阅读了两个时钟的故事和我能找到的所有相关教程,但它们都使用似乎没有出现此问题的振荡器。以下只是我尝试实现代码的方法之一 - 我尝试了 OOP 和各种函数式编程版本,但所有这些版本都出现了问题。

在这个例子中,我创建了名为 playSound() 和 playKick() 的函数。 playSound() 触发振荡器音符,而 playKick() 函数触发底鼓样本。尝试在 scheduler() 函数中切换两者,听听问题是如何发生的。

let audioContext = new (window.AudioContext || window.webkitAudioContext)();
var nextNotetime = audioContext.currentTime;
var startBtn = document.getElementById("startBtn");
var stopBtn = document.getElementById("stopBtn");
var timerID;
let kickBuffer;
loadKick('sounds/kick.wav');

function loadKick(url) {
let xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'arraybuffer';
xhr.onload = function() {
audioContext.decodeAudioData(xhr.response, decoded => {
kickBuffer = decoded;
});
}
xhr.send();
}

function playKick(time) {
let source = audioContext.createBufferSource();
source.connect(audioContext.destination);
source.buffer = kickBuffer;
source.start(time);
}

function playSound(time) {

var osc = audioContext.createOscillator();
osc.connect(audioContext.destination);
osc.frequency.value = 200;
osc.start(time);
osc.stop(time + 0.1);

};

function scheduler() {
while(nextNotetime < audioContext.currentTime + 0.1) {
// switch between playSound and playKick to hear the problem
nextNotetime += 0.5;
playSound(nextNotetime);
// playKick(nextNotetime);
}
timerID = window.setTimeout(scheduler, 0);
}

startBtn.addEventListener('click', function() {
scheduler();
}, false);

stopBtn.addEventListener('click', function() {
clearTimeout(timerID);
}, false);

if(audioContext.state === 'suspended'){
audioContext.resume();
};

如您所见,缓冲区会在文件加载后立即预加载,因此这不是根本原因。非常感谢有关如何解决此问题的任何建议。

最佳答案

工作修复。

"use strict";



var audioContext = new AudioContext(),
futureTickTime = audioContext.currentTime,
counter = 1,
tempo = 120,
secondsPerBeat = 60 / tempo,
counterTimeValue = (secondsPerBeat / 4),
timerID = undefined,
isPlaying = false;


//_____________________________________________BEGIN load sound samples
let kickBuffer;
loadKick('sounds/kick.mp3');

function loadKick(url) {
let xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'arraybuffer';
xhr.onload = function() {
audioContext.decodeAudioData(xhr.response, function(decoded) {
kickBuffer = decoded;
});
}
xhr.send();
}

function playKick(time) {
let source = audioContext.createBufferSource();
source.connect(audioContext.destination);
source.buffer = kickBuffer;
source.start(audioContext.currentTime + time);
}


//_____________________________________________END load sound samples


function scheduleSound(time) {
playKick(time)

}


function playTick() {
console.log(counter);
secondsPerBeat = 60 / tempo;
counterTimeValue = (secondsPerBeat / 1);
counter += 1;
futureTickTime += counterTimeValue;
}


function scheduler() {
if (futureTickTime < audioContext.currentTime + 0.1) {
scheduleSound(futureTickTime - audioContext.currentTime);

playTick();
}

timerID = window.setTimeout(scheduler, 0);
}


function play() {
isPlaying = !isPlaying;

if (isPlaying) {
counter = 1;
futureTickTime = audioContext.currentTime;
scheduler();
} else {
window.clearTimeout(timerID);
}
}



var playStop = document.getElementsByClassName("play-stop-button")[0];

playStop.addEventListener("click",function(){
play();
})

关于javascript - 使用 Web Audio API 安排示例播放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53022480/

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