Transition between sketches in Live Concert


#1

Hi everyone,
I just started using processing, and I plan to use it with my jazz band. (using midi from the keyboards and triggered-drums) Basically, I would like to have my computer running, and me only touching one key between song to go to the next sketch.
Is there a standard way to do that, in order to have a smooth transition ?
thank you
seb


#2

What you mean by smooth? Probably it’ll depend more on the animation itself, for example having the same background color or things like that.
For transitions between sketch, you could make functions that store the code for your different animations and calling it by a switch function.

switch(currentAnimation){
case 0:
animation0();
break;

case1:
Animation1(); 
break
//And  so on
}

Hope it helps


#3

Hi Bryan,
Thank you for your response ! By smooth I mean, for example, a fade to black during 5 second with my sketch still running, and then start the next sketch with a fade from black, during 5 seconds.

I didn’t really understand the animation concept, and I don’t know how to make a function that stores code for a whole sketch …

Seb


#4

Ok, did you have any example of your animations? To give you a more specific example


#5

So this is the sketch I have done so far (which display an image of a street, and when I play on my keyboard, it display the same image with one of the lights ON. on top of everything, I overlay movie of rain)
this sketch works well, and I would like to transition to another sketch, with, for example a line in the middle of the screen, that move when I play my keyboard.

import processing.video.*;
import themidibus.*; //Import the library

MidiBus BusA;
MidiBus BusB;
String BusA_nom = "USB MIDI CABLE";
String BusB_nom = "UM-ONE";
int SoundA=0;
//int x=0;
int place_restanteA=100;
int ajoutA=0;

int SoundB=0;
//int x=0;
int place_restanteB=100;
int ajoutB=0;

float t_A=0;
float t_B=0;


Movie myMovie;

PImage fond;
PImage scooter;
PImage plot;
float t=0;
int largeur = 800;
int hauteur = 600;
  
void setup() {
  size(800 ,600);
  
  MidiBus.list();
  BusA = new MidiBus(this, BusA_nom, BusA_nom,BusA_nom);
  BusA = new MidiBus(this, BusB_nom, BusB_nom,BusB_nom);
  //fullScreen();
  //surface.setResizable(true);
  myMovie = new Movie(this, "video/boucle_pluie720p.mov");
  myMovie.loop();
  
  fond = loadImage("images/fond.png");
  scooter = loadImage("images/scooterd.png");
  plot = loadImage("images/plotd.png");
  
  println("largeur fond :"+fond.width+" hauteir fond"+fond.height);
  println("largeur scooter :"+scooter.width+" hauteir scooter"+scooter.height);
 fond.resize(width,height);
 scooter.resize(width,height);
 plot.resize(width,height);
 //println("largeur:"+fond.width+" hauteur :"+fond.height);
  println("largeur fond :"+fond.width+" hauteir fond"+fond.height);
  println("largeur scooter :"+scooter.width+" hauteir scooter"+scooter.height);
  //  myBus = new MidiBus(this, "USB MIDI CABLE", "USB MIDI CABLE");
}

void draw() {
  SoundA*=0.90;
  SoundB*=0.95;
  t_A*=0.98;
  t_B*=0.98;
//println("SOUND : "+SOUND);

  loadPixels(); 
  fond.loadPixels(); 
  scooter.loadPixels();
  plot.loadPixels();
  for (int y = 0; y < height; y++) {
    for (int x = 0; x < width; x++) {
      int loc = x + y*width;
      
      float fond_r = red(fond.pixels[loc]);
      float fond_g = green(fond.pixels[loc]);
      float fond_b = blue(fond.pixels[loc]);
      
      float scooter_r = red(scooter.pixels[loc]);
      float scooter_g = green(scooter.pixels[loc]);
      float scooter_b = blue(scooter.pixels[loc]);
      
      float plot_r = red(plot.pixels[loc]);
      float plot_g = green(plot.pixels[loc]);
      float plot_b = blue(plot.pixels[loc]);
      
    //if (scooter_r <= 10 && scooter_b <= 10 && scooter_g >= 250){
      if ((scooter_r > fond_r) && (scooter_g > fond_g) && (scooter_b > fond_b)){
        float resultat_r = (1-t_A)*fond_r + t_A*scooter_r ;
        float resultat_g = (1-t_A)*fond_g + t_A*scooter_g ;
        float resultat_b = (1-t_A)*fond_b + t_A*scooter_b ;
        pixels[loc] =  color(resultat_r,resultat_g,resultat_b);        
      }
    else if ((plot_r > fond_r) && (plot_g > fond_g) && (plot_b > fond_b)){
        float resultat_r = (1-t_B)*fond_r + t_B*plot_r ;
        float resultat_g = (1-t_B)*fond_g + t_B*plot_g ;
        float resultat_b = (1-t_B)*fond_b + t_B*plot_b ;
        pixels[loc] =  color(resultat_r,resultat_g,resultat_b);  
    }
    else{
       
    pixels[loc] =  color(fond_r,fond_g,fond_b); }  
    
  }}
  updatePixels();
rect(width/2,height,20,-SoundA*5,3);
rect(width/3,height,20,-SoundB*5,3);
blendMode(OVERLAY);
image(myMovie,0,0,width,height);


  }
void noteOn(int channel, int pitch, int velocity, long timestamp, String bus_name) {
  // Receive a noteOn
  println();
  println("Note On:");
  println("--------");
  println("Channel:"+channel);
  println("Pitch:"+pitch);
  println("Velocity:"+velocity);
  println("Bus:"+bus_name);
  if (bus_name == BusA_nom){
    //x=pitch;
    place_restanteA=100-SoundA;
    //ajout=(velocity/127)*place_restante;
    ajoutA=(velocity*velocity*place_restanteA)/(127*127);
    SoundA+=ajoutA;
    println("place_restante : "+place_restanteA);
    println("ajout : "+ajoutA);
    println("SOUND : "+SoundA);
    t_A = min(1,2*float(SoundA)/127);
    println("t : "+t_A); 
  }
  else if (bus_name ==BusB_nom){
    place_restanteB=100-SoundB;
    //ajout=(velocity/127)*place_restante;
    ajoutB=(velocity*velocity*place_restanteB)/(127*127);
    SoundB+=ajoutB;
    println("place_restante : "+place_restanteA);
    println("ajout : "+ajoutB);
    println("SOUND : "+SoundB);
    t_B = min(1,2*float(SoundB)/127);
    println("t : "+t_B); 
  }
  else{
  }
  
}

void noteOff(int channel, int pitch, int velocity, long timestamp, String bus_name) {
  // Receive a noteOff
  println();
  println("Note Off:");
  println("--------");
  println("Channel:"+channel);
  println("Pitch:"+pitch);
  println("Velocity:"+velocity);
}

void controllerChange(int channel, int number, int value, long timestamp, String bus_name) {
  // Receive a controllerChange
  println();
  println("Controller Change:");
  println("--------");
  println("Channel:"+channel);
  println("Number:"+number);
  println("Value:"+value);
}
void movieEvent(Movie m) {
  
  m.read();
}

#6

I think you need to put everything in 1 sketch.

It can be okay to test your effects on separate sketches but when playing live, having all in 1 sketch would be easier.

The way I would go about it is to create a framework that would allow me to simply add several effects and decide the order in which I want to play them. Then it will take care of the transition and all you would have to do would be to copy the test code on a new tab of your framework to make it works.


#7

Hi again, i tried to make a basic code that i think will help you with your project. And also to make the fade to black effect but i think there are better options out there.

long previousTime = 0;
long currentTime = 0;

int currentAnimation = 0;

void setup() {
  size (600, 600);
  background(255);
}


void draw() {

  println(currentAnimation);
  //this will you your current animation
  switch(currentAnimation) {  
  case 0:
    animation0();
    break;

  case 1:
    animation1();
    break;

  case 2:
    animation2();
    break;
  }
}

//a white rect with red background
void animation0() {
  currentTime = millis();
  if (currentTime - previousTime < 5000) {
    background(255 - 0.05 * (currentTime - previousTime));
  } else { 
    background(255, 0, 0);
    fill(255);
    rect(100, 100, width/2, height/2);
  }
}

//the line in the middle
void animation1() {
  currentTime = millis();
  if (currentTime - previousTime < 5000) {
    background(255 - 0.05 * (currentTime - previousTime));
  } else { 
    background(0, 0, 255);
    stroke(255);
    noFill();
    beginShape();
    for (int i = 0; i < width; i+= 20) {
      vertex(i, height/2 + random(-50, 50));
    }
    endShape();
  }
}

//random ellipses 
void animation2() {
  currentTime = millis();
  if (currentTime - previousTime < 5000) {
    background(255 - 0.05 * (currentTime - previousTime));
  } else {
    background(0, 255, 0);
    fill(random(255), 0, 0);
    for (int i = 0; i < 20; i++) {
      ellipse(random(0, width), random(0, height), random(20, 50), random(20, 50));
    }
  }
}
//every time you pressed the key a, you'll change
//the current animation, if you are in the last animation (2)
//it'll return at the animation 0
void keyPressed() {
  if (key == 'a') {
    previousTime = currentTime;
    currentAnimation++;
    if (currentAnimation > 2) {
      currentAnimation = 0;
    }
  }
}


#8

Thanks a lots for your help Bryan !
Now I get it.
The last thing I’m not sure of is :
Every animation will be using the function “NoteOn”. Since the result of playing a midi note will have to have different actions depending on each animation, should I make

  1. a “switch” in the function NoteOn (like, if we are in animation2, modify the radius of an ellipse, if we are in animation1, modify the width of a line) .
    Or
  2. make a global variable pitch, velocity, etc , that will be used by each animation ?

thank you again


#9

I think it’ll be easier if you use global variables. let say the width of the line, but, I guess there are better ways to do it. Basically you have to understand “if I’m in the case 0, what I should do?, Ok, I’m in case 0, but if I pressed this key, I have to do this, and so on”.

Int widthLine = 5;

void draw (){
switch(currentAnimation){
case1:
animation1 ();
modifyWidth(); 
break;
}

void modifyWidth (){
If(midiButtonPressed){
widthLine+=5;
}
//here you can use a switch statement or various if, so depending of your midi key, you have a different action like rotate, substrate, etc.
}

void animation1(){
strokeWidth(widthLine);
//The line code
}

#10

If you are looking for a general purpose way to cross-fade 2 or more sketches during a live show, then I would strongly recommend a framework such as PraxisLive, which will allow you to treat Processing sketches as patches.

If you don’t want to use something like that, you can try to compile every sketch you plan to use into a single meta-sketch, but this approach is very inflexible if you are working on a concert set and developing a collection of material.