使用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
相关产品推荐
相关产品推荐

