Midi and Object-Oriented Programming

Hello,
I’m new here. I am trying to control an object oriented project with a midi controller.
After doing my oop sketch (thanks to the coding train), I thought I should use the midiBus library. But I can’t figure how to add the void controllerChange in it. I tried to put it in the object class but the println won’t work so this must not be the proper thing to do. Also, I was trying to change floats and not vectors and maybe this is not even possible.
Sorry if this might seem an obvious topic.

class Vehicle {

  PVector position;
  PVector velocity;
  PVector acceleration;
  float r;
  float sw;
  float sline;
  float slinea;
  float maxforce;    // Maximum steering force
  float maxspeed;    // Maximum speed
  
  float bigger;

    // Constructor initialize all values
  Vehicle(float x, float y, float contour, float line, float linea) {
    position = new PVector(x, y);
    r = 4;
    sw = contour;
    sline = line;
    slinea= linea;
    maxspeed = 4;
    maxforce = 0.1;
    acceleration = new PVector(0, 0);
    velocity = new PVector(0, 0);
  }
  
  void controllerChange( int number, int value) {
    println(number);
    if(number==13){
      bigger= map(value,0,127,0,250);
      println("gros:"+grooos);
    }
  }
  
  

  void applyForce(PVector force) {
    // We could add mass here if we want A = F / M
    acceleration.add(force);
  }
  
  void applyBehaviors(ArrayList<Vehicle> vehicles) {
     PVector separateForce = separate(vehicles);
     PVector seekForce = seek(new PVector(mouseX,mouseY));
     separateForce.mult(1.0);
     seekForce.mult(0.5);
     applyForce(separateForce);
     applyForce(seekForce); 
  }
  

  PVector seek(PVector target) {
    PVector desired = PVector.sub(target,position);  
    desired.normalize();
    desired.mult(maxspeed);
    PVector steer = PVector.sub(desired,velocity);
    steer.limit(maxforce);  
    
    return steer;
  }

 
  PVector separate (ArrayList<Vehicle> vehicles) {
    float desiredseparation = r*4;
    PVector sum = new PVector();
    int count = 0;
   
    for (Vehicle other : vehicles) {
      float d = PVector.dist(position, other.position);
      // If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself)
      if ((d > 0) && (d < desiredseparation)) {
        // Calculate vector pointing away from neighbor
        PVector diff = PVector.sub(position, other.position);
        diff.normalize();
        diff.div(d);        
        sum.add(diff);
        count++;            // Keep track of how many
      }
    }
    // Average -- divide by how many
    if (count > 0) {
      sum.div(count);
      sum.normalize();
      sum.mult(maxspeed);
      sum.sub(velocity);
      sum.limit(maxforce);
    }
    return sum;
  }


  // Method to update position
  void update() {
    velocity.add(acceleration);
    velocity.limit(maxspeed);
    position.add(velocity);
    acceleration.mult(0);
    r= r+bigger;
  }

  void display() {
    
    //strokeWeight(sw);
    //stroke(sline,slinea);
    pushMatrix();
    translate(position.x, position.y);
    ellipse(0, 0, r, r);
    popMatrix();
  }
  
}

If you have any idea, that would be great,
Thanks!

2 Likes

For reference:

TheMidiBus library
Themidibus basic example

There is a few approaches and it will really depend on your whole concept. There is an approach documented in one of the lib example here. Based on the code you provided, you could do something like this:

import themidibus.*; //Import the library

MidiBus myBus; // The MidiBus
Vehicle testv;

void setup() {
  size(400, 400);
  background(0);

  MidiBus.list(); // List all available Midi devices on STDOUT. This will show each device's index and name.

  // Either you can
  //                   Parent In Out
  //                     |    |  |
  myBus = new MidiBus(this, -1, 2); // Create a new MidiBus using the device index to select the Midi input and output devices respectively.

  testv=new Vehicle(myBus);
}

void draw() {
  int channel = 0;
  int pitch = 64;
  int velocity = 127;
  Note note = new Note(channel, pitch, velocity);

  myBus.sendNoteOn(note); // Send a Midi noteOn
  delay(200);
  myBus.sendNoteOff(note); // Send a Midi nodeOff

  testv.play();
}

//void delay(int time) {
//  int current = millis();
//  while (millis () < current+time) Thread.yield();
//}


class Vehicle {

  MidiBus externalBusHandle;

  Vehicle(MidiBus handle) {
    externalBusHandle=handle;
  }

  void play() {
    int channel = 0;
    int velocity = 127;
    int number = 0;
    ControlChange change = new ControlChange(channel, number, velocity);

    println("ON");
    myBus.sendControllerChange(change); // Send a controllerChange
    delay(2000);
    reportChange(change);
  }

  void reportChange(ControlChange change) {
    // Receive a controllerChange
    println();
    println("Controller Change:");
    println("--------");
    println("Channel:"+change.channel());
    println("Number:"+change.number());
    println("Value:"+change.value());
  }
}

To run the example above, you first need to list the available synthesizers as shown in setup() and then choose one from the list and update the proper line in setup().

I am not sure if this answers your question though. It is important to know what is the scope of your MidiBus in your sketch. For instance, if you will have only one Vehicle, then you might actually create the MidiBus inside the vehicle and do all the management of the MidiBus there. However, because you are accessing external hardware, and you might have more than one vehicle, then the approach that I show above would potentially be better. You initialize your MiDiBus at your sketch level and then you pass it to each “Vehicle” object that needs it. I do not know much about the MidiBus project, but something you should look into is what if several objects try to change (for instance, setting a note) on your MidiBus. Would the last object making the change take prevalence over the other objects in a draw cycle?

There are other few things you need to reconsider about your sketch.

There is a delay function in processing. If you remove your delay definition, your sketch will work. You might not need these lines.

Second, when you use the delay in draw(), you are actually blocking draw. Nevertheless this is the approach the library creator suggested in his examples. For you, you need to remember that if you are using mouse or key events to drive your sketch, they will not be processed immediately but only after the delay release the draw() function. In the example above, every 2 seconds. This also means your draw is not running at 60fps but more like 0.5 fps.

Kf