使用Sound库时Processing的draw函数执行异常求助
问题描述
我的Processing程序能从两个Arduino传感器接收数据并在控制台打印数值,但draw函数里的if语句(用来切换音频音量、打印指定内容)完全没执行,画布上的文本也不显示。但把Sound相关代码删掉后,程序就正常了——数值达标时控制台会打印指定内容,画布文本也能正常显示。我试过把代码合并到一个函数里,没用。下面是我的代码,求帮忙。
原Processing代码
import processing.sound.*; import processing.serial.*; Serial myPort; String val; int datanum = 0; int val1; int val2; AudioSample glitched; AudioSample music; AudioSample enabled; void setup() { size(400, 400); frameRate(30); String portName = Serial.list()[0]; myPort = new Serial(this, portName, 9600); myPort.bufferUntil('\n'); glitched = new SoundFile(this, "glitchedNew.mp3"); glitched.loop(); glitched.amp(1); music = new SoundFile(this, "music.mp3"); music.loop(); music.amp(0); enabled = new SoundFile(this, "enabled.mp3"); } void draw() { rect(120, 80, 220, 220); if (val1 > 10 && val2 > 10) { glitched.amp(0); music.amp(1); println("Sound 1 now playing"); } else { glitched.amp(1); music.amp(0); } text(val1, 20, 20); text(val2, 20, 60); } void serialEvent(Serial myPort) { val = myPort.readStringUntil('\n'); if (val != null) { val = trim(val); int[] vals = int(splitTokens(val, ",")); if(vals.length >= datanum) { val1 = vals[0]; val2 = vals[1]; print(val1); print(","); print(val2); println(); } } }
原Arduino代码
const int sensorPin1 = A0; const int sensorPin2 = A1; int val; void setup() { pinMode(sensorPin1, INPUT); pinMode(sensorPin2, INPUT); Serial.begin(9600); } void loop() { int sensorVal1 = analogRead(sensorPin1); int sensorVal2 = analogRead(sensorPin2); Serial.print(sensorVal1); Serial.print(","); Serial.print(sensorVal2); Serial.println(); }
问题分析与解决办法
核心原因
Processing的Sound库加载音频时可能阻塞主线程,导致draw循环无法正常刷新,同时串口更新的变量也无法及时在draw中生效。另外代码里还有几个细节问题需要修正:
datanum变量逻辑错误
定义int datanum = 0;后,if(vals.length >= datanum)永远为真,完全起不到校验作用。应该改成if(vals.length >= 2),确保能拿到两个传感器的数值。Sound库资源抢占
音频加载和播放会占用主线程资源,导致draw循环卡顿。解决思路:- 先初始化串口,再加载音频,保证串口优先就绪
- 音频加载后加短暂缓冲时间,避免线程冲突
- 新增状态变量,只在音频状态变化时调用
amp(),减少不必要的性能消耗
修改后的Processing代码
import processing.sound.*; import processing.serial.*; Serial myPort; String val; int val1 = 0; int val2 = 0; // 新增状态变量,避免频繁调用音量调整 boolean musicActive = false; AudioSample glitched; AudioSample music; AudioSample enabled; void setup() { size(400, 400); frameRate(30); textSize(20); // 设置文本大小,确保可见 // 优先初始化串口 String portName = Serial.list()[0]; myPort = new Serial(this, portName, 9600); myPort.bufferUntil('\n'); // 最后加载音频 glitched = new SoundFile(this, "glitchedNew.mp3"); glitched.loop(); glitched.amp(1); music = new SoundFile(this, "music.mp3"); music.loop(); music.amp(0); enabled = new SoundFile(this, "enabled.mp3"); delay(100); // 给音频加载留缓冲时间 } void draw() { background(255); // 每次刷新背景,避免图形重叠 rect(120, 80, 220, 220); // 仅在状态变化时调整音量 boolean shouldActivate = (val1 > 10 && val2 > 10); if (shouldActivate != musicActive) { musicActive = shouldActivate; if (musicActive) { glitched.amp(0); music.amp(1); println("Sound 1 now playing"); enabled.play(); // 触发切换音效 } else { glitched.amp(1); music.amp(0); } } text("传感器1: " + val1, 20, 20); text("传感器2: " + val2, 20, 60); } void serialEvent(Serial myPort) { val = myPort.readStringUntil('\n'); if (val != null) { val = trim(val); int[] vals = int(splitTokens(val, ",")); // 校验是否拿到两个有效数值 if(vals.length >= 2) { val1 = vals[0]; val2 = vals[1]; print(val1); print(","); print(val2); println(); } } }
额外建议
- 确保音频文件放在Processing项目的
data文件夹中,路径正确 - 如果仍有卡顿,可降低音频文件的比特率,或尝试异步加载音频
- Arduino代码可添加
delay(50)在loop中,避免串口数据发送过快导致Processing处理不过来
内容的提问来源于stack exchange,提问作者Jasper
相关产品推荐
相关产品推荐

