Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 25 of 58

Thread: Virtual Midi Cables - 8 ports OSX and PC

Threaded View

  1. #1
    Junior Member
    Join Date
    Sep 2015
    Location
    London
    Posts
    8

    Virtual Midi Cables - 8 ports OSX and PC

    I've managed to get 8 virtual midi cables working over USB for Teensy 3.2/3.6 on OSX and Windows 10, don't have Linux but it should work (famous last words)...

    This thread helped start the ball rolling : thread

    Hopefully the way I've done it is fairly clean (the midi send/receive commands haven't changed ) and useful to some people.

    The files that need to be changed (OSX locations) are:

    /Applications/Arduino.app/Contents/Java/hardware/teensy/avr/cores/teensy3/usb_desc.c
    /Applications/Arduino.app/Contents/Java/hardware/teensy/avr/cores/teensy3/usb_midi.c
    /Applications/Arduino.app/Contents/Java/hardware/teensy/avr/cores/teensy3/usb_midi.h

    Installation:

    1/ Make a copy of these files: usb_desc.c , usb_midi.c , usb_midi.h

    On MacOs in finder goto Applications/Arduino right click show Package contents then

    /Contents/Java/hardware/teensy/avr/cores/teensy3/

    2/ replace them with the three files attached.

    Usage:

    Before sending set the virtual midi cable using usbMIDI.setMidiCable(cable). Note there is no bounds checking and cable needs to be between 0 and 7.

    int cable = 7; // cable can be from 0 to 7
    int note = 45;

    usbMIDI.setMidiCable(cable);
    usbMIDI.sendNoteOn(note,0x7F,1); // note , vel, channel

    Receiving:

    It up to you to check what virtual midi cable received the midi data and decide what to do with it...

    Serial.print("Cable, cb=");
    int cable = usbMIDI.getCable();
    Serial.print(cable, DEC);

    Example code

    The example below sends 50 note on's and 50 note off's as fast as possible when a button is pressed.
    It also writes to the serial terminal when a midi message (note on, off, pitch bend, control change etc) is received.


    Code:
    #include <Bounce.h>
    
    Bounce button2 = Bounce(2, 55); 
    
    
    void setup() {
      Serial.begin(115200);
      delay(300);
      usbMIDI.setHandleNoteOff (OnNoteOff);
      usbMIDI.setHandleNoteOn (OnNoteOn);
      usbMIDI.setHandleVelocityChange(OnVelocityChange);
      usbMIDI.setHandleControlChange(OnControlChange);
      usbMIDI.setHandleProgramChange(OnProgramChange);
      usbMIDI.setHandleAfterTouch(OnAfterTouch);
      usbMIDI.setHandlePitchChange(OnPitchChange);
       pinMode(2, INPUT_PULLUP);
    }
    
    void loop() { 
      usbMIDI.read(); // USB MIDI receive
    
      button2.update();
      int value = button2.read();
    
      if(value == LOW){
        delay(50);
        send_notes();
        delay(250);
      }
        
    }
    
    
    
    void send_notes(){
      
      int cable = 0;
      int i = 0;
     
      
         for (i=0;i<50;i++){
            for ( cable = 0; cable < 8; cable++){ 
                usbMIDI.setMidiCable(cable);
                usbMIDI.sendNoteOn(i,0x7F,1);  // note , vel, channel 
            }
           }
    
      
            for (i=0;i<50;i++){ 
              for ( cable = 0; cable < 8; cable++){ 
                  usbMIDI.setMidiCable(cable);
                  usbMIDI.sendNoteOff(i,0x00,1);  // note , vel, channel
            }
       }
      usbMIDI.send_now();
    }
    
    
    
    void OnNoteOn( byte channel, byte note, byte velocity) {
      
      Serial.print("Cable, cb=");
      int cable = usbMIDI.getCable();
      Serial.print(cable, DEC);
      Serial.print("Note On, ch=");
      Serial.print(channel, DEC);
      Serial.print(", note=");
      Serial.print(note, DEC);
      Serial.print(", velocity=");
      Serial.print(velocity, DEC);
      Serial.println();
    }
    
    void OnNoteOff(byte channel, byte note, byte velocity) {
      Serial.print("Cable, cb=");
      Serial.print(usbMIDI.getCable(), DEC);
      Serial.print("Note Off, ch=");
      Serial.print(channel, DEC);
      Serial.print(", note=");
      Serial.print(note, DEC);
      Serial.print(", velocity=");
      Serial.print(velocity, DEC);
      Serial.println();
    }
    
    void OnVelocityChange(byte channel, byte note, byte velocity) {
    
    
      Serial.print("Cable, cb=");
      Serial.print(usbMIDI.getCable(), DEC);
      Serial.print("Velocity Change, ch=");
      Serial.print(channel, DEC);
      Serial.print(", note=");
      Serial.print(note, DEC);
      Serial.print(", velocity=");
      Serial.print(velocity, DEC);
      Serial.println();
    }
    
    void OnControlChange(byte channel, byte control, byte value) {
      Serial.print("Cable, cb=");
      Serial.print(usbMIDI.getCable(), DEC);
      Serial.print("Control Change, ch=");
      Serial.print(channel, DEC);
      Serial.print(", control=");
      Serial.print(control, DEC);
      Serial.print(", value=");
      Serial.print(value, DEC);
      Serial.println();
    }
    
    void OnProgramChange(byte channel, byte program) {
      Serial.print("Cable, cb=");
      Serial.print(usbMIDI.getCable(), DEC);
      Serial.print("Program Change, ch=");
      Serial.print(channel, DEC);
      Serial.print(", program=");
      Serial.print(program, DEC);
      Serial.println();
    }
    
    void OnAfterTouch(byte channel, byte pressure) {
      
      Serial.print("Cable, cb=");
      Serial.print(usbMIDI.getCable(), DEC);
      Serial.print("After Touch, ch=");
      Serial.print(channel, DEC);
      Serial.print(", pressure=");
      Serial.print(pressure, DEC);
      Serial.println();
    }
    
    void OnPitchChange( byte channel, int pitch) {
      uint8_t data1;
      uint8_t data2;
      uint8_t type;
      uint8_t ch;
      data1 = usbMIDI.getData1();
      data2 = usbMIDI.getData1();
      type = usbMIDI.getType();
      ch = usbMIDI.getChannel();
      Serial.print("Cable, cb=");
      Serial.print(usbMIDI.getCable(), DEC);
      
      Serial.print("Data1 = ");
      Serial.print(data1, DEC);
      Serial.print("Data2 = ");
      Serial.print(data2, DEC);
      Serial.print("Type = ");
      Serial.print(type, DEC);
      Serial.print("Channel = ");
      Serial.print(ch, DEC);
      
     
      Serial.print("Pitch Change, ch=");
      Serial.print(channel, DEC);
      Serial.print(", pitch=");
      Serial.print(pitch, DEC);
      Serial.println();
    }
    The 50 notes sent across eight ports/virtual midi cables (400 in total) were received by the software (Reaper64 in this case) in 3ms - not too shabby.

    Preliminary Testing

    - tested Arduino 1.6.12 and Teensyduino 1.32(?) and
    Arduino 1.8.0 and Teensyduino 1.34

    - left running for a couple of hours pumping midi Note on/off's across 8 ports to Ableton Live no problems.

    - works using USB profiles: Midi / Midi + Serial and Midi + Serial + Audio (audio not tested but shows up in device manager and in OSX and PC)

    - works on T3.2, T3.6 (fairly cursory - mainly 3.2)

    The need for more than one midi port/cable:

    If you are trying to implement some kinds to midi automation e.g. HUI/Mackie etc then you need more than one port. One port limits you to 8 channels. Frequently you need to be able to control up to 32 channels.

    ---

    Hope I haven't missed something...
    Attached Files Attached Files
    Last edited by BuzzBang; 01-05-2017 at 08:08 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •