You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

键盘触发JavaScript合成器仅能播放一次问题求助

解决JavaScript键盘合成器只能播放一次的问题

我来帮你搞定这个合成器的问题,主要是两个核心原因导致了当前的故障,咱们一步步修复:

问题分析

  1. OscillatorNode的生命周期限制:Web Audio API里的振荡器节点一旦调用stop()后就彻底终止了,没法再次调用start()。你现在全局只创建了一个oscillator实例,第一次按A键启动后,释放时执行了stop(),后续再按就没法复用这个实例了。
  2. 振荡器类型拼写错误:你写的oscillator.type = 'sign'是错的,正确的正弦波类型应该是'sine',这个小错误也会导致发声异常(甚至无声)。

修复后的完整代码

// 存储当前活跃的振荡器,初始为空
let activeOscillator = null;
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();

document.onkeydown = checkKey;
document.onkeyup = stopSound;

function checkKey(e) {
  e = e || window.event;
  // 避免重复创建振荡器(如果当前已有活跃的,直接返回)
  if (activeOscillator) return;

  // 创建新的振荡器实例
  const oscillator = audioCtx.createOscillator();
  oscillator.type = 'sine'; // 修正为正确的正弦波类型

  // 按键-频率映射,按标准MIDI音高设置
  const keyFreqMap = {
    '65': 261.63, // A键 -> C4
    '87': 277.18, // W键 -> C#4
    '83': 293.66, // S键 -> D4
    '69': 311.13  // E键 -> D#4
  };

  const freq = keyFreqMap[e.keyCode];
  if (freq) {
    oscillator.frequency.value = freq;
    oscillator.connect(audioCtx.destination);
    oscillator.start();
    // 将当前振荡器存入全局变量,方便释放时操作
    activeOscillator = oscillator;
  }
}

function stopSound() {
  if (activeOscillator) {
    activeOscillator.stop();
    activeOscillator.disconnect();
    // 清空变量,允许下次创建新的振荡器
    activeOscillator = null;
  }
}

关键修改点说明

  • 每次按键创建新振荡器:不再复用单一实例,而是每次按下有效按键时生成新的OscillatorNode,符合Web Audio API的生命周期规则。
  • 映射表简化按键逻辑:用对象keyFreqMap替代冗长的if-else,后续扩展按键会更方便。
  • 跟踪活跃振荡器:用activeOscillator变量记录当前正在发声的振荡器,释放按键时精准停止对应的实例。
  • 修正振荡器类型:把'sign'改成'sine',确保能正常生成正弦波声音。

额外优化建议

  • 可以添加GainNode来控制音量,避免默认音量过大:
    const gainNode = audioCtx.createGain();
    gainNode.gain.value = 0.3; // 设置30%音量
    oscillator.connect(gainNode);
    gainNode.connect(audioCtx.destination);
    
  • 支持多按键同时发声:如果需要同时按多个键发出和弦,可以用数组存储多个活跃振荡器,释放按键时根据keyCode对应停止。

内容的提问来源于stack exchange,提问作者Linus Höggren

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:05:59