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

Thread: MIDI out from DAW

  1. #1
    Junior Member
    Join Date
    Oct 2017
    Posts
    7

    MIDI out from DAW

    Hey everyone,

    I get the feeling this might be an easy one, but haven't been able to figure it out myself :/

    I want to get MIDI notes from Ableton and send them through my teensy2, which I use with a MIDI connector out.
    This way I can sequence my hardware using Ableton.

    I've managed to send notes with the code I have found :
    "#include <MIDI.h>

    const int channel = 10;

    void setup() {
    MIDI.begin();
    }

    void loop() {
    int note;
    for (note=40; note <= 60; note++) {
    MIDI.sendNoteOn(note, 100, channel);
    delay(200);
    MIDI.sendNoteOff(note, 100, channel);
    }
    delay(200);
    }"


    But I'd like to be able to chose which note and channel I am sending to directly on the DAW, not from the code I'm uploading.

    Any way I can do that ?

    Many thanks

  2. #2
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Isle in the Salish Sea
    Posts
    1,326
    Assuming you only want to pass note data then you just need to merge the usbMIDI.read and MIDI.send demo code into a single sketch where the usbMIDI.read() data is passed to MIDI.sendNote commands.

    I'm not going to cover the 'setHandle' method of reading usbMIDI; please read that section carefully!

    (See "Receiving Messages with Read & Callback Functions" section of https://www.pjrc.com/teensy/td_midi.html)

    Here is the usbMIDI.read example code with the stuff we won't need in red (which has to do with blinking the LED):
    Code:
    // USB MIDI receive example, Note on/off -> LED on/off
    // contributed by Alessandro Fasan
    
    int ledPin = 13;
    
    void OnNoteOn(byte channel, byte note, byte velocity)
    {
      digitalWrite(ledPin, HIGH);
    }
    
    void OnNoteOff(byte channel, byte note, byte velocity)
    {
      digitalWrite(ledPin, LOW);
    }
    
    void setup()
    {
      pinMode(ledPin, OUTPUT);
      usbMIDI.setHandleNoteOff(OnNoteOff);
      usbMIDI.setHandleNoteOn(OnNoteOn) ;
      digitalWrite(ledPin, HIGH);
      delay(1000);
      digitalWrite(ledPin, LOW);
      delay(1000);
    }
    
    void loop()
    {
      usbMIDI.read();
    }
    We just need to replace the digitalWrite() lines that were setting the LED to MIDI.send messages (and add an #includes MIDI.h so the library is there for us)

    And here's the MIDI.send example code (with the stuff we will need to copy and adjust in green)
    Code:
    #include <MIDI.h>
    
    const int channel= 1;
    
    void setup() {
      MIDI.begin();
    }
    
    void loop() {
      int note;
      for (note=10; note <= 127; note++) {
        MIDI.sendNoteOn(note, 100, channel);
        delay(200);
        MIDI.sendNoteOff(note, 100, channel);
      }
      delay(2000);
    }
    So now we can pop these lines into the first code.
    After that it's just a matter of replacing the arbitrary velocity values with those the callback functions extract from the data handle from the setup() code.
    The channel and note variable names were the same in both examples so can be left as is.
    Doing so gives me this UNTESTED code:
    Code:
    #include <MIDI.h>
    
    void OnNoteOn(byte channel, byte note, byte velocity)
    {
      MIDI.sendNoteOn(note, velocity, channel);
    }
    
    void OnNoteOff(byte channel, byte note, byte velocity)
    {
      MIDI.sendNoteOff(note, velocity, channel);
    }
    
    void setup()
    {
      MIDI.begin();
      usbMIDI.setHandleNoteOff(OnNoteOff);
      usbMIDI.setHandleNoteOn(OnNoteOn) ;
    }
    
    void loop()
    {
      usbMIDI.read();
    }
    A delay() and Serial.print() instructions could be added to ensure the code is working before unleashing it on your MIDI hardware.
    Last edited by oddson; 10-04-2017 at 06:34 PM.

  3. #3
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Isle in the Salish Sea
    Posts
    1,326
    ...oh... I think the newest MIDI. library may have an extra line of initialization code not in the current documentation but I've not updated

    MIDI_CREATE_DEFAULT_INSTANCE()

    https://forum.pjrc.com/threads/46388...E()-not-needed

  4. #4
    Member Revalogics's Avatar
    Join Date
    Dec 2016
    Location
    Philippines
    Posts
    78
    Hi, I also used a Teensy 3.6 before to send a torrent of MIDI data from my laptop to my keyboard, particularly black MIDIs , to test how well my keyboard responds to a total of about more than 1 million notes.
    I also used a similar approach and the code oddson posted will work.

    Here's my code as a reference (note it's quite obsolete due to MIDI library update; I haven't tested it again)
    Code:
    #include <LiquidCrystalFast.h>
    LiquidCrystalFast MC2004(2, 3, 4, 5, 6, 7, 8);
    #include <MIDI.h>
    
    #include <Audio.h>
    AudioInputI2S       INPUT1;
    AudioAnalyzePeak    METER_LEFT;
    AudioAnalyzePeak    METER_RIGHT;
    AudioSynthWaveform  BEEP;
    AudioMixer4         LEFTMIX;
    AudioMixer4         RIGHTMIX;
    AudioOutputI2S      OUTPUT1;
    AudioOutputUSB      OUTPUT2;
    AudioConnection     A00(INPUT1, 0, METER_LEFT, 0);
    AudioConnection     A01(INPUT1, 1, METER_RIGHT, 0);
    AudioConnection     A02(INPUT1, 0, LEFTMIX, 0);
    AudioConnection     A03(INPUT1, 1, RIGHTMIX, 0);
    AudioConnection     A04(BEEP, 0, LEFTMIX, 1);
    AudioConnection     A05(BEEP, 0, RIGHTMIX, 1);
    AudioConnection     A06(LEFTMIX, 0, OUTPUT1, 0);
    AudioConnection     A07(LEFTMIX, 0, OUTPUT2, 0);
    AudioConnection     A08(RIGHTMIX, 0, OUTPUT1, 1);
    AudioConnection     A09(RIGHTMIX, 0, OUTPUT2, 1);
    
    elapsedMillis LCDt;
    const float scale00dBV = 1;
    const float scale03dBV = 0.707945784;
    const float scale06dBV = 0.501187234;
    const float scale09dBV = 0.354813389;
    const float scale12dBV = 0.251188643;
    const float scale15dBV = 0.177827941;
    const float scale18dBV = 0.125892541;
    const float scale21dBV = 0.089125094;
    const float scale24dBV = 0.063095734;
    const float scale27dBV = 0.044668359;
    const float scale30dBV = 0.031622777;
    const float scale33dBV = 0.022387211;
    const float scale36dBV = 0.015848932;
    const float scale39dBV = 0.011220185;
    const float scale42dBV = 0.007943282;
    const float scale45dBV = 0.005623413;
    const float scale48dBV = 0.003981072;
    const float scale51dBV = 0.002818383;
    const float scale54dBV = 0.001995262;
    const float scale57dBV = 0.001412538;
    const float scale60dBV = 0.001000000;
    float peakL = 1, peakR = 1, raw1, raw2;
    byte metervalL, metervalR, r1, r2;
    
    void setup() {
      MC2004.begin(20, 4);
      MC2004.clear();
      MC2004.print("DEO POGI ELECTRONICS");
      MC2004.print("Audio ADC/DAC to USB");
      MIDI.begin(MIDI_CHANNEL_OMNI);
      usbMIDI.setHandleNoteOff(OnNoteOff);
      usbMIDI.setHandleNoteOn(OnNoteOn);
      usbMIDI.setHandleControlChange(OnControlChange);
      usbMIDI.setHandleProgramChange(OnProgramChange);
      usbMIDI.setHandlePitchChange(OnPitchChange);
      AudioMemory(128);
      BEEP.begin(0, 1000, WAVEFORM_SQUARE);
    }
    void loop() {
      if(METER_LEFT.available()) raw1 = METER_LEFT.read();
      if(METER_RIGHT.available()) raw2 = METER_RIGHT.read();
      if(peakL < raw1) peakL = raw1;
      if(peakR < raw2) peakR = raw2;
      if(peakL >= scale00dBV) metervalL = 20;
      if(peakR >= scale00dBV) metervalR = 20;
      if(peakL < scale00dBV && peakL >= scale03dBV) metervalL = 19;
      if(peakR < scale00dBV && peakR >= scale03dBV) metervalR = 19;
      if(peakL < scale03dBV && peakL >= scale06dBV) metervalL = 18;
      if(peakR < scale03dBV && peakR >= scale06dBV) metervalR = 18;
      if(peakL < scale06dBV && peakL >= scale09dBV) metervalL = 17;
      if(peakR < scale06dBV && peakR >= scale09dBV) metervalR = 17;
      if(peakL < scale09dBV && peakL >= scale12dBV) metervalL = 16;
      if(peakR < scale09dBV && peakR >= scale12dBV) metervalR = 16;
      if(peakL < scale12dBV && peakL >= scale15dBV) metervalL = 15;
      if(peakR < scale12dBV && peakR >= scale15dBV) metervalR = 15;
      if(peakL < scale15dBV && peakL >= scale18dBV) metervalL = 14;
      if(peakR < scale15dBV && peakR >= scale18dBV) metervalR = 14;
      if(peakL < scale18dBV && peakL >= scale21dBV) metervalL = 13;
      if(peakR < scale18dBV && peakR >= scale21dBV) metervalR = 13;
      if(peakL < scale21dBV && peakL >= scale24dBV) metervalL = 12;
      if(peakR < scale21dBV && peakR >= scale24dBV) metervalR = 12;
      if(peakL < scale24dBV && peakL >= scale27dBV) metervalL = 11;
      if(peakR < scale24dBV && peakR >= scale27dBV) metervalR = 11;
      if(peakL < scale27dBV && peakL >= scale30dBV) metervalL = 10;
      if(peakR < scale27dBV && peakR >= scale30dBV) metervalR = 10;
      if(peakL < scale30dBV && peakL >= scale33dBV) metervalL = 9;
      if(peakR < scale30dBV && peakR >= scale33dBV) metervalR = 9;
      if(peakL < scale33dBV && peakL >= scale36dBV) metervalL = 8;
      if(peakR < scale33dBV && peakR >= scale36dBV) metervalR = 8;
      if(peakL < scale36dBV && peakL >= scale39dBV) metervalL = 7;
      if(peakR < scale36dBV && peakR >= scale39dBV) metervalR = 7;
      if(peakL < scale39dBV && peakL >= scale42dBV) metervalL = 6;
      if(peakR < scale39dBV && peakR >= scale42dBV) metervalR = 6;
      if(peakL < scale42dBV && peakL >= scale45dBV) metervalL = 5;
      if(peakR < scale42dBV && peakR >= scale45dBV) metervalR = 5;
      if(peakL < scale45dBV && peakL >= scale48dBV) metervalL = 4;
      if(peakR < scale45dBV && peakR >= scale48dBV) metervalR = 4;
      if(peakL < scale48dBV && peakL >= scale51dBV) metervalL = 3;
      if(peakR < scale48dBV && peakR >= scale51dBV) metervalR = 3;
      if(peakL < scale51dBV && peakL >= scale54dBV) metervalL = 2;
      if(peakR < scale51dBV && peakR >= scale54dBV) metervalR = 2;
      if(peakL < scale54dBV && peakL >= scale57dBV) metervalL = 1;
      if(peakR < scale54dBV && peakR >= scale57dBV) metervalR = 1;
      if(peakL < scale57dBV && peakL >= scale60dBV) metervalL = 0;
      if(peakR < scale57dBV && peakR >= scale60dBV) metervalR = 0;
      if(LCDt >= 50) {
        LCDt = 0;
        MC2004.setCursor(0, 2);
        r1 = 20 - metervalL;
        r2 = 20 - metervalR;
        for(byte a = metervalL; a > 0; a--) {
          MC2004.write(0xFF);
        }
        for(byte a = r1; a > 0; a--) {
          MC2004.write(0x20);
        }
        MC2004.setCursor(0, 3);
        for(byte a = metervalR; a > 0; a--) {
          MC2004.write(0xFF);
        }
        for(byte a = r2; a > 0; a--) {
          MC2004.write(0x20);
        }
        peakL *= scale03dBV;
        peakR *= scale03dBV;
      }
      if(MIDI.read()) {
        byte type = MIDI.getType();
        byte note, velocity, channel, control, value, program, d1, d2;
        int d3, pitch;
        switch(type) {
          case NoteOff:
            note = MIDI.getData1();
            velocity = MIDI.getData2();
            channel = MIDI.getChannel();
            usbMIDI.sendNoteOff(note, velocity, channel);
          break;
          case NoteOn:
            note = MIDI.getData1();
            velocity = MIDI.getData2();
            channel = MIDI.getChannel();
            usbMIDI.sendNoteOn(note, velocity, channel);
          break;
          case ControlChange:
            control = MIDI.getData1();
            value = MIDI.getData2();
            channel = MIDI.getChannel();
            usbMIDI.sendControlChange(control, value, channel);
          break;
          case ProgramChange:
            program = MIDI.getData1();
            channel = MIDI.getChannel();
            usbMIDI.sendProgramChange(program, channel);
          break;
          case PitchBend:
            d1 = MIDI.getData1();
            d2 = MIDI.getData2();
            d3 = d2 << 9;
            pitch = (d3 >> 2) + d1;
            channel = MIDI.getChannel();
            usbMIDI.sendPitchBend(pitch, channel);
          break;
          default:
          break;
        }
      }
      usbMIDI.read();
      //noteCopier();
    }
    void OnNoteOff(byte channel, byte note, byte velocity) {
      MIDI.sendNoteOff(note, velocity, channel);
    }
    void OnNoteOn(byte channel, byte note, byte velocity) {
      MIDI.sendNoteOn(note, velocity, channel);
    }
    void OnControlChange(byte channel, byte control, byte value) {
      MIDI.sendControlChange(control, value, channel);
    }
    void OnProgramChange(byte channel, byte program) {
      MIDI.sendProgramChange(program, channel);
    }
    void OnPitchChange(byte channel, int pitch) {
      pitch += 8192;
      MIDI.sendPitchBend(pitch, channel);
    }
    void noteCopier() {
      while(!Serial);
      delay(1000);
      for(byte reps = 0; reps <= 10; reps++) {
        BEEP.amplitude(0.0625);
        delay(50);
        BEEP.amplitude(0);
        delay(50);
      }
      delay(1000);
      for(byte note = 36; note <= 96; note += 3) {
        MIDI.sendNoteOn(note, 127, 1);
        delay(9500);
        MIDI.sendNoteOff(note, 127, 1);
        delay(500);
        MIDI.sendNoteOn(note, 127, 1);
        delay(9500);
        MIDI.sendNoteOff(note, 127, 1);
        delay(500);
        MIDI.sendNoteOn(note, 127, 1);
        delay(9500);
        MIDI.sendNoteOff(note, 127, 1);
        delay(500);
        BEEP.amplitude(0.0625);
        delay(50);
        BEEP.amplitude(0);
        delay(500);
      }
      for(byte reps = 0; reps <= 10; reps++) {
        BEEP.amplitude(0.0625);
        delay(50);
        BEEP.amplitude(0);
        delay(50);
      }
      while(1);
    }

  5. #5
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Isle in the Salish Sea
    Posts
    1,326
    Code:
    #include <MIDI.h>
    
    MIDI_CREATE_DEFAULT_INSTANCE();
    
    void setup(){
    
      MIDI.begin(MIDI_CHANNEL_OMNI); // read all channels
      usbMIDI.setHandleNoteOff(OnNoteOff);
      usbMIDI.setHandleNoteOn(OnNoteOn) ;
    }
    
    void loop()
    {
      usbMIDI.read();
    }
    
    void OnNoteOn(byte channel, byte note, byte velocity)
    {
      MIDI.sendNoteOn(note, velocity, channel);
      serialNotePrint(true, note, velocity, channel);
    }
    
    void OnNoteOff(byte channel, byte note, byte velocity)
    {
      MIDI.sendNoteOff(note, velocity, channel);
      serialNotePrint(false, note, velocity, channel);
    }
    
    
    void serialNotePrint(boolean On, byte note, byte velocity, byte channel){  
      if (On){
        Serial.print("Note On, ch=");
      }else {
        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();
    }
    Here's code for the less ancient versions of the MIDI library where you have to initialize the type of MIDI connection you want to make.

    And I added a serialNotePrint() function to print to the data to the serial monitor so I can be fairly sure it works without having MIDI hardware set up.
    Last edited by oddson; 10-05-2017 at 05:26 AM.

  6. #6
    Junior Member
    Join Date
    Oct 2017
    Posts
    7
    Hey everyone ! Thanks a lot for helping me out on this

    It works perfectly, I've managed to sequence my drum machine using ableton !!

    I think I understand how the code works as well so it's great I've learned something haha

  7. #7
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Isle in the Salish Sea
    Posts
    1,326
    This only does note on/off.... you can extend to the other main types but sysex and realtime midi are tricky.
    I think I understand how the code works as well
    Most of the code is simple enough; it's understanding how 'setHandle...' commands make an object that is updated by the usbMIDI.read() command in the main loop.

    The alternative is to use getType and getData commands and a generic MIDI.send which would allow handling standard midi types with the same code... but type has to be extracted and bit shifted as the numbering of types is different in the two libraries.

Posting Permissions

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