Great, good code to handle those messages.
I found what could be a good solution:
We have to modify ofxMidi to handle system messages.
In Midi, Midi Clock is comming on byte “zero” number 248 (MIDI_TIME_CLOCK) , sending each tick (1/24th quarter note). There is no byteOne or Two.
When there is a stop, midi sends in byteZero number 252 (MIDI_STOP)
When there is a start, midi sends byteZero number 250 (MIDI_START).
To send a song position pointer, midi sends on byteZero = 242 (MIDI_SONG_POS_POINTER), byteOne and Two will be the position.
But the problem is how ofxMidi handle those messages.
Let ´s look into ofxMidiIn.cpp -> ManageNewMessage method:
void ofxMidiIn::manageNewMessage(double deltatime, vector< unsigned char > *message){
unsigned int nBytes = message->size();
if(bVerbose){
cout << "num bytes: "<<nBytes;
for ( unsigned int i=0; i<nBytes; i++ )
cout << " Byte " << i << " = " << (int)message->at(i) << ", ";
if ( nBytes > 0 )
cout << "stamp = " << deltatime << '\n';
}
if(nBytes>0){
ofxMidiEventArgs eventArgs;
eventArgs.channel = ((int)(message->at(0)) % 16)+1;
eventArgs.status = ((int)message->at(0)) - (eventArgs.channel-1);
eventArgs.timestamp = deltatime;
if(nBytes==2){
eventArgs.byteOne = (int)message->at(1);
}else if(nBytes==3){
eventArgs.byteOne = (int)message->at(1);
eventArgs.byteTwo = (int)message->at(2);
}
ofNotifyEvent( newMessageEvent, eventArgs, this );
}
}
but there is an incorrect handling here:
eventArgs.channel = ((int)(message->at(0)) % 16)+1;
eventArgs.status = ((int)message->at(0)) - (eventArgs.channel-1);
eventArgs.timestamp = deltatime;
For messages like Midi Time Clock one (248, void, void) it will be done:
channel = 9
status = 240
And this is incorrect. It should be:
status = 248
channel = whatever (goes to all channels) , say channel 0 …
Same for all the midi messages that are NOT as control, notes, etc.
So I had to change ofxMidiIn.cpp -> manageNewMessages function to this one:
void ofxMidiIn::manageNewMessage(double deltatime, vector< unsigned char > *message){
unsigned int nBytes = message->size();
if(bVerbose){
cout << "num bytes: "<<nBytes;
for ( unsigned int i=0; i<nBytes; i++ )
cout << " Byte " << i << " = " << (int)message->at(i) << ", ";
if ( nBytes > 0 )
cout << "stamp = " << deltatime << '\n';
}
if(nBytes>0){
ofxMidiEventArgs eventArgs;
eventArgs.timestamp = deltatime;
int byteZero = (int)(message->at(0));
/// this is when the midi message is NOT into the category of midi system messages...
if( byteZero < MIDI_TIME_CODE){
eventArgs.channel = ((int)(message->at(0)) % 16)+1;
eventArgs.status = ((int)message->at(0)) - (eventArgs.channel-1);
if(nBytes==2 ){
eventArgs.byteOne = (int)message->at(1);
eventArgs.byteTwo = 0;
}else if(nBytes==3) {
eventArgs.byteOne = (int)message->at(1);
eventArgs.byteTwo = (int)message->at(2);
}
ofNotifyEvent( newMessageEvent, eventArgs, this );
/// and now for midi messages INTO the category of midi system, etc.
} else {
eventArgs.channel = 0;
eventArgs.status = (int)message->at(0);
if(nBytes==1 ){
// we make byeOne and Two = 0 to not to deal with previous values.
eventArgs.byteOne = 0;
eventArgs.byteTwo = 0;
}else if(nBytes==2 ){
eventArgs.byteOne = (int)message->at(1);
eventArgs.byteTwo = 0;
}else if(nBytes==3) {
eventArgs.byteOne = (int)message->at(1);
eventArgs.byteTwo = (int)message->at(2);
}
ofNotifyEvent( newMessageEvent, eventArgs, this );
}
}
So this would be an example of code that uses this new ofxMidiIn.cpp::
int port = args.port ;
int channel = args.channel;
int status = args.status;
int byteOne = args.byteOne;
int byteTwo = args.byteTwo;
double timestamp = args.timestamp;
int _ticksPerqNote = (int) 24.0 * 4.0/tempoDenominator;
ticksPerBar = tempoNumerator * ticksPerqNote;
ticks32thNotePerBar = (int) ticksPerBar/8.0;
ticksPer32thNote = (int) ticksPerqNote/8.0;
if(status == MIDI_TIME_CLOCK)){
tempoTicks += 1;
ticksfor32thNote +=1;
if(ticksfor32thNote % ticksPer32thNote == 0 ) {
// if(num32thNotes % 2 == 0) midiOut.sendNoteOff(1, 62, 0); else midiOut.sendNoteOn(1, 62, 127);
num32thNotes += 1;
}
if(tempoTicks % _ticksPerqNote == 0 ) {
tempoqNotes += 1;
tempoTicks = 0;
//// hemos llegado al beat final::::
if (tempoqNotes % (tempoNumerator + 1) == 0 ) { /// eso está bien ???
tempoBars += 1;
tempoqNotes = 1;
num32thNotes = 0;
ticksfor32thNote = 0;
}
}
}
////////////////////
if(status == MIDI_START) {
//ticks = 0;
//qNotes = 0;
//bars = 0;
tempoTicks = 0;
tempoqNotes = 1;
tempoBars = 1;
isPlaying = false;
num32thNotes = 0;
ticksfor32thNote = 0;
cout << " live Set playing ...." << endl;
isPlaying = true;
};
//////////////////
if(status == MIDI_STOP) cout << " live Set paused " << endl;
//////////////////
if(status == MIDI_SONG_POS_POINTER && byteOne == 0 && byteTwo == 0) {
cout << " live Set stopped " << endl;
tempoTicks = 0;
tempoqNotes = 1;
tempoBars = 1;
//isPlaying = false;
num32thNotes = 0;
ticksfor32thNote = 0;
}