Title: Seeking Help with Complex Processing Script for Visual Representation Generator
Hello Processing Community,
I’m working on a visual representation generator that draws inspiration from the music of Karlheinz Stockhausen, the concept of sound painting, and German expressionist abstract cinema from WWII. The core idea is to create a dynamic system that drives granular synthesis generation in the style of Iannis Xenakis using SuperCollider, and to generate visual scores in real-time to guide free improvisation.
However, I’m facing some challenges with a particularly long Processing script that I’ve been developing. The goal of the script is to manage 15 different visualizations and cycle between them with a time offset ranging from 21 to 46.7 seconds.
Here’s what I need help with:
Allocating 15 Visualizations: I need to efficiently set up and manage 15 separate visualizations within Processing.
Shifting Between Visualizations: Implementing a mechanism to switch between these visualizations with the specified time offset.
Script Optimization: The script is quite lengthy and complex. Any advice on optimizing or troubleshooting it would be greatly appreciated.
If anyone has experience with similar projects or can offer insights on managing multiple visualizations and implementing timed transitions, I would be grateful for your support.
Here would be a little trick using a little trick to generating the visualizations with fewer lines of code provided you add constructors too each of your classes:
Here would be a little example of that. (There also is a way to do it without however there is some “dark magic” involved)
abstract class SuperCl {
abstract void printStuff();
}
class Ext1 extends SuperCl {
public Ext1() {
}
void printStuff() {
println("Extension 1");
}
}
class Ext2 extends SuperCl {
public Ext2() {
}
void printStuff() {
println("Extension 2");
}
}
class Ext3 extends SuperCl {
public Ext3() {
}
void printStuff() {
println("Extension 3");
}
}
import java.util.*;
import java.lang.reflect.*;
void setup() {
//Number of extension
int extCount=3;
//List of the extensions
List<SuperCl> exts=new ArrayList<SuperCl>();
try {
Class<?> sketchClass=this.getClass();
String baselineClassName=sketchClass.getName()+"$Ext";
for (int i=1; i<=extCount; i++) exts.add(
(SuperCl)Class.forName(baselineClassName+i)
.getConstructor(sketchClass)
.newInstance(this));
}
catch(Exception e) {
throw new RuntimeException(e);
}
for(SuperCl ext:exts) ext.printStuff();
}
Since your code already uses an index of wich visualisation is active you can do the folowing. First add the “volatile” keyword to currentVisualizationIndex .
java.util also provides a Timer class that can be used to set this variable.
First benefit would be to combine the creation of the visualization with adding it to the arraykist like this
void setup() {
size(800, 600);
noLoop();
// Add more instances as needed
visualizations.add( new Visualization1());
visualizations.add( new Visualization2());
visualizations.add( new Visualization3());
visualizations.add( new Visualization4());
visualizations.add( new Visualization5());
visualizations.add( new Visualization6());
visualizations.add( new Visualization7());
visualizations.add( new Visualization8());
visualizations.add( new Visualization9());
visualizations.add( new Visualization10());
visualizations.add( new Visualization11());
visualizations.add( new Visualization12());
visualizations.add( new Visualization13());
visualizations.add( new Visualization14());
visualizations.add( new Visualization15());
// Call setup for each visualization
for (Visualization vis : visualizations) {
vis.setup();
}
loop(); // needed to enable the
}
On my computer creating the 15 visualizations took 11ms so is more than fast enough.
As to the Visualisation class I have several suggestions.
the class setup method is a problem. I suspect that you created separate sketches for each visualization then copied and pasted the code into its own class Most of the code is redundant because the method is only executed once from the main sketch setup method.
For instance the size method will be ignored by Processing after its first execution and the call toframeRate is overwritten every time in this loop
for (Visualization vis : visualizations) {
vis.setup();
}
Since each visualization has its own offset and timer values these should be attributes of the class rather than stored in separate arraylists e.g.
This will make adding new visualizations much easier because you don’t have to update 3 array lists and maintain the order between them. The draw method then becomes
void draw() {
background(0);
if (visualizations.size() == 0) return;
// Check the time for each visualization
for (int i = 0; i < visualizations.size(); i++) {
Visualization v = visualizations.get(i);
float elapsedTime = (millis() - v.timer) / 1000.0;
if (elapsedTime >= v.offsetTime) {
currentVisualizationIndex = i;
v.timer = millis(); // Reset timer
break; // Break loop to render only the current visualization
}
}
// Display the current visualization
if (currentVisualizationIndex != -1) {
visualizations.get(currentVisualizationIndex).draw();
}
}
and you can delete the arraylists for offsets and timers.
AMENDED CODE
You can download the archived sketch here
You can take a look at this code that handles timing:
import java.util.*;
volatile int state=-1;
//Intervals in millis
long timings[]={2000, 3000, 5000};
//timer class used
Timer timers[]=new Timer[timings.length];
//A creates the timer task that switches to state i
TimerTask createTask(final int i) {
return new TimerTask() {
@Override void run() {
//If you want additional code to be executed when the state gets switched to i do it here.
state=i;
}
};
}
void setup() {
//Creates the timers and sets them to be executed at the givens intervals.
for (int i=0; i<timings.length; i++) {
timers[i]=new Timer();
timers[i].scheduleAtFixedRate(createTask(i),
/*Time until first execution*/ timings[i],
/*Interval in wich execution is done*/ timings[i]);
}
}
void draw() {
println(state);
}
Also an option you might explore would be looking into the registerMethod method. Here would be a little example on one possible application:
public abstract class Task {
public abstract void draw();
}
public class TaskA extends Task{
public void draw() {
println("Hi");
}
}
public class TaskB extends Task{
public void draw() {
println("Hello");
}
}
Task ta=new TaskA();
Task tb=new TaskB();
void setup() {
//The draw method of the Object ta is executed after the draw method of this sketch
this.registerMethod("draw",ta);
}
//Any method where you do not want two threads executing the method at the same time should be declared synchronized
synchronized void swap(Task t1,Task t2){
this.unregisterMethod("draw",t1);
this.registerMethod("draw",t2);
}
void draw(){
if(frameCount==300) swap(ta,tb);
}