midi input

Hi all, I want to control some of the variables in my app with a midi controller and was wondering what the best option is? I almost considered writing a little app in processing to map incoming midi CC to OSC, but I was hoping there’s a better way! I read somewhere that there was the beginnings of a midi addon, though output only - was wondering what the latest situation is?

Cheers,

Hi

I’ve used sometimes a processing app that generates osc messages from midi input but it’s a little ineficient. I needed something like that for an app i’m working in so i’ve made an ofxMidiInput.

It uses rtMidi, I’m only using it to receive values from one of those midi usb tables with knobs and sliders, so perhaps the way it’s programmed is not the best for real midi uses.

It’s based on poco events, you just need to extend ofxMidiListener in the class you want to receive the event and overwrite the method newMessage. I’ve seen in other midi input libraries, like the one in processing that it generates diferent types of messages like noteon, noteoff, controllerin… but with rtmidi I only receive the id the value and the number of milliseconds since the last message.

http://65.111.166.199/openframeworks/ofxMidiIn.zip

EDIT:

to use this in the diferent platforms some compiler flags are needed:

linux:

-D __LINUX_ALSASEQ__

or just add at the begining of rtMidi.h:

#define __LINUX_ALSASEQ__

mac:

-D __MACOSX_CORE__ -framework CoreMidi -framework CoreAudio -framework CoreFoundation

although CoreAudio framework should be already there

windows:

-D __WINDOWS_MM__ -lwinmm -llib -lmultithreaded

haven’t tested in windows but from the rtMidi page should be something like that

Wow, great work arturo.
I haven’t installed poco yet so I can’t yet try it. But it sounds like you have it all there.

like the one in processing that it generates diferent types of messages like noteon, noteoff, controllerin… but with rtmidi I only receive the id the value and the number of milliseconds since the last message.

I’m guessing the id represents the type of midi message, i.e.
Note Off, Note On, AfterTouch, Control Change, Program Change etc

and the value is just the corresponding value between 0-127.

Pitch wheel messages have a higher resolution, so they might not be detected properly. Otherwise it looks like it should work with all other messages.

Well, the id is just the number of the control that it’s being activated. I think the type of event has something to do with the timestamp and the values that are being generated, but don’t know how it works.

I also receive another value that might be the type of message, but it’s always the same: 176 for buttons and sliders, and the java library actually generates diferent messages for those…

Hey arturo, thanks for that will hava look. I ended up using Quartz Composer to map the midi to OSC, not the most efficient but quickest to implement. will check out your addon though cos I use it a lot…

Thanks for creating this wonderful MIDI input addon, very useful for a project I’m working on at the moment. Currently, I’m also having QC mapping midi to OSC to use midi information in Open Frameworks, though I would really go for direct input in OF.

Unfortunately, I don’t get Poco added to my project in XCode, which is needed for your addon. Whenever I add Poco libs to a project I get this waterfall of errors telling me that ‘::memcpy’ has not been declared and 99 similar messages for ‘memmove’, ‘strcpy’, etc. etc.

I have the feeling I’m doing something wrong in my build parameters, could anyone post a working xCode project for this addon?

-> EDIT: Great I found this nice threat on poco which solved my problem: http://forum.openframeworks.cc/t/event-handling-±merging-of-with-poco-c++/408/18, sorry for being too fast on my question

Thanks for this - exactly what I needed!

I added:

ofxMidiIn.cpp

  
	  
		eventArgs.msgType=(int)message->at(0);   
  

ofxMidiEvents.h

  
protected:  
  
	virtual void newMessage(int port, int msgType, int id, int value, double timestamp){};  
  
public:  
  
	void newMessage(const void* sender, ofxMidiEventArgs& eventArgs){  
		ofxMidiEventArgs& midiArgs = (ofxMidiEventArgs&)eventArgs;  
		newMessage( ((ofxMidiIn*)sender)->getPort(), midiArgs.msgType, midiArgs.id, midiArgs.value, midiArgs.timestamp);  
	}  
  
};  

to to give me the midi data types (as integers):
176 Control Change
144 Note On
128 Note Off
224 Pitchbend
240 Sysex Start
247 Sysex End

No luck getting a 14bit number for pitchbend, but maybe this is a problem with rtMidi?

perhaps you already tried this, but in ofxMidiIn.cpp in the newMessage method theres:

  
if(nBytes == 3){...  

I used that as all the messages the controller I was using had 3 bytes, but surely changing it will work with other types of messages. Please post the changes if you manage to do it so I can add it to the addon.

Wow arthuro, we think alike. I just wrote a Midi class with Poco based events, with the exactly the same class names as you used… I like your style :wink: I guess it’s because i based it on the ofxHttp addon you & chris wrote

:slight_smile: Yes, the httpUtils, mailUtils and this one have really similar structure…

Did you find anything about other kind of messages? I only programmed this with a usb table with some knobs I had by then, but haven’t tried with other devices.

I only used it with a Maudio Trigger Finger, also USB. I thought (and still think) that all midi messages where (program, status, value). Then i just use another class to decode the midi events into values connected to defines representing the different keys, knobs and sliders on the Trigger Finger.

Hi there

Has anyone had any luck getting this to work in CodeBlocks on Windows?

I can’t seem to set the right linker flags,a s I keep getting a whole slew of:

  
undefined reference to 'vtable for RtMidiIn'  
undefined reference to....  
etc  
  
  

Some googling around tells me that this is because I don’t have the right compile flags set, but am having trouble figuring out the correct ones.

Have tried linking to the libwinmm.a library - no luck…
Have tried using the compile flags above… -lmultithreaded leads to the compiler balking as it can’t find this…

Any ideas?

Hi (arturo)

I’m having a little trouble building.

My windows Codeblocks (0.06) project has these search directories…

“…\addons\ofxMidi\src”
“…\addons\ofxMidi\events”
“…\addons\ofxMidi\libs”

and these files are added
…\addons\ofxMidi\events\ofxMidiEvents.h
…\addons\ofxMidi\libs\RtMidi.cpp
…\addons\ofxMidi\libs\RtMidi.h
…\addons\ofxMidi\src\ofxMidiIn.cpp
…\addons\ofxMidi\src\ofxMidiIn.h

RtMidi.cpp is kicking up a load of errors, starting with

#include <pthread.h>
“No such file or directory”

What am I missing?

Thanks

hi chris

in RtMidi.h line 43:

#define __LINUX_ALSASEQ__

for windows should be:

#define __WINDOWS_MM__

and for mac:

#define __MACOSX_CORE__

thanks art.

ive done that. now in ofxMidiEvents.h

for:
class ofxMidiEventArgs: public ofEventArgs{

it says build error:
expected class-name before ‘{’ token

Thanks

the problem is this addon is for 0.057xx not for 006, i thought i’ve already ported this but indeed i didn’t :slight_smile: will port it as soon as i can.

Ah, all you have to do is add this to the top of ofxMidiEvents.h

#include “ofEvents.h”

Great addition Gameover.

I was trying to work out which byte was the channel number, but I noticed when I do a control change on channel 1 it the type is 176, but then I do control change on channel 2 it gives me a type 177. Channel 16 = type of 191

This sort of makes sense. 128+16 = 144

So it might be something like:

128 - 143 = Note Off (channel 1 - 16)
144 - 159 = Note On (channel 1 - 16)

I’ve just found this which confirms it, see bottom of the page
http://www.earlevel.com/MIDI/MIDI%20Overview.html

[update]
Here is an addition to ofxMidiIn that will work out the correct channel number for a message, and also keep the message type to the right number…

  
  
void ofxMidiIn::newMessage(double deltatime, std::vector< unsigned char > *message){  
  
	unsigned int nBytes = message->size();  
	if(bVerbose){  
		std::cout << "num bytes: "<<nBytes;  
		for ( unsigned int i=0; i<nBytes; i++ )  
			std::cout << " Byte " << i << " = " << (int)message->at(i) << ", ";  
		if ( nBytes > 0 )  
			std::cout << "stamp = " << deltatime << '\n';  
	}  
  
    ofxMidiEventArgs eventArgs;  
    eventArgs.channel = ((int)message->at(0)) % 16;  
    eventArgs.msgType = ((int)message->at(0)) - eventArgs.channel;  
    eventArgs.channel += 1; // should start at midi channel 1 really  
    eventArgs.id = (int)message->at(1);  
    eventArgs.value = (int)message->at(2);  
    eventArgs.timestamp = deltatime;  
  
    eventManager->notify(eventArgs);  
}  
  

hi

has just made this a little bit more 006ish is more or less the same but now there’s no eventManager.

have also added the changes to differentiate the message type and some conditionals so it compile for the 3 platforms without needing to change RtMidi.h

haven’t really tested it, but it should work just the same as the previous version

ofxMidiIn.zip

thanks art, I will take a look.

Do you have any objections to me changing this from ofxMidiIn to ofxMidi ?

I’ve got to do midi out on the same port, so I was going to write in sending out into the class.

The code I posted that works out the type and channel is wrong, it only works for midi messages of 3 bytes, otherwise it crashes. Some messages I am getting such as midi clock are only 1 byte long.

I also want to add events and broadcasts to be more defined, ie call noteOn or noteOff functions. Maybe you can only listen for those types on certain channels too.

Also in my edit of your class I have…

  
  
// channel info  
#define 	MIDI_NOTE_OFF 	          128  
#define 	MIDI_NOTE_ON 	          144  
#define 	MIDI_POLY_PRESSURE 	      160  
#define 	MIDI_CONTROL_CHANGE       176  
#define 	MIDI_PROGRAM_CHANGE       192  
#define 	MIDI_CHANNEL_PRESSURE     208  
#define 	MIDI_PITCH_BEND           224  
  
// system exclusive  
#define 	MIDI_NOTE_ON 	          144  
  
// system common  
#define 	MIDI_TIME_CODE	          241  
#define 	MIDI_SONG_POS_POINTER     242  
#define 	MIDI_SONG_SELECT          243  
#define 	MIDI_TUNE_REQUEST         244  
#define 	MIDI_EOX                  247  
  
// system realtime  
#define 	MIDI_TIME_CLOCK           248  
#define 	MIDI_START                250  
#define 	MIDI_CONTINUE             251  
#define 	MIDI_STOP                 252  
#define 	MIDI_ACTIVE_SENSING       254  
#define 	MIDI_SYSTEM_RESET         255  
  

I’ll post my changes soon.