网络音频 API 互相播放音符
Web Audio API Play Notes after each other
我对 Javascript 比较陌生,我尝试使用网络音频 API 来演奏音符。这些音符确实在演奏,但不是我想要的那样。我正在尝试让音符在 之后 彼此演奏。我代码中的每个节点都有一个频率数组。然后我使用 for 循环遍历此数组并使用函数 playNote
播放频率。我尝试使用 timeOut 来延迟 for 循环中的 playNote 调用,但这似乎不起作用。
class Node {
constructor(x, y, radius, color, frequency){
this.x = x
this.y = y
this.radius = radius
this.color = color
this.frequency = frequency
}
}
const player1 = new Node(100, 100, 30, 'blue',[1047])
const player2 = new Node(200, 100, 30, 'red',[1047, 1047])
var listOfNodes = []
listOfNodes.push(player1)
listOfNodes.push(player2)
function playNote(freq) {
oscillator = audioCtx.createOscillator()
gain = audioCtx.createGain()
oscillator.type = 'sine'
oscillator.connect(gain)
oscillator.frequency.value = freq
gain.connect(audioCtx.destination)
oscillator.start(0)
gain.gain.exponentialRampToValueAtTime(0.00001, audioCtx.currentTime + 1)
}
listOfNodes.forEach(node => {
var i;
for (i = 0; i < node.frequency.length; i++) {
setTimeout(function() {
playNote(node.frequency[i])
}, 2000 * i);
}
}
);
有很多方法可以做到。例如,您可以为每个 playNote
设置不同的开始时间。像这样:
function playNote(freq, time) {
oscillator = audioCtx.createOscillator()
gain = audioCtx.createGain()
oscillator.type = 'sine'
oscillator.connect(gain)
oscillator.frequency.value = freq
gain.connect(audioCtx.destination)
oscillator.start(audioCtx.currentTime + time)
gain.gain.exponentialRampToValueAtTime(0.00001, audioCtx.currentTime + 1 + time)
}
for (i = 0; i < node.frequency.length; i++) {
playNote(node.frequency[i], i)
}
或者使用递归函数,当一个音符结束时执行。但是为此你需要用 oscillator.stop(audioCtx.currentTime + sometime)
指定实际结束时间,而不是那个丑陋的 hack :) gain.gain.exponentialRampToValueAtTime(0.00001, audioCtx.currentTime + 1 + time)
function playNote(freq) {
oscillator = audioCtx.createOscillator()
gain = audioCtx.createGain()
oscillator.type = 'sine'
oscillator.connect(gain)
oscillator.frequency.value = freq
gain.connect(audioCtx.destination)
oscillator.start(audioCtx.currentTime)
oscillator.stop(audioCtx.currentTime + 1)
oscillator.addEventListener('ended', () => {playNote(nextFrequency)}, { once: true });
}
但我认为最好的方法是使用现代 javascript 功能:Promises
with async await
const audioCtx = new AudioContext();
class Node {
constructor(x, y, radius, color, frequency){
this.x = x
this.y = y
this.radius = radius
this.color = color
this.frequency = frequency
}
}
const player1 = new Node(100, 100, 30, 'blue',[1047])
const player2 = new Node(200, 100, 30, 'red',[1047, 1047])
var listOfNodes = []
listOfNodes.push(player1)
listOfNodes.push(player2)
function playNote(freq) {
return new Promise((resolve) => {
oscillator = audioCtx.createOscillator()
gain = audioCtx.createGain()
oscillator.type = 'sine'
oscillator.connect(gain)
oscillator.frequency.value = freq
gain.connect(audioCtx.destination)
oscillator.start(audioCtx.currentTime)
oscillator.stop(audioCtx.currentTime + 1)
oscillator.addEventListener('ended', resolve, { once: true });
})
}
async function play() {
for (const node of listOfNodes) {
for (const frequency of node.frequency) {
console.log(`note with frequenty ${frequency} started`)
await playNote(frequency);
console.log(`note with frequency ${frequency} ended`)
}
}
}
play();
我对 Javascript 比较陌生,我尝试使用网络音频 API 来演奏音符。这些音符确实在演奏,但不是我想要的那样。我正在尝试让音符在 之后 彼此演奏。我代码中的每个节点都有一个频率数组。然后我使用 for 循环遍历此数组并使用函数 playNote
播放频率。我尝试使用 timeOut 来延迟 for 循环中的 playNote 调用,但这似乎不起作用。
class Node {
constructor(x, y, radius, color, frequency){
this.x = x
this.y = y
this.radius = radius
this.color = color
this.frequency = frequency
}
}
const player1 = new Node(100, 100, 30, 'blue',[1047])
const player2 = new Node(200, 100, 30, 'red',[1047, 1047])
var listOfNodes = []
listOfNodes.push(player1)
listOfNodes.push(player2)
function playNote(freq) {
oscillator = audioCtx.createOscillator()
gain = audioCtx.createGain()
oscillator.type = 'sine'
oscillator.connect(gain)
oscillator.frequency.value = freq
gain.connect(audioCtx.destination)
oscillator.start(0)
gain.gain.exponentialRampToValueAtTime(0.00001, audioCtx.currentTime + 1)
}
listOfNodes.forEach(node => {
var i;
for (i = 0; i < node.frequency.length; i++) {
setTimeout(function() {
playNote(node.frequency[i])
}, 2000 * i);
}
}
);
有很多方法可以做到。例如,您可以为每个 playNote
设置不同的开始时间。像这样:
function playNote(freq, time) {
oscillator = audioCtx.createOscillator()
gain = audioCtx.createGain()
oscillator.type = 'sine'
oscillator.connect(gain)
oscillator.frequency.value = freq
gain.connect(audioCtx.destination)
oscillator.start(audioCtx.currentTime + time)
gain.gain.exponentialRampToValueAtTime(0.00001, audioCtx.currentTime + 1 + time)
}
for (i = 0; i < node.frequency.length; i++) {
playNote(node.frequency[i], i)
}
或者使用递归函数,当一个音符结束时执行。但是为此你需要用 oscillator.stop(audioCtx.currentTime + sometime)
指定实际结束时间,而不是那个丑陋的 hack :) gain.gain.exponentialRampToValueAtTime(0.00001, audioCtx.currentTime + 1 + time)
function playNote(freq) {
oscillator = audioCtx.createOscillator()
gain = audioCtx.createGain()
oscillator.type = 'sine'
oscillator.connect(gain)
oscillator.frequency.value = freq
gain.connect(audioCtx.destination)
oscillator.start(audioCtx.currentTime)
oscillator.stop(audioCtx.currentTime + 1)
oscillator.addEventListener('ended', () => {playNote(nextFrequency)}, { once: true });
}
但我认为最好的方法是使用现代 javascript 功能:Promises
with async await
const audioCtx = new AudioContext();
class Node {
constructor(x, y, radius, color, frequency){
this.x = x
this.y = y
this.radius = radius
this.color = color
this.frequency = frequency
}
}
const player1 = new Node(100, 100, 30, 'blue',[1047])
const player2 = new Node(200, 100, 30, 'red',[1047, 1047])
var listOfNodes = []
listOfNodes.push(player1)
listOfNodes.push(player2)
function playNote(freq) {
return new Promise((resolve) => {
oscillator = audioCtx.createOscillator()
gain = audioCtx.createGain()
oscillator.type = 'sine'
oscillator.connect(gain)
oscillator.frequency.value = freq
gain.connect(audioCtx.destination)
oscillator.start(audioCtx.currentTime)
oscillator.stop(audioCtx.currentTime + 1)
oscillator.addEventListener('ended', resolve, { once: true });
})
}
async function play() {
for (const node of listOfNodes) {
for (const frequency of node.frequency) {
console.log(`note with frequenty ${frequency} started`)
await playNote(frequency);
console.log(`note with frequency ${frequency} ended`)
}
}
}
play();