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

使用p5.js PolySynth遇oldestNote未定义及音符同时发声问题

问题排查与修复

错误原因分析

1. 所有音符同时发声

  • draw()函数每秒执行约60次,每次都会调用playSynth(),而playSynth内的for循环给所有音符设置了time=0(立即播放),导致每次draw都会触发所有音符同时发声,还会重复触发。
  • 同步for循环执行速度极快,即使没有draw的重复调用,time=0也会让所有音符同时启动。

2. ReferenceError: oldestNote is not defined

  • p5.PolySynth默认最大复音数为8,你一次性尝试播放12个音符,超过了这个上限。当库尝试自动移除旧音符腾出位置时,内部代码引用了未定义的oldestNote变量(属于旧版本p5.sound的小问题)。
  • 代码中note = notes[i]未用let/const声明,导致note成为全局变量,可能与库内部变量产生冲突。

修复方案

修改后的代码

let polySynth;
let notes = ['C3', 'G3', 'D4', 'A4', 'E5', 'Bb5', 'Gb5', 'Db4', 'Ab4', 'Eb3', 'Bb3', 'F2']

function setup() {
  createCanvas(windowWidth, windowHeight);
  // 初始化复音数为12,容纳所有音符
  polySynth = new p5.PolySynth(12);
  // 仅调用一次音频初始化
  userStartAudio();
}

// 用鼠标点击触发音符序列播放,避免重复执行
function mousePressed() {
  playSynth();
}

function playSynth() {
  for (let i = 0; i < notes.length; i++){
    // 声明局部变量note,避免全局冲突
    let note = notes[i];
    // velocity范围为0-1,0.5是适中的音量
    let velocity = 0.5;
    // 每个音符间隔0.5秒播放,实现依次发声
    let time = i * 0.5;
    let dur = 1;
    polySynth.play(note, velocity, time, dur);
  }
}

关键修改点

  • 移除draw()中对playSynth()的调用,改用mousePressed()触发,确保序列只播放一次。
  • 初始化PolySynth时指定复音数为12,避免因超过上限触发内部错误。
  • 给每个音符设置递增的time参数,实现依次播放的效果。
  • 修复note变量的声明,改为局部变量。
  • 调整velocity为0-1范围内的合理值(原10超出范围,会被强制转为1)。

内容的提问来源于stack exchange,提问作者muaoilk

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 14:30:22