USBMIDI Beat Clock - Send A Quarter Note for Every 24 Ticks?

Status
Not open for further replies.
Hey all, thanks for taking the time to read. I'm trying to add external clock sync from a DAW to my project and I'm a little lost. The best documentation I've been able to find on how to implement the beat clock is from here but I'm still foggy. This is also my first time programming in a C language and I've been trying to pick up the syntax as I go, so it's very possible there may be conventions in here I would have picked up on if I had more previous experience or fundamentals I just have no idea about so I apologize my issues seem obvious.

As a test to get clock sync working in my program, I'm trying to generate a midi note send for every quarter note synced to my DAW. My rationale based off the above link is that every time the counter reaches 0 a note should play. If the DAW sends the START or CONTINUE byte the counter should start back at 0. If the DAW sends STOP I tried setting the counter to 1 so that the for loop condition would not be met and a midi note would not trigger. My understanding is that there are 24 ticks per quarter note from the midi clock so the counter should loop back to 0 when it hits 24 to keep track of quarter notes at any bpm.

I have my DAW set to only send clock when the track is rolling. The way the program behaves currently is that the usb note will repeatedly trigger in my DAW regardless of whether the track is playing or not. BPM changes do not seem to affect the rate. The start of the note pattern does not seem to reset when I hit play, though when I hit stop it does stop but only for a brief moment. The delay I inserted as a test between NoteOn and NoteOff seems to be the only thing that affects the rate of the note.

I'm on Teensy 2.0. Any help or hints very appreciated!!

Code:
byte counter;
byte CLOCK = 248;
byte START = 250;
byte CONTINUE = 251;
byte STOP = 252;

const int note = 60;
const int velocityOn = 99;
const int velocityOff = 0;
const int channel = 1;

void setup() {
usbMIDI.setHandleRealTimeSystem(myRealTimeSystem);
}

void loop() {

usbMIDI.read();

//////////clock test begin//////////
  for (counter==0; counter==0; ) {
    usbMIDI.sendNoteOn(note , velocityOn, channel);
    delay(500);
    usbMIDI.sendNoteOff(note, velocityOff, channel);
  }
//////////clock test end//////////

}

//////////beat clock begin//////////
void myRealTimeSystem(byte realtimebyte) {
  if (realtimebyte == 248) {
  counter++; 
    if (counter == 24) {
      counter = 0;
    }
    if (realtimebyte == START || realtimebyte == CONTINUE) {
        counter = 0;
    }
    if(realtimebyte == STOP) {
      counter = 1;
    }
  }
}
//////////beat clock end//////////
 
A few remarks,

Your use of the for loop is completely wrong. Condition instead of initialisation, no increase.
And instead of the for loop you should have used an if statement.
http://www.cplusplus.com/doc/tutorial/control/

The last two if statements are nested in the first one and in this case will never be executed!

Since timing of the system is dependent on the "counter" variable, as a good measure you don't want the mess with it anywhere else as in myRealTimeSystem().

The if statements in myRealTimeSystem() should be replaced by a switch statement, you really want to leave that function as fast as possible. But i'll leave that to you as an exercise. Refer to above link.

Here is a corrected version of your program to make it work like you intended.

Code:
byte CLOCK = 248;
byte START = 250;
byte CONTINUE = 251;
byte STOP = 252;

const int note = 60;
const int velocityOn = 99;
const int velocityOff = 0;
const int channel = 1;

bool quarternote_flag = false;

void setup() {
  usbMIDI.setHandleRealTimeSystem(myRealTimeSystem);
}

void loop() {

  usbMIDI.read();

//////////clock test begin//////////
  if (quarternote_flag) {
    usbMIDI.sendNoteOn(note , velocityOn, channel);
    quarternote_flag = false;
    delay(50);
    usbMIDI.sendNoteOff(note, velocityOff, channel);
  }
//////////clock test end//////////

}

//////////beat clock begin//////////
void myRealTimeSystem(byte realtimebyte) {
  static byte counter;
  if (realtimebyte == CLOCK) {
    if (counter == 24) {
      counter = 0;
      quarternote_flag = true;
    }
    counter++; 
  }
  if (realtimebyte == START) {
    counter = 24;
  }
  if(realtimebyte == CONTINUE) {
    counter = 24;
  }
  if(realtimebyte == STOP) {

  }
}
//////////beat clock end//////////
 
A few remarks,

Your use of the for loop is completely wrong. Condition instead of initialisation, no increase.
And instead of the for loop you should have used an if statement.
http://www.cplusplus.com/doc/tutorial/control/

The last two if statements are nested in the first one and in this case will never be executed!

Since timing of the system is dependent on the "counter" variable, as a good measure you don't want the mess with it anywhere else as in myRealTimeSystem().

The if statements in myRealTimeSystem() should be replaced by a switch statement, you really want to leave that function as fast as possible. But i'll leave that to you as an exercise. Refer to above link.

Here is a corrected version of your program to make it work like you intended.

Hey! Thanks so much for your suggestions. I am reading through what you did and it makes sense, and I'm reading up on switch statements.

Peculiarly though, I loaded up the program and I can't get it to produce any notes?
 
Peculiarly though, I loaded up the program and I can't get it to produce any notes?

Since I don't have a Teensy2, I tested this on a Teensy3.6 connected to an iMac and it happily spits out a note every beat when LogicPro is running.

Did you select USB type -> midi under the tools menu in arduino?
Does your Daw send out midi clock?
Switch the teensy led on after the noteOn command and off after the noteOff to facilitate debugging.

Midi problems can sometimes be hard to track.
 
Since I don't have a Teensy2, I tested this on a Teensy3.6 connected to an iMac and it happily spits out a note every beat when LogicPro is running.

Did you select USB type -> midi under the tools menu in arduino?
Does your Daw send out midi clock?
Switch the teensy led on after the noteOn command and off after the noteOff to facilitate debugging.

Midi problems can sometimes be hard to track.

My bad, I figured it out. Reason had another think to checkmark outside of the prefs to actually send the clock after clock output was set. Works now! And I set up the switch statement which also seems to be working. Thanks a million!!
 
Status
Not open for further replies.
Back
Top