tttapa / MIDI_controller

This is a library for creating a MIDI controller using an Arduino or Teensy board.
GNU General Public License v3.0
403 stars 70 forks source link

Multiple Interfces Usge #42

Closed NinjaPanas closed 6 years ago

NinjaPanas commented 6 years ago

I want to have an additional MIDI Connector besides MIDI USB. As I understand it, I need to add a line to the code: HardwareSerialMIDI_Interface (HardwareSerial & serial, unsigned long baud).

Could you add an example code of using an additional interface? I can not understand how to setup a pin for transmission. Also I can not understand where and with what syntax to interpose a line to connect two interfaces. I think it may be something like this: SoftwareSerial midiSerial(2, 3); but can't find.

tttapa commented 6 years ago

What board are you using?

You could try to do something like this:

#include <MIDI_Controller.h> // Include the library

class DualMIDI_Interface : public MIDI_Interface {
  public:
    DualMIDI_Interface(MIDI_Interface &midi1, MIDI_Interface &midi2)
     : midi1(midi1), midi2(midi2) {}
    void begin() {
      midi1.begin();
      midi2.begin();
    }
    bool refresh() {
      midi1.refresh();
      midi2.refresh();
    }
  protected:
    void sendImpl(uint8_t m, uint8_t c, uint8_t d1, uint8_t d2) {
      midi1.send(m, c, d1, d2);
      midi2.send(m, c, d1, d2);
    }
    void sendImpl(uint8_t m, uint8_t c, uint8_t d1) {
      midi1.send(m, c, d1);
      midi2.send(m, c, d1);
    }
  private:
    MIDI_Interface &midi1;
    MIDI_Interface &midi2;
};

SoftwareSerial softserial(2, 3);
SoftwarSerialMIDI_Interface softmidi(softserial, 31250); // Note: this is a typo in the library, I'll fix it on a next release
USBMIDI_Interface usbmidi;
DualMIDI_Interface dualmidi(softmidi, usbmidi);
NinjaPanas commented 6 years ago

Thank you very much. I'm using a Leonardo board.

tttapa commented 6 years ago

Then you don't have to use SoftwareSerial. Use HardwareSerial instead. SoftwareSerial is a huge waste of resources.

One thing I have noticed is that MIDIUSB has a timeout of 250 ms if the MIDI connection is closed on the PC side, causing the second output to lag as well. A solution would be to only send if the connection is open. However, the MIDIUSB library offers no such information. I have opened an issue on their GitHub.

NinjaPanas commented 6 years ago

I have no words. I acted as you ordered and it all worked like a Swiss watch. Here is the test code I tried:

#include <MIDI_Controller.h> // Include the library

class DualMIDI_Interface : public MIDI_Interface {
  public:
    DualMIDI_Interface(MIDI_Interface &midi1, MIDI_Interface &midi2)
     : midi1(midi1), midi2(midi2) {}
    void begin() {
      midi1.begin();
      midi2.begin();
    }
    bool refresh() {
      midi1.refresh();
      midi2.refresh();
    }
  protected:
    void sendImpl(uint8_t m, uint8_t c, uint8_t d1, uint8_t d2) {
      midi1.send(m, c, d1, d2);
      midi2.send(m, c, d1, d2);
    }
    void sendImpl(uint8_t m, uint8_t c, uint8_t d1) {
      midi1.send(m, c, d1);
      midi2.send(m, c, d1);
    }
  private:
    MIDI_Interface &midi1;
    MIDI_Interface &midi2;
};

SoftwareSerial softserial(0, 1);
SoftwarSerialMIDI_Interface softmidi(softserial, 31250); // Note: this is a typo in the library, I'll fix it on a next release
USBMIDI_Interface usbmidi;
DualMIDI_Interface dualmidi(softmidi, usbmidi);

const uint8_t velocity = 0b1111111; // Maximum velocity (0b1111111 = 0x7F = 127)
const uint8_t C4 = 60;              // Note number 60 is defined as middle C in the MIDI specification

// Create a new instance of the class 'Digital', called 'button', on pin 2, that sends MIDI messages with note 'C4' (60) on channel 1, with velocity 127
Digital button(A5, C4, 1, velocity);

// Create a new instance of the class 'Analog', called 'potentiometer', on pin A0, 
// that sends MIDI messages with controller 7 (channel volume) on channel 1
Analog potentiometer(A0, MIDI_CC::Channel_Volume, 1);

void setup() {}

void loop() {
  // Refresh the MIDI controller (check whether the potentiometer's input has changed since last time, if so, send the new value over MIDI)
  MIDI_Controller.refresh();
}

MIDI DIN Connector data wire to pin 1 (TX pin). Connect it with my Roland UA-FX sound card via MIDI cable and check it with MIDI-OX softwre. All work great!! MIDI messages comes from Leonardo MIDI device as well as from UA-FX device. Thank you very much! I would never do it myself.

Would not it be too cheeky to ask you how to properly use the Hardwar Serial function for a Leonardo card in this case?

tttapa commented 6 years ago
HardwareSerialMIDI_Interface hwmidi(Serial1, 31250);
USBMIDI_Interface usbmidi;
DualMIDI_Interface dualmidi(hwmidi, usbmidi);
NinjaPanas commented 6 years ago

Thank you!!!! You are awesome! Your lib made like good scientific book. It is perfect! I mean it is joy to read pages of it. I'm sorry, that for me it is "starting to learn Chinese" :) I mean if I learn C++ in high school, I would never ask such infant questions about code. Thank you for your help, and thank you for your patience!

tttapa commented 6 years ago

Great! Glad to hear :)