configuring for MidiOut?

Hi All,

I have been racking my brain for a couple hours now trying to figure out how to set up my app to emulate a midi controller.

I have all my trigger logic worked out and everything, and I would like to be able to integrate the app with a audio program like garageband/adobe audition so that I can record the real time output if necessary or just play it through external speakers.

I tried (quite unsuccessfully) to add some midi libraries, one being Improv.

http://improv.sapp.org/doc/web/introduction/

I saw that midi/osc will be implemented in OF5 so that should be pretty awesome. Until then, what would be the best way to implement some midi functions?

Thanks,
Nick

You can also have a try using PortMidi:

http://www.cs.cmu.edu/~music/portmusic/

I’ve successfully used it to send midi messages from C/C++ code before…

we’ve gotten about 80% done with midi for making an addon, using rtMidi - if someone is interested, there is code here:

http://www.openframeworks.cc/files/ofMidiWork-2.zip

it’s definitely not a well coded addon (and only does output, no input yet) , compared to the wonderful OSC one coded by damian. I throw it out there in case someone would like to get it up and running and work on it. it’s unfinished, but it was working for me to send midi commands and do note-on, note-off type commands. If someone wants to work on it, they can PM me or email and I’ll explain what’s in and need to be done.

our first release with addons will feature:

opencv, osc, obj loading, director list, xmlSettings, network

I would imagine that midi will be part of the second round of addons (along with shaders)

I hope that’s helpful – it’s definitely on the way.

take care,
zach

Grimus and Zach,

Thanks for the new options, I can’t wait to try them out when i get back from class today!

I’ll post my results if I’m able to get rtMidi to work for me, hopefully I will.

-Nick

So after some trial and error, I got rtMidi integrated with my app.

I have working code to trigger a note output, but the note is repeatedly output like holding down a key on the keyboard. I looked for a bool function so that I could use a statement similar to the “getIsPlaying” function for audio files, but didn’t see one. here’s an idea of the code as it is now.

  
if (gridaa > 25){  
        playeraa.setInstrument(1);  
        playeraa.noteOnForDuration(60,127,5.0f);}  
	if (gridbc > 25){  
        playeraa.setInstrument(1);  
        playeraa.noteOnForDuration(80,127,5.0f);}  
	if (griddd > 25){  
        playeraa.setInstrument(1);  
        playeraa.noteOnForDuration(40,127,5.0f);}  

so what I’m trying to solve is to somehow allow detection of the duration in each statement. I thought about just trying to detect if a certain note is being played, but realized the note int will be replaced with an algorithm. so the note will be an unknown integer. which only leaves duration, right?

in midiPlayer.h, the bool “bHasDuration” seemed promising, but I just keep getting errors when compiling stating that it is not defined.

any ideas?

I’m not sure I understand the question

are you saying that noteOnForDuration fails to work? or that because of how youve coded, you need to know if a note is already playing?

the problem is that midi doesn’t allow you to query that info (while fmod does). but for that, it’s easy enough to code, I’d attack it in this way:

there is a vector:
std::vector notes;

notes get removed when they are done playing.

  
  
// pseudo code untested !!   
bool getIsNotePlaying (int chan, int instr, int note){  
 bool bPlaying = false;   
 for (int i = 0; i < notes.size(); i++){  
    if (notes[i].channel == chan && notes[i].interument == instr && notes[i].note == note){  
      bPlaying = true;  
    }  
  }  
  return bPlaying;  
}  
  

hope that helps.

take care
zach

Thanks zach,

I had to edit a couple things but I got that bool function working inside of midiPlayer.h.

So here’s the updated test code:

  
	if (gridaa > 25){          
        if (playeraa.getIsNotePlaying(0,1,60) == false){  
        playeraa.setChannel(0);  
        playeraa.setInstrument(1);  
        playeraa.noteOnForDuration(60,127,3.0f);}}  
	if (gridbc > 25){  
        if (playeraa.getIsNotePlaying(1,1,80) == false){  
        playeraa.setChannel(1);  
        playeraa.setInstrument(1);  
        playeraa.noteOnForDuration(80,127,3.0f);}}  
	if (griddd > 25){  
        if (playeraa.getIsNotePlaying(2,1,40) == false){         
        playeraa.setChannel(2);  
        playeraa.setInstrument(1);  
        playeraa.noteOnForDuration(40,127,3.0f);}}   

It works, but I’m going to run into some problems down the line since there’s only one instance of midiPlayer (playeraa). I tried to add other instances (playerbc, player dd, etc) but the app crashed when trying to setup the midi ports. [the error said there was only one available port]

I did think to put each trigger on a separate channel, and that works fine so later down the line i can use a random int for the note. but with only 15 channels (channel 10 being percussion), i’ll fall one short. I could use channel 10, but I’m not sure how to control the duration.

why do you need to have them on different channels ?

does this :

  
  
   if (gridaa > 25){         
        if (playeraa.getIsNotePlaying(0,1,60) == false){  
        playeraa.setChannel(0);  
        playeraa.setInstrument(1);  
        playeraa.noteOnForDuration(60,127,3.0f);}}  
   if (gridbc > 25){  
        if (playeraa.getIsNotePlaying(0,1,80) == false){  
        playeraa.setChannel(0);  
        playeraa.setInstrument(1);  
        playeraa.noteOnForDuration(80,127,3.0f);}}  
   if (griddd > 25){  
        if (playeraa.getIsNotePlaying(0,1,40) == false){         
        playeraa.setChannel(0);  
        playeraa.setInstrument(1);  
        playeraa.noteOnForDuration(40,127,3.0f);}}  
  

not work?? I think it should…

-zach

It definitely works, but I was just thinking that if rather than having the same note over and over (60, 80, 40) i could replace the [int note] with a random generator. in which case the If code would end up something like:

if playeraa.getIsNotePlaying(0,1,(random int))

so my if statements would all register true at the same time. I figured since the instruments would all be the same, all that left was the channel.

Am I overlooking a simple function? i have a bad habit of making things way too complicated.

I don’t think you need the channel, but you need to know the “id” of the note you turned on

for example:

int myNewNote = noteOnForDuration(int note, int volume, float duration);

myNewNote now has an int which is an internal id, unique for each played note (ie, first note = 1, second note = 2, third note you play = 3, etc).

now, you need to know if that particular note is playing, so you will need to write something like:

  
  
bool getIsNotePlaying (int id){  
 bool bPlaying = false;  
 for (int i = 0; i < notes.size(); i++){  
    if (notes[i].id == id){  
      bPlaying = true;  
    }  
  }  
  return bPlaying;  
}   
  

then you could call the getIsPlaying on that id you got back. you will need a variable to store that info.

like this:
getIsNotePlaying (myNewNote );

hope that helps - I definitely think you don’t need multiple channels for this.

take care!
zach

dang, Zach. Pro.

You should get paid for this.

Thanks for everything!