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

使用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中生效。另外代码里还有几个细节问题需要修正:

  1. datanum变量逻辑错误
    定义int datanum = 0;后,if(vals.length >= datanum)永远为真,完全起不到校验作用。应该改成if(vals.length >= 2),确保能拿到两个传感器的数值。

  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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 10:53:16