kd5rxt-mark
Well-known member
EDIT: This has been resolved. See P#7 for a detailed discussion of the solution, along with a fully working sketch that supports two MIDI devices connected thru a USB hub which is connected to the T4.1 USBhost interface.
EDIT2: Changed the topic title to more accurately reflect my actual mistake which caused the original problem (was "Whether multiple MIDI devices work thru USB hub seems to be plug-order dependent").
I have wrapped up my latest TeensyMIDIPolySynth project & a friend of mine is running it thru its paces to verify whether everything works as designed & expected. One of the tests involves plugging a secondary TMPS into the USBhost port of the primary TMPS & having them both to respond appropriately to MIDI commands & notes (which can originate from traditional MIDI on either TMPS, USB MIDI on either TMPS, and/or USBhostMIDI (such as a USB MIDI keyboard and/or MIDI sequencer) on either TMPS). One possible configuration involves connecting a USB hub to the primary TMPS, to which a USB MIDI keyboard and the secondary TMPS are connected. Whether the secondary TMPS and/or the keyboard work in this cascaded configuration seems to be dependent on which device is plugged in first [ THE PROBLEM TO BE INVESTIGATED ].
I have been able to reproduce the apparent (mis)behavior in a simplified setup. I will describe the successive tests (starting with a very basic setup & progressing to the more complex setups) & the results of each (using the following nomenclature to describe the connectivity, with the specific interface on each device in parentheses):
Here's the test sketch (programmed identically into both T1 & T2):
I am hoping that someone else is able to recreate these same setups & most importantly is able to reproduce the apparent problem when using multiple MIDI devices connected thru a USB hub.
Thanks in advance for taking a look !!
Mark J Culross
KD5RXT
EDIT2: Changed the topic title to more accurately reflect my actual mistake which caused the original problem (was "Whether multiple MIDI devices work thru USB hub seems to be plug-order dependent").
I have wrapped up my latest TeensyMIDIPolySynth project & a friend of mine is running it thru its paces to verify whether everything works as designed & expected. One of the tests involves plugging a secondary TMPS into the USBhost port of the primary TMPS & having them both to respond appropriately to MIDI commands & notes (which can originate from traditional MIDI on either TMPS, USB MIDI on either TMPS, and/or USBhostMIDI (such as a USB MIDI keyboard and/or MIDI sequencer) on either TMPS). One possible configuration involves connecting a USB hub to the primary TMPS, to which a USB MIDI keyboard and the secondary TMPS are connected. Whether the secondary TMPS and/or the keyboard work in this cascaded configuration seems to be dependent on which device is plugged in first [ THE PROBLEM TO BE INVESTIGATED ].
I have been able to reproduce the apparent (mis)behavior in a simplified setup. I will describe the successive tests (starting with a very basic setup & progressing to the more complex setups) & the results of each (using the following nomenclature to describe the connectivity, with the specific interface on each device in parentheses):
Code:
T1 = primary Teensy 4.1 - simply because it is easy to access the USBhost interface
T2 = secondary Teensy 4.0 - could also be a T4.1
TAA = Teensy Audio Adapter
USBhub = Sabrent HB-UMP3 powered USB hub (with individual port power switches), typically connected to the USBhost interface of T1 - could probably be any USB hub
KB = MIDIPLUS AKM322 USB MIDI keyboard - could probably be any USB MIDI keyboard, or any MIDI sequencer
PC = Windows PC running Aria Maestosa to generate MIDI notes & controls - could probably be any MIDI source under any OS
HP = headphone jack on the TAA
<<< Simple MIDI-to-AUDIO setup - PC driven >>>
PC(USB port) ==> (microUSB)T1 + TAA(headphone jack) ==> HP
- when fed by MIDI notes & controls from the PC
- [ WORKS ] T1 generates MIDI output audio as expected
<<< Simple MIDI-to-AUDIO setup - KB driven >>>
KB(USB cable) ==> (USBhost)T1 + TAA(headphone jack) ==> HP
- when fed by MIDI notes & controls from the keyboard
- [ WORKS ] T1 generates MIDI output audio as expected
<<< Simple MIDI-to-AUDIO setup w/ USB HUB - PC driven >>>
PC(USB port) ==> (microUSB)T1 + TAA(headphone jack) ==> HP
T1(USBhost) ==> (USB cable)KB
- when fed by MIDI notes & controls from the PC
- [ WORKS ] T1 generates MIDI output audio as expected
- when fed by MIDI notes & controls from the keyboard
- [ WORKS ] T1 generates MIDI output audio as expected
- NOTE: the two MIDI sources work simultaneously
<<< Simple MIDI-to-AUDIO setup w/ USB HUB - PC and/or KB driven >>>
PC(USB port) ==> (microUSB)T1 + TAA(headphone jack) ==> HP
T1(USBhost) ==> (USB input)USBhub(USB port) ==> (USB cable)KB
- when fed by MIDI notes & controls from the PC
- [ WORKS ] T1 generates MIDI output audio as expected
- when fed by MIDI notes & controls from the keyboard
- [ WORKS ] T1 generates MIDI output audio as expected
- NOTE: the two MIDI sources work simultaneously
<<< Cascaded MIDI-to-AUDIO setup - PC driven >>>
PC(USB port) ==> (microUSB)T1(USBhost) ==> (microUSB)T2 + TAA(headphone jack) ==> HP
- when fed by MIDI notes & controls from the PC
- [ WORKS ] T2 generates MIDI output audio as expected
<<< Cascaded MIDI-to-AUDIO setup w/ USB hub - PC driven >>>
PC(USB port) ==> (microUSB)T1(USBhost) ==> (USB input)USBhub(USB port) ==>(microUSB)T2 + TAA(headphone jack) ==> HP
- when fed by MIDI notes & controls from the PC
- [ WORKS ] T2 generates MIDI output audio as expected
<<< Cascaded MIDI-to-AUDIO setup w/ USB hub - PC and/or KB driven >>>
PC(USB port) ==> (microUSB)T1(USBhost) ==> (USB input)USBhub(USB port) ==>(microUSB)T2 + TAA(headphone jack) ==> HP
USBhub(USB port) ==> (USB cable)KB
- if T2 is plugged into the USBhub, then the keyboard is plugged into the USBhub
- when fed by MIDI notes & controls from the PC
- [ WORKS ] T2 generates MIDI output as expected
- [ FAILS ] keyboard does not generate any MIDI notes or controls (suspect that the MIDI notes & controls are not getting thru the USBhub)
- if keyboard is plugged into the USBhub, then T2 is plugged into the USBhub
- when fed by MIDI notes & controls from the keyboard
- [ WORKS ] keyboard generates MIDI notes & controls (as observed in the Serial Monitor)
- [ FAILS ] T2 does not generate any MIDI output (suspect that the MIDI notes & controls are not getting thru the USBhub)
Here's the test sketch (programmed identically into both T1 & T2):
Code:
//
// Teensy MIDI USBhost test
//
// - reads MIDI data & cmds from traditional MIDI, usbMIDI, or USBhost & plays the indicated note(s)
//
// Arduino IDE Configuration:
// Tools/Board: "Teensy 4.0"
// Tools/USB Type: "Serial + MIDI"
// Tools/CPU Speed: "600MHz"
// Tools/Optimize: "Debug"
// Tools/Keyboard Layout: "US English"
// Tools/Port: "COMx Serial (Teensy 4.0)"
//
#define DEBUG_NOTE_MSGS
#define DEBUG_MIDI_NOTE_MSGS
#define DEBUG_USB_MIDI_NOTE_MSGS
#define DEBUG_USBHOST_MIDI_NOTE_MSGS
#include <SPI.h>
#include <USBHost_t36.h>
#include <MIDI.h>
#include <Audio.h>
// GUItool: begin automatically generated code
AudioSynthWaveform square01; //xy=94,37.75
AudioOutputI2S i2s1; //xy=1431.75,487.75
AudioConnection patchCord1(square01, 0, i2s1, 0);
AudioConnection patchCord2(square01, 0, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1; //xy=1283,157.75
// GUItool: end automatically generated code
#define LOCAL_MIDI_CHANNEL_OMNI -1
int midi_channel = LOCAL_MIDI_CHANNEL_OMNI;
USBHost thisUSB;
USBHub hub1(thisUSB);
USBHub hub2(thisUSB);
USBHub hub3(thisUSB);
USBHub hub4(thisUSB);
MIDIDevice_BigBuffer usbhostMIDI(thisUSB);
MIDI_CREATE_DEFAULT_INSTANCE();
//
// The following pins are used in this (Audio) portion of the Teensy 4.x PolySynth project:
//
// PIN D0 = (not used)
// PIN D1 = (not used)
// PIN D2 = (not used)
// PIN D3 = (not used)
// PIN D4 = (not used)
// PIN D5 = (not used)
// PIN D6 = Audio adapter memory chip select (MEMCS)
// PIN D7 = Audio adapter data in (DIN)
// PIN D8 = Audio adapter data out (DOUT)
// PIN D9 = (not used)
// PIN D10 = Audio adapter SD card chip select (SDCS)
// PIN D11 = Audio adapter SPI data in (MOSI)
// PIN D12 = Audio adapter SPI data out (MISO)
// PIN D13 = Audio adapter SPI serial clock (SCK) + on-board LED
// PIN D14/A0 = (not used)
// PIN D15/A1 = Volume pot on audio adapter
// PIN D16/A2 = EA Receive
// PIN D17/A3 = EA Transmit
// PIN D18/A4 = Audio adapter I2C control data (SDA)
// PIN D19/A5 = Audio adapter I2C control clock (SCL)
// PIN D20/A6 = Audio adapter Left/Right Clock (LRCLK)
// PIN D21/A7 = Audio adapter Bit Clock (BCLK)
// PIN D22/A8 = (not used)
// PIN D23/A9 = Audio adapter Master Clock (MCLK)
// PIN D24/A10 = (not used)
// PIN D25/A11 = (not used)
// PIN D26/A12 = (not used)
// PIN D27/A13 = (not used)
// PIN D28 = (not used)
// PIN D29 = (not used)
// PIN D30 = (not used)
// PIN D31 = (not used)
// PIN D32 = (not used)
// PIN D33 = (not used)
// PIN D34 = (not used)
// PIN D35 = (not used)
// PIN D36 = (not used)
// PIN D37 = (not used)
// PIN D38/A14 = (not used)
// PIN D39/A15 = (not used)
// PIN D40/A16 = (not used)
// PIN D41/A17 = (not used)
#define LED_PIN 13
// MIDI note-to-frequency data from: http://tonalsoft.com/pub/news/pitch-bend.aspx
#define FLOAT_NOTE_C0 16.352
#define FLOAT_NOTE_CS0 17.324
#define FLOAT_NOTE_D0 18.354
#define FLOAT_NOTE_DS0 19.445
#define FLOAT_NOTE_E0 20.602
#define FLOAT_NOTE_F0 21.827
#define FLOAT_NOTE_FS0 23.125
#define FLOAT_NOTE_G0 24.500
#define FLOAT_NOTE_GS0 25.957
#define FLOAT_NOTE_A0 27.500
#define FLOAT_NOTE_AS0 29.135
#define FLOAT_NOTE_B0 30.868
#define FLOAT_NOTE_C1 32.703
#define FLOAT_NOTE_CS1 34.648
#define FLOAT_NOTE_D1 36.708
#define FLOAT_NOTE_DS1 38.891
#define FLOAT_NOTE_E1 41.203
#define FLOAT_NOTE_F1 43.654
#define FLOAT_NOTE_FS1 46.249
#define FLOAT_NOTE_G1 48.999
#define FLOAT_NOTE_GS1 51.913
#define FLOAT_NOTE_A1 55.000
#define FLOAT_NOTE_AS1 58.270
#define FLOAT_NOTE_B1 61.735
#define FLOAT_NOTE_C2 65.406
#define FLOAT_NOTE_CS2 69.296
#define FLOAT_NOTE_D2 73.416
#define FLOAT_NOTE_DS2 77.782
#define FLOAT_NOTE_E2 82.407
#define FLOAT_NOTE_F2 87.307
#define FLOAT_NOTE_FS2 92.499
#define FLOAT_NOTE_G2 97.999
#define FLOAT_NOTE_GS2 103.826
#define FLOAT_NOTE_A2 110.000
#define FLOAT_NOTE_AS2 116.541
#define FLOAT_NOTE_B2 123.471
#define FLOAT_NOTE_C3 130.813
#define FLOAT_NOTE_CS3 138.591
#define FLOAT_NOTE_D3 146.832
#define FLOAT_NOTE_DS3 155.563
#define FLOAT_NOTE_E3 164.814
#define FLOAT_NOTE_F3 174.614
#define FLOAT_NOTE_FS3 184.997
#define FLOAT_NOTE_G3 195.998
#define FLOAT_NOTE_GS3 207.652
#define FLOAT_NOTE_A3 220.000
#define FLOAT_NOTE_AS3 233.082
#define FLOAT_NOTE_B3 246.942
#define FLOAT_NOTE_C4 261.626
#define FLOAT_NOTE_CS4 277.183
#define FLOAT_NOTE_D4 293.665
#define FLOAT_NOTE_DS4 311.127
#define FLOAT_NOTE_E4 329.628
#define FLOAT_NOTE_F4 349.228
#define FLOAT_NOTE_FS4 369.994
#define FLOAT_NOTE_G4 391.995
#define FLOAT_NOTE_GS4 415.305
#define FLOAT_NOTE_A4 440.000
#define FLOAT_NOTE_AS4 466.164
#define FLOAT_NOTE_B4 493.883
#define FLOAT_NOTE_C5 523.251
#define FLOAT_NOTE_CS5 554.365
#define FLOAT_NOTE_D5 587.330
#define FLOAT_NOTE_DS5 622.254
#define FLOAT_NOTE_E5 659.255
#define FLOAT_NOTE_F5 698.456
#define FLOAT_NOTE_FS5 739.989
#define FLOAT_NOTE_G5 783.991
#define FLOAT_NOTE_GS5 830.609
#define FLOAT_NOTE_A5 880.000
#define FLOAT_NOTE_AS5 932.328
#define FLOAT_NOTE_B5 987.767
#define FLOAT_NOTE_C6 1046.502
#define FLOAT_NOTE_CS6 1108.731
#define FLOAT_NOTE_D6 1174.659
#define FLOAT_NOTE_DS6 1244.508
#define FLOAT_NOTE_E6 1318.510
#define FLOAT_NOTE_F6 1396.913
#define FLOAT_NOTE_FS6 1479.978
#define FLOAT_NOTE_G6 1567.982
#define FLOAT_NOTE_GS6 1661.219
#define FLOAT_NOTE_A6 1760.000
#define FLOAT_NOTE_AS6 1864.655
#define FLOAT_NOTE_B6 1975.533
#define FLOAT_NOTE_C7 2093.005
#define FLOAT_NOTE_CS7 2217.461
#define FLOAT_NOTE_D7 2349.318
#define FLOAT_NOTE_DS7 2489.016
#define FLOAT_NOTE_E7 2637.020
#define FLOAT_NOTE_F7 2793.826
#define FLOAT_NOTE_FS7 2959.955
#define FLOAT_NOTE_G7 3135.963
#define FLOAT_NOTE_GS7 3322.438
#define FLOAT_NOTE_A7 3520.000
#define FLOAT_NOTE_AS7 3729.310
#define FLOAT_NOTE_B7 3951.066
#define FLOAT_NOTE_C8 4186.009
#define FLOAT_NOTE_CS8 4434.922
#define FLOAT_NOTE_D8 4698.636
#define FLOAT_NOTE_DS8 4978.032
#define FLOAT_NOTE_E8 5274.041
#define FLOAT_NOTE_F8 5587.651
#define FLOAT_NOTE_FS8 5919.911
#define FLOAT_NOTE_G8 6271.927
#define FLOAT_NOTE_GS8 6644.875
#define FLOAT_NOTE_A8 7040.000
#define FLOAT_NOTE_AS8 7458.620
#define FLOAT_NOTE_B8 7902.133
#define FLOAT_NOTE_C9 8372.018
#define FLOAT_NOTE_CS9 8869.844
#define FLOAT_NOTE_D9 9397.273
#define FLOAT_NOTE_DS9 9956.063
#define FLOAT_NOTE_E9 10548.082
#define FLOAT_NOTE_F9 11175.303
#define FLOAT_NOTE_FS9 11839.822
#define FLOAT_NOTE_G9 12543.854
#define FLOAT_NOTE_GS9 13289.750
#define FLOAT_NOTE_A9 14080.000
#define FLOAT_NOTE_AS9 14917.240
#define FLOAT_NOTE_B9 15804.266
#define FLOAT_NOTE_C10 16744.036
// NOTE: this array includes valid entries for indices 0..120 (to cover the extended range sent by my MIDI keyboard)
const float fNotePitches[] = {
FLOAT_NOTE_C0, FLOAT_NOTE_CS0, FLOAT_NOTE_D0, FLOAT_NOTE_DS0, FLOAT_NOTE_E0, FLOAT_NOTE_F0, FLOAT_NOTE_FS0, FLOAT_NOTE_G0, FLOAT_NOTE_GS0, FLOAT_NOTE_A0, FLOAT_NOTE_AS0, FLOAT_NOTE_B0,
FLOAT_NOTE_C1, FLOAT_NOTE_CS1, FLOAT_NOTE_D1, FLOAT_NOTE_DS1, FLOAT_NOTE_E1, FLOAT_NOTE_F1, FLOAT_NOTE_FS1, FLOAT_NOTE_G1, FLOAT_NOTE_GS1, FLOAT_NOTE_A1, FLOAT_NOTE_AS1, FLOAT_NOTE_B1,
FLOAT_NOTE_C2, FLOAT_NOTE_CS2, FLOAT_NOTE_D2, FLOAT_NOTE_DS2, FLOAT_NOTE_E2, FLOAT_NOTE_F2, FLOAT_NOTE_FS2, FLOAT_NOTE_G2, FLOAT_NOTE_GS2, FLOAT_NOTE_A2, FLOAT_NOTE_AS2, FLOAT_NOTE_B2,
FLOAT_NOTE_C3, FLOAT_NOTE_CS3, FLOAT_NOTE_D3, FLOAT_NOTE_DS3, FLOAT_NOTE_E3, FLOAT_NOTE_F3, FLOAT_NOTE_FS3, FLOAT_NOTE_G3, FLOAT_NOTE_GS3, FLOAT_NOTE_A3, FLOAT_NOTE_AS3, FLOAT_NOTE_B3,
FLOAT_NOTE_C4, FLOAT_NOTE_CS4, FLOAT_NOTE_D4, FLOAT_NOTE_DS4, FLOAT_NOTE_E4, FLOAT_NOTE_F4, FLOAT_NOTE_FS4, FLOAT_NOTE_G4, FLOAT_NOTE_GS4, FLOAT_NOTE_A4, FLOAT_NOTE_AS4, FLOAT_NOTE_B4,
FLOAT_NOTE_C5, FLOAT_NOTE_CS5, FLOAT_NOTE_D5, FLOAT_NOTE_DS5, FLOAT_NOTE_E5, FLOAT_NOTE_F5, FLOAT_NOTE_FS5, FLOAT_NOTE_G5, FLOAT_NOTE_GS5, FLOAT_NOTE_A5, FLOAT_NOTE_AS5, FLOAT_NOTE_B5,
FLOAT_NOTE_C6, FLOAT_NOTE_CS6, FLOAT_NOTE_D6, FLOAT_NOTE_DS6, FLOAT_NOTE_E6, FLOAT_NOTE_F6, FLOAT_NOTE_FS6, FLOAT_NOTE_G6, FLOAT_NOTE_GS6, FLOAT_NOTE_A6, FLOAT_NOTE_AS6, FLOAT_NOTE_B6,
FLOAT_NOTE_C7, FLOAT_NOTE_CS7, FLOAT_NOTE_D7, FLOAT_NOTE_DS7, FLOAT_NOTE_E7, FLOAT_NOTE_F7, FLOAT_NOTE_FS7, FLOAT_NOTE_G7, FLOAT_NOTE_GS7, FLOAT_NOTE_A7, FLOAT_NOTE_AS7, FLOAT_NOTE_B7,
FLOAT_NOTE_C8, FLOAT_NOTE_CS8, FLOAT_NOTE_D8, FLOAT_NOTE_DS8, FLOAT_NOTE_E8, FLOAT_NOTE_F8, FLOAT_NOTE_FS8, FLOAT_NOTE_G8, FLOAT_NOTE_GS8, FLOAT_NOTE_A8, FLOAT_NOTE_AS8, FLOAT_NOTE_B8,
FLOAT_NOTE_C9, FLOAT_NOTE_CS9, FLOAT_NOTE_D9, FLOAT_NOTE_DS9, FLOAT_NOTE_E9, FLOAT_NOTE_F9, FLOAT_NOTE_FS9, FLOAT_NOTE_G9, FLOAT_NOTE_GS9, FLOAT_NOTE_A9, FLOAT_NOTE_AS9, FLOAT_NOTE_B9,
FLOAT_NOTE_C10
};
// function headers
void handleNoteOff(byte channel, byte pitch, byte velocity);
void handleNoteOn(byte channel, byte pitch, byte velocity);
void MIDIhandleNoteOff(byte channel, byte pitch, byte velocity);
void MIDIhandleNoteOn(byte channel, byte pitch, byte velocity);
void USBhandleNoteOff(byte channel, byte pitch, byte velocity);
void USBhandleNoteOn(byte channel, byte pitch, byte velocity);
void usbhostMIDIhandleNoteOff(byte channel, byte pitch, byte velocity);
void usbhostMIDIhandleNoteOn(byte channel, byte pitch, byte velocity);
void handleNoteOff(byte channel, byte pitch, byte velocity)
{
digitalWrite(LED_PIN, HIGH);
#ifdef DEBUG_NOTE_MSGS
Serial.print("Note Off: ch=");
if (channel < 10)
{
Serial.print("0");
}
Serial.print(channel);
Serial.print(" pitch=");
if (pitch < 100)
{
Serial.print(" ");
}
if (pitch < 10)
{
Serial.print(" ");
}
Serial.println(pitch);
#endif
if ((midi_channel == LOCAL_MIDI_CHANNEL_OMNI) || (midi_channel == channel))
{
square01.amplitude(0);
}
digitalWrite(LED_PIN, LOW);
} //handleNoteOff()
void handleNoteOn(byte channel, byte pitch, byte velocity)
{
digitalWrite(LED_PIN, HIGH);
#ifdef DEBUG_NOTE_MSGS
Serial.print("Note On: ch=");
if (channel < 10)
{
Serial.print("0");
}
Serial.print(channel);
Serial.print(" pitch=");
if (pitch < 100)
{
Serial.print(" ");
}
if (pitch < 10)
{
Serial.print(" ");
}
Serial.print(pitch);
Serial.print(" velocity=");
if (velocity < 100)
{
Serial.print(" ");
}
if (velocity < 10)
{
Serial.print(" ");
}
Serial.println(velocity);
Serial.print(channel);
Serial.print(" ");
Serial.print(fNotePitches[pitch]);
Serial.print(" ");
Serial.println(float(velocity) / 255.0);
#endif
if ((midi_channel == LOCAL_MIDI_CHANNEL_OMNI) || (midi_channel == channel))
{
square01.frequency(fNotePitches[pitch] / 2.0);
square01.amplitude(velocity);
}
digitalWrite(LED_PIN, LOW);
} // handleNoteOn
// -----------------------------------------------------------------------------
void loop()
{
MIDI.read();
usbMIDI.read();
usbhostMIDI.read();
thisUSB.Task();
} // loop()
void MIDIhandleNoteOff(byte channel, byte pitch, byte velocity)
{
#ifdef DEBUG_MIDI_NOTE_MSGS
Serial.print("MIDI Note Off: ch=");
if (channel < 10)
{
Serial.print("0");
}
Serial.print(channel);
Serial.print(" pitch=");
if (pitch < 100)
{
Serial.print(" ");
}
if (pitch < 10)
{
Serial.print(" ");
}
Serial.println(pitch);
#endif
if ((midi_channel == LOCAL_MIDI_CHANNEL_OMNI) || (midi_channel == channel))
{
#ifdef DEBUG_USB_MIDI_NOTE_MSGS
Serial.print("Sending USB MIDI Note Off: ch=");
if (channel < 10)
{
Serial.print("0");
}
Serial.print(channel);
Serial.print(" pitch=");
if (pitch < 100)
{
Serial.print(" ");
}
if (pitch < 10)
{
Serial.print(" ");
}
Serial.println(pitch);
#endif
usbMIDI.sendNoteOff(pitch, velocity, channel);
#ifdef DEBUG_USBHOST_MIDI_NOTE_MSGS
Serial.print("Sending USBhost MIDI Note Off: ch=");
if (channel < 10)
{
Serial.print("0");
}
Serial.print(channel);
Serial.print(" pitch=");
if (pitch < 100)
{
Serial.print(" ");
}
if (pitch < 10)
{
Serial.print(" ");
}
Serial.println(pitch);
#endif
usbhostMIDI.sendNoteOff(pitch, velocity, channel);
handleNoteOff(channel, pitch, velocity);
}
} // MIDIhandleNoteOff()
void MIDIhandleNoteOn(byte channel, byte pitch, byte velocity)
{
#ifdef DEBUG_MIDI_NOTE_MSGS
Serial.print("MIDI Note On: ch=");
if (channel < 10)
{
Serial.print("0");
}
Serial.print(channel);
Serial.print(" pitch=");
if (pitch < 100)
{
Serial.print(" ");
}
if (pitch < 10)
{
Serial.print(" ");
}
Serial.print(pitch);
Serial.print(" velocity=");
if (velocity < 100)
{
Serial.print(" ");
}
if (velocity < 10)
{
Serial.print(" ");
}
Serial.println(velocity);
Serial.print(channel);
Serial.print(" ");
Serial.print(fNotePitches[pitch]);
Serial.print(" ");
Serial.println(float(velocity) / 255.0);
#endif
if ((midi_channel == LOCAL_MIDI_CHANNEL_OMNI) || (midi_channel == channel))
{
#ifdef DEBUG_USB_MIDI_NOTE_MSGS
Serial.print("Sending USB MIDI Note On: ch=");
if (channel < 10)
{
Serial.print("0");
}
Serial.print(channel);
Serial.print(" pitch=");
if (pitch < 100)
{
Serial.print(" ");
}
if (pitch < 10)
{
Serial.print(" ");
}
Serial.print(pitch);
Serial.print(" velocity=");
if (velocity < 100)
{
Serial.print(" ");
}
if (velocity < 10)
{
Serial.print(" ");
}
Serial.println(velocity);
Serial.print(channel);
Serial.print(" ");
Serial.print(fNotePitches[pitch]);
Serial.print(" ");
Serial.println(float(velocity) / 255.0);
#endif
usbMIDI.sendNoteOn(pitch, velocity, channel);
#ifdef DEBUG_USBHOST_MIDI_NOTE_MSGS
Serial.print("Sending USBhost MIDI Note On: ch=");
if (channel < 10)
{
Serial.print("0");
}
Serial.print(channel);
Serial.print(" pitch=");
if (pitch < 100)
{
Serial.print(" ");
}
if (pitch < 10)
{
Serial.print(" ");
}
Serial.print(pitch);
Serial.print(" velocity=");
if (velocity < 100)
{
Serial.print(" ");
}
if (velocity < 10)
{
Serial.print(" ");
}
Serial.println(velocity);
Serial.print(channel);
Serial.print(" ");
Serial.print(fNotePitches[pitch]);
Serial.print(" ");
Serial.println(float(velocity) / 255.0);
#endif
usbhostMIDI.sendNoteOn(pitch, velocity, channel);
handleNoteOn(channel, pitch, velocity);
}
} // MIDIhandleNoteOn()
void setup()
{
Serial.begin(57600);
pinMode(LED_PIN, OUTPUT);
usbMIDI.setHandleNoteOn(handleNoteOn); // Put only the name of the function
usbMIDI.setHandleNoteOff(handleNoteOff);
MIDI.setHandleNoteOn(MIDIhandleNoteOn); // Put only the name of the function
MIDI.setHandleNoteOff(MIDIhandleNoteOff);
usbMIDI.setHandleNoteOn(USBhandleNoteOn);
usbMIDI.setHandleNoteOff(USBhandleNoteOff);
usbhostMIDI.setHandleNoteOn(usbhostMIDIhandleNoteOn);
usbhostMIDI.setHandleNoteOff(usbhostMIDIhandleNoteOff);
AudioNoInterrupts();
AudioMemory(18);
sgtl5000_1.enable();
square01.amplitude(0.5);
square01.begin(WAVEFORM_SQUARE);
sgtl5000_1.volume(0.25);
AudioInterrupts();
// start the USBhost for MIDI inputs/devices
usbhostMIDI.begin();
// Initiate MIDI communications, listen to all channels
MIDI.begin(MIDI_CHANNEL_OMNI);
} // setup()
void USBhandleNoteOff(byte channel, byte pitch, byte velocity)
{
#ifdef DEBUG_USB_MIDI_NOTE_MSGS
Serial.print("USB MIDI Note Off: ch=");
if (channel < 10)
{
Serial.print("0");
}
Serial.print(channel);
Serial.print(" pitch=");
if (pitch < 100)
{
Serial.print(" ");
}
if (pitch < 10)
{
Serial.print(" ");
}
Serial.println(pitch);
#endif
if ((midi_channel == LOCAL_MIDI_CHANNEL_OMNI) || (midi_channel == channel))
{
#ifdef DEBUG_MIDI_NOTE_MSGS
Serial.print("Sending MIDI Note Off: ch=");
if (channel < 10)
{
Serial.print("0");
}
Serial.print(channel);
Serial.print(" pitch=");
if (pitch < 100)
{
Serial.print(" ");
}
if (pitch < 10)
{
Serial.print(" ");
}
Serial.println(pitch);
#endif
MIDI.sendNoteOff(pitch, velocity, channel);
#ifdef DEBUG_USBHOST_MIDI_NOTE_MSGS
Serial.print("Sending USBhost MIDI Note Off: ch=");
if (channel < 10)
{
Serial.print("0");
}
Serial.print(channel);
Serial.print(" pitch=");
if (pitch < 100)
{
Serial.print(" ");
}
if (pitch < 10)
{
Serial.print(" ");
}
Serial.println(pitch);
#endif
usbhostMIDI.sendNoteOff(pitch, velocity, channel);
handleNoteOff(channel, pitch, velocity);
}
} // USBhandleNoteOff()
void USBhandleNoteOn(byte channel, byte pitch, byte velocity)
{
#ifdef DEBUG_USB_MIDI_NOTE_MSGS
Serial.print("USB MIDI Note On: ch=");
if (channel < 10)
{
Serial.print("0");
}
Serial.print(channel);
Serial.print(" pitch=");
if (pitch < 100)
{
Serial.print(" ");
}
if (pitch < 10)
{
Serial.print(" ");
}
Serial.print(pitch);
Serial.print(" velocity=");
if (velocity < 100)
{
Serial.print(" ");
}
if (velocity < 10)
{
Serial.print(" ");
}
Serial.println(velocity);
Serial.print(channel);
Serial.print(" ");
Serial.print(fNotePitches[pitch]);
Serial.print(" ");
Serial.println(float(velocity) / 255.0);
#endif
if ((midi_channel == LOCAL_MIDI_CHANNEL_OMNI) || (midi_channel == channel))
{
#ifdef DEBUG_MIDI_NOTE_MSGS
Serial.print("Sending MIDI Note On: ch=");
if (channel < 10)
{
Serial.print("0");
}
Serial.print(channel);
Serial.print(" pitch=");
if (pitch < 100)
{
Serial.print(" ");
}
if (pitch < 10)
{
Serial.print(" ");
}
Serial.print(pitch);
Serial.print(" velocity=");
if (velocity < 100)
{
Serial.print(" ");
}
if (velocity < 10)
{
Serial.print(" ");
}
Serial.println(velocity);
Serial.print(channel);
Serial.print(" ");
Serial.print(fNotePitches[pitch]);
Serial.print(" ");
Serial.println(float(velocity) / 255.0);
#endif
MIDI.sendNoteOn(pitch, velocity, channel);
#ifdef DEBUG_USBHOST_MIDI_NOTE_MSGS
Serial.print("Sending USBhost MIDI Note On: ch=");
if (channel < 10)
{
Serial.print("0");
}
Serial.print(channel);
Serial.print(" pitch=");
if (pitch < 100)
{
Serial.print(" ");
}
if (pitch < 10)
{
Serial.print(" ");
}
Serial.print(pitch);
Serial.print(" velocity=");
if (velocity < 100)
{
Serial.print(" ");
}
if (velocity < 10)
{
Serial.print(" ");
}
Serial.println(velocity);
Serial.print(channel);
Serial.print(" ");
Serial.print(fNotePitches[pitch]);
Serial.print(" ");
Serial.println(float(velocity) / 255.0);
#endif
usbhostMIDI.sendNoteOn(pitch, velocity, channel);
handleNoteOn(channel, pitch, velocity);
}
} // USBhandleNoteOn()
// MIDI message callback - note off via usbhostMIDI
void usbhostMIDIhandleNoteOff(byte channel, byte pitch, byte velocity)
{
#ifdef DEBUG_USBHOST_MIDI_NOTE_MSGS
Serial.print("USBhost MIDI Note Off: ch=");
if (channel < 10)
{
Serial.print("0");
}
Serial.print(channel);
Serial.print(" pitch=");
if (pitch < 100)
{
Serial.print(" ");
}
if (pitch < 10)
{
Serial.print(" ");
}
Serial.println(pitch);
#endif
if ((midi_channel == LOCAL_MIDI_CHANNEL_OMNI) || (midi_channel == channel))
{
#ifdef DEBUG_MIDI_NOTE_MSGS
Serial.print("Sending MIDI Note Off: ch=");
if (channel < 10)
{
Serial.print("0");
}
Serial.print(channel);
Serial.print(" pitch=");
if (pitch < 100)
{
Serial.print(" ");
}
if (pitch < 10)
{
Serial.print(" ");
}
Serial.println(pitch);
#endif
MIDI.sendNoteOff(pitch, velocity, channel);
#ifdef DEBUG_USB_MIDI_NOTE_MSGS
Serial.print("Sending USB MIDI Note Off: ch=");
if (channel < 10)
{
Serial.print("0");
}
Serial.print(channel);
Serial.print(" pitch=");
if (pitch < 100)
{
Serial.print(" ");
}
if (pitch < 10)
{
Serial.print(" ");
}
Serial.println(pitch);
#endif
usbMIDI.sendNoteOff(pitch, velocity, channel);
handleNoteOff(channel, pitch, velocity);
}
} // usbhostMIDIhandleNoteOff()
// MIDI message callback - note on via usbhostMIDI
void usbhostMIDIhandleNoteOn(byte channel, byte pitch, byte velocity)
{
#ifdef DEBUG_USBHOST_MIDI_NOTE_MSGS
Serial.print("USBhost MIDI Note On: ch=");
if (channel < 10)
{
Serial.print("0");
}
Serial.print(channel);
Serial.print(" pitch=");
if (pitch < 100)
{
Serial.print(" ");
}
if (pitch < 10)
{
Serial.print(" ");
}
Serial.print(pitch);
Serial.print(" velocity=");
if (velocity < 100)
{
Serial.print(" ");
}
if (velocity < 10)
{
Serial.print(" ");
}
Serial.println(velocity);
Serial.print(channel);
Serial.print(" ");
Serial.print(fNotePitches[pitch]);
Serial.print(" ");
Serial.println(float(velocity) / 255.0);
#endif
if ((midi_channel == LOCAL_MIDI_CHANNEL_OMNI) || (midi_channel == channel))
{
#ifdef DEBUG_MIDI_NOTE_MSGS
Serial.print("Sending MIDI Note On: ch=");
if (channel < 10)
{
Serial.print("0");
}
Serial.print(channel);
Serial.print(" pitch=");
if (pitch < 100)
{
Serial.print(" ");
}
if (pitch < 10)
{
Serial.print(" ");
}
Serial.print(pitch);
Serial.print(" velocity=");
if (velocity < 100)
{
Serial.print(" ");
}
if (velocity < 10)
{
Serial.print(" ");
}
Serial.println(velocity);
Serial.print(channel);
Serial.print(" ");
Serial.print(fNotePitches[pitch]);
Serial.print(" ");
Serial.println(float(velocity) / 255.0);
#endif
MIDI.sendNoteOn(pitch, velocity, channel);
#ifdef DEBUG_USB_MIDI_NOTE_MSGS
Serial.print("Sending USB MIDI Note On: ch=");
if (channel < 10)
{
Serial.print("0");
}
Serial.print(channel);
Serial.print(" pitch=");
if (pitch < 100)
{
Serial.print(" ");
}
if (pitch < 10)
{
Serial.print(" ");
}
Serial.print(pitch);
Serial.print(" velocity=");
if (velocity < 100)
{
Serial.print(" ");
}
if (velocity < 10)
{
Serial.print(" ");
}
Serial.println(velocity);
Serial.print(channel);
Serial.print(" ");
Serial.print(fNotePitches[pitch]);
Serial.print(" ");
Serial.println(float(velocity) / 255.0);
#endif
usbMIDI.sendNoteOn(pitch, velocity, channel);
handleNoteOn(channel, pitch, velocity);
}
} // usbhostMIDIhandleNoteOn
// EOF PLACEHOLDER
I am hoping that someone else is able to recreate these same setups & most importantly is able to reproduce the apparent problem when using multiple MIDI devices connected thru a USB hub.
Thanks in advance for taking a look !!
Mark J Culross
KD5RXT
Last edited: