How to receive all ofxMidi events during a draw() loop

Hello,

I am using ofxMidi to use midi events to draw certain objects to the screen in the draw() method the same way as in this example: https://github.com/danomatika/ofxMidi/blob/master/exampleInput/src/ofApp.cpp.

The problem is, however, that when I press keys faster than the time it takes for one draw() function to execute, it only registers the last key I pressed, not all that weren’t rendered the previous frame. How would it be possible to implement this? I assume the keyPressed() bypasses this issue, but I cannot figure out looking at the source code to do it.

Any help would be appreciated.

Hello @macusual,

Can we see your ofApp::newMidiMessage(ofxMidiMessage& msg) ?

The keyPressed() in only for keyboard input, not midi input.

Best,
V

My ofApp::newMidiMessage is implemented the same way as in the example, like this:

void ofApp::newMidiMessage(ofxMidiMessage& message)
{
    msg = message;
}

With having expressions like this in the ofApp::draw() method (or update() – doesn’t make a difference):

float h = ofMap(msg.value, 0, 127, 0.0, 1.0);
if (msg.control == 1) swirl.setHue(h);

Hello,

First check if your app runs at 60 fps (ofSetFrameRate(60))
Assuming your app runs @ 60 fps: when you’re sending midi messages very fast (approx < 16/20ms between each, this is fast!), your app could discard some, as it can not operate fast enough to process them. The variable msg is declared as a member variable, so it lives throughout your whole app. Since midi messages follow each other very fast, the newMidiMessage callback has already rewritten the msg variable, overwriting the previous one.

A possible and effective way to store midi messages so that your update/draw loop can iterate over them, processing each, could be:

ofApp.h

#include <queue>

std::queue<ofxMidiMessage> messages; // good container for FIFO

ofApp.cpp

//--------------------------------------------------------------
void ofApp::draw(){
    // iterate over all received message and do something...
    while (!messages.empty()) {
        printf("%lu messages to process.\n", messages.size());
        ofxMidiMessage mes = messages.front();
        std::cout << "Pitch: " << mes.pitch << std::endl;
        messages.pop();
    }
}

//--------------------------------------------------------------
void ofApp::newMidiMessage(ofxMidiMessage& msg) {
    // store in queue
    messages.push(msg);
    
}

Best,
V

That’s an elegant solution. I’ll try it out now, thanks!