Web Audio API 声音交互在一段时间后停止工作
Web Audio API sound interaction stops working after a while
我正在为我的 javascript 项目使用 Web Audio API,我 运行 遇到了一个我似乎找不到答案的问题任何地方。
我添加了事件侦听器来响应按键事件 - 每次用户按下键盘上的某个键时,都会播放声音。这工作了一会儿,但在按下按键大约 6 秒后,会发生一些事情使声音停止 - 按键可能会在半秒内不会发出声音,然后它们将再次开始工作。任何人都知道为什么会发生这种情况,我该如何解决?
这是我的事件侦听器代码:
import Audio from './scripts/audio'
document.addEventListener('keydown', (e) => {
const audio = new Audio();
let key = e.key;
audio.createNotes(key);
})
这是我的音频代码:
class Audio {
constructor() {
// instantiate web audio api object
this.audioContext = new AudioContext();
// create gain node, gain corresponds with volume
this.gainNode = this.audioContext.createGain();
this.gainNode.gain.setValueAtTime(0.08, 0);
// allows volume to decrease with time
this.gainNode.gain.exponentialRampToValueAtTime(0.001, this.audioContext.currentTime + 1.5);
}
createNotes(key) {
// C4 to C5 scale, attach frequencies to corresponding keyboard value
const notes = {
's': 261.63,
'd': 293.66,
'f': 329.63,
'g': 349.23,
'h': 392.00,
'j': 440.00,
'k': 493.88,
'l': 523.25,
'e': 587.33,
'r': 659.25,
't': 698.46,
'y': 783.99,
'u': 880.00,
'i': 987.77,
'o': 1046.50,
'p': 1174.66
}
// if e.key corresponds with notes key, we want to play sound
if (notes[key]) {
// oscillator corresponds with frequency,
// create oscillator node to attach frequency from notes object
let oscillator = this.audioContext.createOscillator();
oscillator.frequency.setValueAtTime(notes[key], this.audioContext.currentTime);
// lower gain for higher frequency notes
if (notes[key] > 699) {
this.gainNode.gain.setValueAtTime(0.03, this.audioContext.currentTime);
}
// connect oscillator node to volume node
oscillator.connect(this.gainNode);
// connect gain node to destination (speakers)
this.gainNode.connect(this.audioContext.destination);
oscillator.start(0);
// tone will play for 1.5 seconds
oscillator.stop(this.audioContext.currentTime + 1.5)
}
}
}
export default Audio;
问题是您创建了太多的 AudioContext 实例。这不是 API 的预期用途。你为什么要创建这么多实例?你应该重新使用它们。
通常您只需要一个 AudioContext。在 mozzila 开发者页面上明确指出某些 Chrome 版本仅支持 6.
https://developer.mozilla.org/en-US/docs/Web/API/AudioContext/AudioContext#google_chrome
这里有一个question/answer进一步说明了这个问题。
要解决您的问题,基本上是创建一个 AudioContext 并使其可全局访问,如下所示:
let globalAudioContext = new AudioContext();
class Audio
{
constructor()
{
// instantiate web audio api object
// create gain node, gain corresponds with volume
this.gainNode = globalAudioContext.createGain();
this.gainNode.gain.setValueAtTime(0.08, 0);
// allows volume to decrease with time
this.gainNode.gain.exponentialRampToValueAtTime(0.001, globalAudioContext.currentTime + 1.5);
}
createNotes(key)
{
// C4 to C5 scale, attach frequencies to corresponding keyboard value
const notes = {
's': 261.63,
'd': 293.66,
'f': 329.63,
'g': 349.23,
'h': 392.00,
'j': 440.00,
'k': 493.88,
'l': 523.25,
'e': 587.33,
'r': 659.25,
't': 698.46,
'y': 783.99,
'u': 880.00,
'i': 987.77,
'o': 1046.50,
'p': 1174.66
}
// if e.key corresponds with notes key, we want to play sound
if (notes[key]) {
// oscillator corresponds with frequency,
// create oscillator node to attach frequency from notes object
let oscillator = globalAudioContext.createOscillator();
oscillator.frequency.setValueAtTime(notes[key], globalAudioContext.currentTime);
// lower gain for higher frequency notes
if (notes[key] > 699) {
this.gainNode.gain.setValueAtTime(0.03, globalAudioContext.currentTime);
}
// connect oscillator node to volume node
oscillator.connect(this.gainNode);
// connect gain node to destination (speakers)
this.gainNode.connect(globalAudioContext.destination);
oscillator.start(0);
// tone will play for 1.5 seconds
oscillator.stop(globalAudioContext.currentTime + 1.5);
}
}
}
document.addEventListener('keydown', (e) =>
{
const audio = new Audio();
let key = e.key;
console.log(e.keyCode);
audio.createNotes(key);
})
如果你想制作键盘钢琴,你应该将每个键绑定到一个预初始化的图形节点(增益节点)并重新使用它们。
它再次开始工作的原因是垃圾收集器需要时间才能启动。
我正在为我的 javascript 项目使用 Web Audio API,我 运行 遇到了一个我似乎找不到答案的问题任何地方。
我添加了事件侦听器来响应按键事件 - 每次用户按下键盘上的某个键时,都会播放声音。这工作了一会儿,但在按下按键大约 6 秒后,会发生一些事情使声音停止 - 按键可能会在半秒内不会发出声音,然后它们将再次开始工作。任何人都知道为什么会发生这种情况,我该如何解决?
这是我的事件侦听器代码:
import Audio from './scripts/audio'
document.addEventListener('keydown', (e) => {
const audio = new Audio();
let key = e.key;
audio.createNotes(key);
})
这是我的音频代码:
class Audio {
constructor() {
// instantiate web audio api object
this.audioContext = new AudioContext();
// create gain node, gain corresponds with volume
this.gainNode = this.audioContext.createGain();
this.gainNode.gain.setValueAtTime(0.08, 0);
// allows volume to decrease with time
this.gainNode.gain.exponentialRampToValueAtTime(0.001, this.audioContext.currentTime + 1.5);
}
createNotes(key) {
// C4 to C5 scale, attach frequencies to corresponding keyboard value
const notes = {
's': 261.63,
'd': 293.66,
'f': 329.63,
'g': 349.23,
'h': 392.00,
'j': 440.00,
'k': 493.88,
'l': 523.25,
'e': 587.33,
'r': 659.25,
't': 698.46,
'y': 783.99,
'u': 880.00,
'i': 987.77,
'o': 1046.50,
'p': 1174.66
}
// if e.key corresponds with notes key, we want to play sound
if (notes[key]) {
// oscillator corresponds with frequency,
// create oscillator node to attach frequency from notes object
let oscillator = this.audioContext.createOscillator();
oscillator.frequency.setValueAtTime(notes[key], this.audioContext.currentTime);
// lower gain for higher frequency notes
if (notes[key] > 699) {
this.gainNode.gain.setValueAtTime(0.03, this.audioContext.currentTime);
}
// connect oscillator node to volume node
oscillator.connect(this.gainNode);
// connect gain node to destination (speakers)
this.gainNode.connect(this.audioContext.destination);
oscillator.start(0);
// tone will play for 1.5 seconds
oscillator.stop(this.audioContext.currentTime + 1.5)
}
}
}
export default Audio;
问题是您创建了太多的 AudioContext 实例。这不是 API 的预期用途。你为什么要创建这么多实例?你应该重新使用它们。
通常您只需要一个 AudioContext。在 mozzila 开发者页面上明确指出某些 Chrome 版本仅支持 6.
https://developer.mozilla.org/en-US/docs/Web/API/AudioContext/AudioContext#google_chrome
这里有一个question/answer进一步说明了这个问题。
要解决您的问题,基本上是创建一个 AudioContext 并使其可全局访问,如下所示:
let globalAudioContext = new AudioContext();
class Audio
{
constructor()
{
// instantiate web audio api object
// create gain node, gain corresponds with volume
this.gainNode = globalAudioContext.createGain();
this.gainNode.gain.setValueAtTime(0.08, 0);
// allows volume to decrease with time
this.gainNode.gain.exponentialRampToValueAtTime(0.001, globalAudioContext.currentTime + 1.5);
}
createNotes(key)
{
// C4 to C5 scale, attach frequencies to corresponding keyboard value
const notes = {
's': 261.63,
'd': 293.66,
'f': 329.63,
'g': 349.23,
'h': 392.00,
'j': 440.00,
'k': 493.88,
'l': 523.25,
'e': 587.33,
'r': 659.25,
't': 698.46,
'y': 783.99,
'u': 880.00,
'i': 987.77,
'o': 1046.50,
'p': 1174.66
}
// if e.key corresponds with notes key, we want to play sound
if (notes[key]) {
// oscillator corresponds with frequency,
// create oscillator node to attach frequency from notes object
let oscillator = globalAudioContext.createOscillator();
oscillator.frequency.setValueAtTime(notes[key], globalAudioContext.currentTime);
// lower gain for higher frequency notes
if (notes[key] > 699) {
this.gainNode.gain.setValueAtTime(0.03, globalAudioContext.currentTime);
}
// connect oscillator node to volume node
oscillator.connect(this.gainNode);
// connect gain node to destination (speakers)
this.gainNode.connect(globalAudioContext.destination);
oscillator.start(0);
// tone will play for 1.5 seconds
oscillator.stop(globalAudioContext.currentTime + 1.5);
}
}
}
document.addEventListener('keydown', (e) =>
{
const audio = new Audio();
let key = e.key;
console.log(e.keyCode);
audio.createNotes(key);
})
如果你想制作键盘钢琴,你应该将每个键绑定到一个预初始化的图形节点(增益节点)并重新使用它们。
它再次开始工作的原因是垃圾收集器需要时间才能启动。