ofxMidi updates


#61

*Woops. Sorry for the double post.*


#62

Howdy again,

I’ve now created projects files on Win and Linux. It’s working fine on Win7 and Ubuntu 11.04.

Check it out in my develop branch:

https://github.com/danomatika/ofxMidi/tree/develop

I haven’t heard anything from anyone … can someone please test and/or provide some feedback on the api?


#63

i’ve tried in windows Vista with VisulStudio2010, but with no luck, i receive this errors in all 2 examples and debug or release versions:

1>------ Inizio compilazione: Progetto: openframeworksLib, Configurazione: Release Win32 ------
1> openframeworksLib.vcxproj -> C:\OF007\openFrameworks\libs\openFrameworksCompiled\project\vs2010…\lib\vs2010\openframeworksLib.lib
2>------ Inizio compilazione: Progetto: OutputExample, Configurazione: Release Win32 ------
2> ofxMidiIn.cpp
2>c1xx : fatal error C1083: Impossibile aprire il file origine ‘…\src\ofxMidiIn.cpp’: No such file or directory
2> ofxMidiMessage.cpp
2>c1xx : fatal error C1083: Impossibile aprire il file origine ‘…\src\ofxMidiMessage.cpp’: No such file or directory
2> ofxMidiOut.cpp
2>c1xx : fatal error C1083: Impossibile aprire il file origine ‘…\src\ofxMidiOut.cpp’: No such file or directory
2> RtMidi.cpp
2>c1xx : fatal error C1083: Impossibile aprire il file origine ‘…\src\rtmidi\RtMidi.cpp’: No such file or directory
2> main.cpp
2> testApp.cpp
2> Generazione del codice in corso…
========== Compilazione: 1 completate, 1 non riuscite, 0 aggiornate, 0 ignorate ==========

it’s strange because all the include directives should be fine, what could be?
the addon is in the folder addons with name ofxMidi, and the examples are in the \apps\addonsExamples.


#64

It’s simple. The files were added to the project in the addons/ofxMidi fodler so the paths are relative to that folder. Try removing all the sources and readding them. That should add them with the …/…/…/addons/ofxMidi path which will work in both places.

I can fix this soon. Also, can someone check if the Win Codeblocks project has this problem.


#65

It’s simple. The files were added to the project in the addons/ofxMidi fodler so the paths are relative to that folder. Try removing all the sources and readding them. That should add them with the …/…/…/addons/ofxMidi path which will work in both places.

I can fix this soon. Also, can someone check if the Win Codeblocks project has this problem.

yes , i suppose this. I ve imported again the addons in the tree of the Explorer solution pointing where my files are located and now the solutions compile fine. From the test side it seems that the “current program” don’t work very fine. I have to test with my Focusrite PRO 24 now i’m testing with the notebook integrated audio card.

p.s I haven’t codeblocks in windows … but i can try in Ubuntu 11.04 .
best regards


#66

Well ofxMidi itself dosen’t make any sound. If you run the output example and open port 0 on WIndows it should connect to the Windows General Midi Software synth. Pressing the keys plays notes and you can use the mouse to change pitch bend and pan.

As the readme says, you’ll need to use an app that can create virtual midi ports on Windows in order to connect software together. I used loopMIDI and tested with PureData using both examples.


#67

If you run the output example and open port 0 on WIndows it should connect to the Windows General Midi Software synth

yes, i’ve done this . Perhaps I have not explained well, I meant to sendProgramChange programs. if I change with key up or down does not seem to change the instruments but maybe it is a problem of my sound card and windows. Sure I can try as you said with PureData and midi loop (I have midi yoke). I’ll sapere.Thanks for the answer!


#68

[quote=“kalwalt, post:67, topic:2435”]
Perhaps I have not explained well, I meant to sendProgramChange programs. if I change with key up or down does not seem to change glistrumenti but maybe is a problem of my sound card and windows.[/quote]

Hmm, the program change worked for me on Win 7 with the Microsoft GM Synth.


#69

Also, there is PD patch for testing in ofxMidi/res. Sysex in/out dosen’t work since the [midiin]/[midiout] objects are somewhat broken on Windows.


#70

ofxMidi in VS with puredata with your patch works good for me …!


#71

Ok all. I fixed the relative path issues for all project files. You should be abel to copy an example folder into apps/myApps and everything should work.


#72

Hi danomatika!
I am trying the last develop branch.

I wanted to know how I could manage separately events from different devices’ midiIn?

I have a clock arriving from one device (software) and a 2nd device I am using (input/output).

  
  
ofxMidiIn midiClock;  
midiClock.openPort("Maschine Virtual Output");  
midiClock.ignoreTypes(false, false, true);  
midiClock.addListener(this);  
  
midiIn.openPort("Maschine Controller MIDI input port 0");  
midiIn.ignoreTypes(true, true, false);  
midiIn.addListener(this);  
  
midiOut.listPorts();  
midiOut.openPort("Maschine Controller MIDI output port 0");  
  

I wish I could have midiClock’s events going to one testApp::newMidiClockMessage and midiIn’s events going to
testApp:newMidiMessage.

Unfortunately. I have no experience with events and I am a bit lost.

I tried the following with no success:

  
  
midiClock.addListener(midiClock.manageNewMessage, this, &testApp::newMidiClockMessage);  
midiIn.addListener(midiIn.manageNewMessage, this, &testApp::newMidiMessage);  
  

By the way, as at the present time I am receiving all the events to the same function,
I made a switch based on messages’ status:

  
  
void testApp::newMidiMessage(ofxMidiMessage& midi_msg) {  
       
    //    switch((MidiStatus)midi_msg.status)  
    switch(midi_msg.status)  
    {           
        case MIDI_TIME_CLOCK:  
        case MIDI_CONTINUE:  
        case MIDI_STOP:   
        case MIDI_SONG_POS_POINTER:  
        default: //None of the above SYSEX messages  
    }  
  

To make it working I had to edit ofxMidiIn.cpp (cf. my pull request #14 https://github.com/chrisoshea/ofxMidi/pull/14 ).


#73

There are two ways to do this:

1 receive all messages to a single function and check the status or portNum/portName to forward it to another function
2 create a class for each midi device you are talking to in order to separate the message handling code

You can do option 1 by checking which port the message came from in the main event function, then pass that along to your functions:

  
  
  
// .h  
void newMidiClockMessage(ofxMidiMessage& midi_msg);  
  
// .cpp  
  
void testApp::newMidiMessage(ofxMidiMessage& midi_msg) {  
       
    if(midi_msg.portNum == midiClock.getPort())           
        newMidiClockMessage(midi_msg);  
    }  
    else {  
        // handle regular midi messages  
    }  
}  
  
void testApp::newMidiClockMessage(ofxMidiMessage& midi_msg) {  
  
    switch(midi_msg.status)  
    {           
        case MIDI_TIME_CLOCK:  
            // do clock stuff  
            break;  
        case MIDI_CONTINUE:  
        case MIDI_STOP:   
        case MIDI_SONG_POS_POINTER:  
        default: //None of the above SYSEX messages  
    }  
}  
  

You can do option 2 by creating 2 classes, 1 for the clock and 1 for the Maschine. It’s trickier to send changes to the testApp, but separates the code in a more manageable way.

  
  
  
// .h  
  
class MidiClock : public ofxMidiListener {  
public:  
      
    MidiClock() {  
        input.addListener(this);  
    }  
  
    void newMidiMessage(ofxMidiMessage& msg);  
  
    ofxMidiIn input;  
};  
  
class Maschine : public ofxMidiListener {  
public:  
  
    Maschine() {  
        input.addListener(this);  
    }  
      
    void newMidiMessage(ofxMidiMessage& msg);  
  
    ofxMidiIn input;  
    ofxMidi output;  
};  
  
class testApp : public ofBaseApp {  
    ...  
  
    MidiClock midiClock;  
    Maschine maschine;  
  
    ...  
};  
  
// .cpp  
  
// midi classes  
  
void MidiClock::newMidiMessage(ofxMidiMessage& msg) {  
   // handle midi clock messages  
}  
  
void Maschine::newMidiMessage(ofxMidiMessage& msg) {  
   // handle regular midi messages  
}  
  
// testApp class  
void testApp::setup() {  
  
    midiClock.input.openPort("Maschine Virtual Output");     
    midiClock.input.ignoreTypes(false, false, true);      
    
    maschine.input.openPort("Maschine Controller MIDI input port 0");    
    maschine.input.ignoreTypes(true, true, false);    
    
    maschine.listPorts();    
    maschine.openPort("Maschine Controller MIDI output port 0");   
}  
  

That won’t work as testApp inherits the ofxMidiListener class and ofxMidiIn only sends messages to the newMidiMessage function. It dosen’t know about your newMidiClockMessage function.

Thanks.


#74

danomatika!
Thank you so much for your great reply!!

EDIT: Really made my day!!!


#75

iOS updates … I have midi working on iOS in an OF app. I can send and receive midi between my laptop and iPad 2 via usb midi *and* OSX network midi. The next step is to work this into ofxMidi itself. Stay tuned.


#76

Very cool danomatika. Have you added any virtual midi port functions to it? I’ve been trying to figure this part out. I can post some resources later.


#77

Looks like it works:

http://www.youtube.com/watch?v=pSpIHymwX9I

I’d need to add that functionality to PGMidi, probably using the RtAudio sources as a guide. I’m more interested in getting basic functionality working first since I don’t really have a need for virtual ports on iOS.


#78

Yeah understood, getting the basic network MIDI going first is best. The network midi will still let you do app-to-app MIDI. The virtual ports thing lets you actually pick and choose what ports (apps) to send to. Not as important of course.

This is one source for virtual midi ports: https://www.onereddog.com.au/2011/04/08/coremidi-networking-setup/

Another one using PGMidi, but it doesn’t include the functions to turn on/off virtual ports and I wasn’t able to figure it out: http://resources.atastypixel.com/PGMidi+TPAdditions.zip

Is your code committed? I couldn’t find it.


#79

It’s not online as it’s not worked into ofxMidi yet. I was only playing with PGMidi to understand how to work with it.


#80

Ok, sounds good. BTW, in case you hadn’t seen this - this is a good 3 part series on iOS MIDI: http://syntheticbits.com/blog/?p=1213

Based on that, I did add one function to PGMidi which lets you set the time to send:

  
- (void) sendQueuedMidi:(const UInt8*)bytes size:(UInt32)size atTime:(UInt64)time  
{  
    assert(size < 65536);  
    Byte packetBuffer[size+100];  
    MIDIPacketList *packetList = (MIDIPacketList*)packetBuffer;  
    MIDIPacket     *packet     = MIDIPacketListInit(packetList);  
    packet = MIDIPacketListAdd(packetList, sizeof(packetBuffer), packet, time, size, bytes);  
      
    [self sendPacketList:packetList];  
}  

That way you can do something like this and keep things in time by sending them at a time in the future:

  
        
 uint64_t onTime = mach_absolute_time() + midiLatency; //send with a timestamp of curtime + latency  
 uint64_t offTime = onTime + noteLength;   // send note off from onTime + noteLength  
          
 [midi sendQueuedMidi:noteOn size:sizeof(noteOn) atTime:onTime];  
 [midi sendQueuedMidi:noteOff size:sizeof(noteOff) atTime:offTime];