2

I'm trying to write a C++ app using RtMidi to send control signals via my Tascam FireOne MIDI Controller to Ableton Live. So far, I have it successfully sending Note On + Off Signals, Volume Up + Down Signals, etc. via my MIDI Controller to my digital piano using 'a' and 's' keypresses.

// midiout.cpp

#include <iostream>
using namespace std;

#include <signal.h>
#include <windows.h>
#include <conio.h>
#include "RtMidi.h"

int main()
{
    std::vector<unsigned char> message;

    int i, keyPress;
    int nPorts;
    char input;

    RtMidiOut *midiout = 0;

    // midiOUT
    try {
        midiout = new RtMidiOut();

        // Check available ports.
        nPorts = midiout->getPortCount();
        if ( nPorts == 0 ) {
            cout << "No ports available!" << endl;
            goto cleanup;
        }

        // List Available Ports
        cout << "\nPort Count = " << nPorts << endl;
        cout << "Available Output Ports\n-----------------------------\n";
        for( i=0; i<nPorts; i++ )
        {
            try {
                cout << "  Output Port Number " << i << " : " << midiout->getPortName(i) << endl;
            }
            catch(RtError &error) {
                error.printMessage();
                goto cleanup;
            }
        }

        cout << "\nSelect an output port number :" << endl;
        cin >> keyPress;

        while( keyPress < 0 || keyPress >= midiout->getPortCount() )
        {
            cout << "\nIncorrect selection. Please try again :" << endl;
            cin >> keyPress;
        }

        // Open Selected Port
        midiout->openPort( keyPress );

        keyPress = NULL;

        bool done = false;

        cout << "Press a key to generate a message, press 'Esc' to exit" << endl;

        while(!done)
        {
            keyPress = _getch();
            input = keyPress;
            cout << input << " is: " << keyPress << endl;

            switch ( keyPress )
            {
                case 97 : 
                // Process for keypress = a
                    // Note On: 144, 60, 90
                    message.push_back( 144 );
                    message.push_back( 60 );
                    message.push_back( 90 );
                    midiout->sendMessage( &message );
                    break;
                case 115 : 
                    // Process for keypress = s
                    // Note Off: 128, 60, 90
                    message.push_back( 128 );
                    message.push_back( 60 );
                    message.push_back( 90 );
                    midiout->sendMessage( &message );
                    break;
                case 27 : 
                    // Process for keypress = esc
                    done = true;
                    break;
            }
            message.clear();
            keyPress = NULL;
        }
    }
    catch(RtError &error) {
        error.printMessage();
        exit( EXIT_FAILURE );
    }

    cleanup:
        delete midiout;

  return 0;
}

I tried sending control signals in the same manner as above but this time with control values in the message bytes in place of the note-on or note-off values.

When ableton live is running, I press a key to send a signal but the app locks up and doesn't return to the start of the while loop to receive input from the next keypress.

edit: I've just noticed that even the above code (which usually runs fine) freezes when ableton live is running and I press a key.

further edit: I downloaded a really neat app called MIDI Monitor, which can monitor MIDI data being transferred: http://obds.free.fr/midimon -- my MIDI controller device has two ports -> one for MIDI and one for control. When I'm monitoring control, I can send midi signals and vice versa. However, if, for example, I'm monitoring control and I try to send some CC type data the program locks. Could this be a device driver problem? –

Does anyone know what is going wrong here?

pje
  • 21,801
  • 10
  • 54
  • 70
kylestephens
  • 326
  • 5
  • 15

2 Answers2

1

Just one comment - your exception handling is a little weird.

I'd wrap the whole code (initialization and all) in a try/catch(RtError &err) block, and lose most of the other try/catch blocks.

In particular, I don't know what your catch(char * str) stuff will achieve, and you have no catch at all if openPort() throws.

Roddy
  • 66,617
  • 42
  • 165
  • 277
0

First of all, try sending a different CC and mapping it to some arbitrary control in Ableton, just to see if it's working. The volume controls you are trying to alter behave slightly differently than regular CC's. Specifically, you should check out the MIDI organization's recommended practice for incrementing/decrementing controllers (note that 0x60 == 96), namely when they write:

This parameter uses MSB and LSB separately, with MSB adjusting sensitivity in semitones and LSB adjusting sensitivity in cents. Some manufacturers may even ignore adjustments to the LSB.

Nik Reiman
  • 39,067
  • 29
  • 104
  • 160
  • I downloaded a really neat app called MIDI Monitor, which can monitor MIDI data being transferred: http://obds.free.fr/midimon/ Now heres the kicker -- my MIDI controller device has two ports -> one for MIDI and one for control. When I'm monitoring control, I can send midi signals and vice versa but if, for example, I'm monitoring control and I try to send some CC type data, the program locks. Could this be a device driver problem? – kylestephens May 24 '11 at 15:15
  • @kosomonova The two MIDI ports probably correspond to the physical MIDI port on the back of the device (to which you would connect a keyboard or something) and the device itself, which also is sending/receiving MIDI. You should see the two show up as different entries in MIDI Monitor's output window. You should probably have different rtmidi output ports for each one. – Nik Reiman May 24 '11 at 15:34