Building a Midi Controller/Sequencer thing

hi, my name is Thomas
and I am new to arduino and this forum.

I'd like to present you the project I'm working on,
and maybe you got some guidance for me.
Well i need some I guess.

As a musician I'm working with apples MainStage, which ist great but lacks any sort of automation, so I got me a Teensy and a bunch of Tutorials.
My style is Ed Sheehanish Acoustic Guitar looping.

Here's the need:

the ability to run a certain sequence depending on the incoming Midi program change.
Everything Synced, of course, MainStage mostly gets Midi NoteOn/Off commands.

one switch starts/stops MainStage.

the second switch will have two functions:
a) start the Arduino „sequence“, starts the „count“ (Ticks, bars, measures)
b) rewind to certain points in that running sequence.
That's for example: on measure 7, tick 90 the sequence starts one of MainStage Loopers at Measure 8.
now on measure 9 I make a mistake, I hit that button again, the sequence „rewinds“ to the same position (say... tick 78) in measure 7, commands are sent to stop and clear the looper.

I think I can get through all the things I need (I didn't try that rewind stuff yet), but only with a whole lot of if/else /while loops and huge amounts of variables and code.

Here is what I got so far, please have a look at it, I bet there's a more sophisticated approach to this. e.g. I tried to work with Function Pointers, but with little success...

thanks

Code starts here:

const byte START = 250;
const byte STOP = 252;
const byte CLOCK = 248;

// variables for recieved MidiClockTicks, resulting Beats and full measures
byte tick = 0;
byte schlag = 0;
byte takt = 1;

// variables for the switch and its resulting state (see void loop())
int S1 = HIGH;
int S1_1 = HIGH;
bool ply = false;

//variable for recieved Midi ProgramChange
byte programNum = 0;

// give the midi notes to be sent a good name
#define start_stop 40
#define allstop 43
#define L1_playstop 41
#define L1_stop 42




void setup() {
  pinMode(12, INPUT_PULLUP);
  pinMode(13, OUTPUT);
  usbMIDI.setHandleProgramChange(myProgramChange);
  usbMIDI.setHandleRealTimeSystem(beatClock);
  Serial.begin(312500);
}




void loop() {

  int S1 = digitalRead(12);

  if (S1 == LOW && S1_1 == HIGH) {
    usbMIDI.sendNoteOn(start_stop, 127, 1); S1_1 = S1;
    }
  if (S1 == HIGH && S1_1 == LOW) {
    usbMIDI.sendNoteOff(start_stop, 0, 1); S1_1 = S1; ply =! ply;
    }
  
  usbMIDI.read();
}   


//if there is a program change, catch the program number and stop it all with halt()
void myProgramChange(byte channel, byte program) {
  programNum = program; halt();
  }


// 
void beatClock(byte realtimebyte) {
  if(realtimebyte == START) {// reset with each START from the host
    tick = 0;
    takt = 1; 
    schlag = 0;
    }
  if(realtimebyte == STOP) {//well, stop...
    halt();
    }

  //„play“ the commands of Song according to number of program
  if(programNum == 1) {
    song_01(realtimebyte);
    }
  if(programNum == 2) {
    song_02(realtimebyte);
    }
  } 

void song_01(byte realtimebyte) {
    // if there is ticks coming AND I pressed „play“
    if(realtimebyte == CLOCK && ply == true) {
    // increase tick with each recieved Midi Click
    tick++; 
      //reset to 1 after 96 click (= full measure)
      if(tick % 97 == 0) {
        tick = 1;
        } 
      // Blink part one and increase the number of Beats every 24 ticks
      if(tick == 1 || tick == 25 || tick == 49 || tick == 73) {
        digitalWrite(13, HIGH);  
        schlag++;
        } 
    // reset beats to 1 depending on 3/4 or 4/4 Measure
      if(schlag % (5) == 0) {
      takt++;
      schlag = 1;} 
    // Blink part two
      if(tick == 10 || tick == 26 || tick == 50 || tick == 74) {
      digitalWrite(13, LOW);
      }
    serialPrint();
    if(takt == 2 && tick == 90) {befehl(L1_playstop);} //the commands
    if(takt == 4 && tick == 48) {befehl(L1_playstop);}
    if(takt == 4 && tick == 90) {befehl(L1_playstop);}
    if(takt == 5 && tick == 90) {befehl(L1_playstop);}
    if(takt >= 8) {halt();}
   }
  }

void song_02(byte realtimebyte) {// see above...
  if(realtimebyte == CLOCK && ply == true) {
    tick++;
    if(tick % 97 == 0) {
      tick = 1;
      }
    if(tick == 1 || tick == 25 || tick == 49 || tick == 73) {
      digitalWrite(13, HIGH); schlag++;
      }
    if(schlag % (5) == 0) {
      takt++; schlag = 1;
      } 
    if(tick == 10 || tick == 26 || tick == 50 || tick == 74) {
      digitalWrite(13, LOW);
      }
    serialPrint();
    if(takt == 3 && tick == 90) {
      befehl(L1_playstop);
      }
    if(takt == 5 && tick == 48) {
      befehl(L1_playstop);
      }
    if(takt == 6 && tick == 90) {
      befehl(L1_playstop);
      }
    if(takt == 7 && tick == 90) {
      befehl(L1_playstop);
      }
    if(takt >= 8) {
      halt();
      }
   }
  }

void serialPrint(){ //self explanatory?
  Serial.print(takt);
    Serial.print(" / ");
    Serial.print(schlag);
    Serial.print(" / ");
    Serial.println(tick);
  }

void befehl(byte note) { //function for sent commands
    usbMIDI.sendNoteOn(note, 127, 1);
    usbMIDI.sendNoteOff(note, 0, 1);
  }

  void halt() { //stop and reset everything
    takt = 1; schlag = 0;
    usbMIDI.sendNoteOn(allstop, 127, 1);
    usbMIDI.sendNoteOff(allstop, 0, 1);
    befehl(L1_stop);;
    ply = false;
    digitalWrite(13, LOW);
  }
Tippe oder füge den Code hier ein

Please post all your code, with any "include" things that bring in libraries &c.

Use the </> thing in the toolbar, paste your code within the space it opens up in your post.

Use the IDE auto format ability (Tools Menu) first.

It will look like this

// see how nice your code will look

void loop() {
    blah blah blah blah 
}

Also, what library are you using?

It will make helping easier.

TIA

a7

Hi alto, I updated my Post.

I am using a teensy that has all that Midi Stuff included, Non include.h etc.
what you see is the complete code. I have no idea what libraries the teensy ist using internally...

cheers
thomas

Haha, that's programming for you. Anything programmed in a straight ahead manner with no advanced tricks is going to have all that stuff you worried about. :wink:

But.

Sry, I've run the Teensyduino, to which I added a plausible library from jcpr (something like that), and your code doesn't compile here yet, there is no creation of the

usbMIDI

object you use all over the place.

I will try to look at the code, but usually being able to comblike it at least is a helpful step.

Do you have any idea what I may be missing? I assume you are able to run the code you presented, and it sounds like however you set up your teensy IDE gave you the library automatically, but I am still missing the creation of the midi object.

I haven't looked at the midi library source code... 1) I'm not sure I have the right one in front of me so 2) since I am with my nostrils at the level of the water here it might not help if I was sure.

a7

You have to select the "MIDI" USB type in the Tools menu, this will give you access to the usbMIDI object.

@PieterP THX, found it.

Not only did I not think of that, I might never have. :wink:

a7

Ok, I'm late here: select MIDI USB output for the Teensy... sorry
thanks PieterP.

What I tried to make this a bit less IF-Else-heavy was a function pointer
(all „songs“ in an array, have the void beatClock look it up:
Program Change received = number, number = position of Song in Array)

Maybe someone can give me at least a hint what fancy advanced programming techniques might come in handy in my project : )

Don't worry, don't hurry, it's a hobby