GithubHelp home page GithubHelp logo

lathoub / arduino-usbmidi Goto Github PK

View Code? Open in Web Editor NEW
145.0 9.0 11.0 98 KB

Allows a microcontroller, with native USB capabilities, to appear as a MIDI device over USB to a connected computer

License: MIT License

C++ 100.00%
usb-midi midi midi-controller midi-device arduino arduino-library teensy arduino-midi-library

arduino-usbmidi's Introduction

Arduino USB-MIDI Transport

arduino-library-badge

This library implements the USB-MIDI transport layer for the FortySevenEffects Arduino MIDI Library and uses the underlying Arduino MIDIUSB library (so only devices working with MIDIUSB, will work here).

Alternative library: see also Adafruit's TinyUSB Library for Arduino for ESP32, mbed_rp2040, ArduinoCore-samd and Pico

Installation

Screenshot 2020-04-25 at 09 42 19

This library depends on the Arduino MIDI Library and Arduino's MIDIUSB.

When installing this library from the Arduino IDE, both will be downloaded and installed in the same directory as this library. (Thanks to the depends clause in library.properties)

When manually installing this library, you have to manually download Arduino MIDI Library and MIDIUSB from github and install it in the same directory as this library - without these additional installs, this library will not be able to compile.

Usage

Basic / Default

#include <USB-MIDI.h>
...
USBMIDI_CREATE_DEFAULT_INSTANCE();
...
void setup()
{
   MIDI.begin(1);
...
void loop()
{
   MIDI.read();

will create a instance named MIDI (transport instance named __usbMIDI) and is by default connected to cable number 0 - and listens to incoming MIDI on channel 1.

Modified

#include <USB-MIDI.h>
...
USBMIDI_CREATE_INSTANCE(4);

will create a instance named MIDI (transport instance named __usbMIDI) and is connected to cable number 4.

Advanced

#include <USB-MIDI.h>
...
USBMIDI_NAMESPACE::usbMidiTransport usbMIDI2(5);
MIDI_NAMESPACE::MidiInterface<USBMIDI_NAMESPACE::usbMidiTransport> MIDI2((USBMIDI_NAMESPACE::usbMidiTransport&)usbMIDI2);

will create a instance named usbMIDI2 (and underlaying MIDI object MIDI2) and is by default connected to cable number 5.

Tested boards / modules

  • Arduino Leonardo
  • Teensy 4.1 (incl MIDI, MIDIx4 and MIDIx16)

Boards / modules in development (help needed)

  • Arduino NANO 33 BLE
  • nRF52832 Bluefruit Feather

Memory usage

The library does not add additional buffers and is extremely efficient and has a small memory footprint.

Other Transport protocols:

The libraries below the same calling mechanism (API), making it easy to interchange the transport layer.

arduino-usbmidi's People

Contributors

frensing avatar lathoub avatar levicole avatar yuuichiakagawa avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

arduino-usbmidi's Issues

Is it possible to have 2 USB MIDI ports in different cables numbers?

Hi!

I am trying to make my device show 2 different USB-MIDI ports to the computer.

Is this possible?

I am trying like this:

USBMIDI_CREATE_DEFAULT_INSTANCE()
USBMIDI_CREATE_INSTANCE(4, MIDIOUT)

and then

MIDI.begin(MIDI_CHANNEL_OMNI); 
MIDI.turnThruOff(); 

MIDIOUT.begin(MIDI_CHANNEL_OMNI); 
MIDIOUT.turnThruOff(); 

But I only see the first MIDI port.

In the examples I see that there is one for a Hardware MIDI and USB midi ports, but I don't see an example with 2 USB ports.

Thanks!

No midi send or received with board profile arduino zero

Reproduce like this:
Install MIDI and USB-MIDI, the latter pulls in also MIDIUSB.
Load the example NoteOnOffEverySecond.
The computer connected to the MCU via USB detects MIDI device Arduino zero, but no MIDI is received, and no midi notes are received by the MCU. This example works perfectly: MIDIUSBwrite, it uses the MIDIUSB library. So I will use that library now.

Device used: SAMD21 MINI, using profile "Arduino-zero (native USB).

Is it possible to change the name of the MIDI Device?

Hey! Not really an issue as much as just a question. I'm using a Metro M0 Express, I'm wondering if theres a way to change the name that applications see when this is plugged in, currently programs see it is "Metro M0 Express" But i'm not sure where or how it see's that info and if theres a way to change it?

USBMIDI and HID device at once.

Does this library support to be a USBMIDI, while a other library is functioning as a HID device at once over the same USB-port?

Is it possible to change the maximum sysex message length?

I 've been experimenting with this library along with the FortySevenEffects library. I was attempting to use an Arduino as a USB -> DIN midi interface so I could send DX7 patches from Dexed to a VolcaFM. It seems as if the SysexMaxSize is not customizable in the same way that it is for say serial midi (snippet below).

I'm OK with C, but when it comes to C++ templates and macros, I get completely lost. It seems like it might be possible and my limited knowledge might be keeping me from seeing it.

Custom settings subclass and instantiation for serial midi:

struct MySettings : public midi::DefaultSerialSettings
{
   static const unsigned SysExMaxSize = 1024; // Accept SysEx messages up to 1024 bytes long.
};

MIDI_CREATE_CUSTOM_INSTANCE(HardwareSerial, Serial1, MIDI_S, MySettings);

USB-MIDI_defs.h suggestion

I suggest adding MidiType:: to each of the types below to prevent ambiguities with user defined types:

static uint8_t type2cin[][2] = { {InvalidType,0}, {NoteOff,8}, {NoteOn,9}, {AfterTouchPoly,0xA}, {ControlChange,0xB}, {ProgramChange,0xC}, {AfterTouchChannel,0xD}, {PitchBend,0xE} };

static uint8_t system2cin[][2] = { {SystemExclusive,0}, {TimeCodeQuarterFrame,2}, {SongPosition,3}, {SongSelect,2}, {0,0}, {0,0}, {TuneRequest,5}, {SystemExclusiveEnd,0}, {Clock,0xF}, {0,0}, {Start,0xF}, {Continue,0xF}, {Stop,0xF}, {0,0}, {ActiveSensing,0xF}, {SystemReset,0xF} };

MIDI.sendRealTime seems not working properly over USB

I installed the example code "AllEvents" on my Arduino Leonardo.

Most time, I do not get the Midi-NoteOn-Message from this example on my USB-Port. I Checked it with midi-ox unter windows 10 and even unter Ubuntu.
It seems that sending a MIDI-SendRealTime message like "MIDI.sendRealTime(MidiType::Clock);" corrupts a following Midi-Message most times.
I disabled the output on serial port an still got this error.
I changed the MIDI-sendRealTime - Message from "Clock" to "Start". I get still this error.
I added a second MIDI-sendRealTime-Message in the example code. I only see the first MIDI.sendRealTime-Message in midi-ox.

I don't have a clue.

Regards Bernd

ESP32 S2 and S3 support??

Would it be possible to make this library work with the ESP32 S2 and S3? Both support native USB.
Thanks

PluggableUSB.h

I am getting an error that I cannot resolve.

/Users/temporary/Documents/Arduino/libraries/USBMIDI/src/usbmidi_pluggableusb.cpp:13:10: fatal error: PluggableUSB.h: No such file or directory
 #include <PluggableUSB.h>

I see other posts online about this issue, but nothing that has helped me, are you able to offer some clarity or a fix or workaround?
Thank you!

USB Midi hang when connected computer hibernates

So I have another unusual issue. I am again using an ATmega32U4. It is connected to a PC USB port and everything works as intended until I hibernate the computer. The MIDI device keeps receiving power from the computer and begins hanging on USB sends while the computer is hibernated, and when it's powered back on it acts normal again once the Windows login screen loads. The hangs cause around 1/4 second delay before the program loop can proceed, and the pro micro's LED which lights up on a USB send stays lit the entire time the computer is hibernated.

If I comment out the USB MIDI .begin() as well as the USB sends, the computer does not keep sending power to the device when it goes into hibernation, powering the device off as it hibernates.

If I power cycle the device while the PC is hibernated, it will power on and will work as normal. After the PC is powered back on and the ATmega32U4 communicates with the computer it will hang again if the computer is hibernated (it will actually communicate for a brief time during the PC's boot sequence and as soon as the boot proceeds on, it will begin hanging for the rest of the boot until Windows comes up).

Is there a way to tell the device to only send USB data if there is an established connection to prevent the hanging?

MIDI_DIN2USB example does not work (incorrect second and third byte)

The MIDI_DIN2USB doesn't seem to work properly.

Versions used:

  • USB-MIDI 1.1.2
  • MIDI Library 5.0.2
  • Arduino IDE 2.3.2
  • Arduino Leonardo

Setup (tested working using another library):

  • MIDI keyboard connected to the DIN input
  • PC connected through USB running a MIDI monitor

If I press a key on the MIDI keyboard, I see a message coming in in the MIDI monitor on the PC. Only the first byte is correct however:

90 00 00
80 00 00

Adding some Serial.println() statements in the onSerialMessage() method confirms that message contains the correct channel, data1 and data2. The length attribute is 0 however. Forcing it to 3 before sending it out to MIDICoreUSB.send() results in correct MIDI note on/off messages. This won't work for messages with different lengths of course.

Handling both Serial & USB

Hi, I'm working in a MIDI instrument that I would like to support both serial & midi clock + messages, like any other industrial instrument.

I haven't seen any example on the whole internet, would you provide one?

Use cases:

  • MIDI clock read from serial is connected.
  • MIDI clock read from USB is connected.
  • MIDI clock read from digital pin (optional, audio cable 3.5mm)
  • MIDI messages read from serial & USB (if any or both are connected)
  • MIDI messages sent to serial & USB (if any or both are connected)

Unable to compile for Digispark (ATTiny85)

Does this library support the ATTiny85? I tried to compile the same code that runs fine on ATmega32u4, but I get the following error.

In file included from C:\Users\<user>\Documents\Arduino\libraries\USB-MIDI\src/USB-MIDI.h:26:0,
from C:\Users\<user>\Desktop\myMIDI\test_jul09a\test_jul09a.ino:10:
C:\Users\<user>\Documents\Arduino\libraries\MIDIUSB\src/MIDIUSB.h:18:2: error: #error MIDIUSB
can only be used with an USB MCU.
#error MIDIUSB can only be used with an USB MCU.
  ^
In file included from C:\Users\<user>\Documents\Arduino\libraries\USB-MIDI\src/USB-MIDI.h:26:0,
from C:\Users\<user>\Desktop\myMIDI\test_jul09a\test_jul09a.ino:10:
C:\Users\RDCUser\Documents\Arduino\libraries\MIDIUSB\src/MIDIUSB.h:25:26: fatal error: PluggableUSB.h:
No such file or directory
#include "PluggableUSB.h"

I have seen another project (USBMIDI) that seem to emulate MIDI over USB using the V-USB library and works for ATTiny85 and the Digispark boards. If it does not support, is it easy to make modifications to support Digispark? I am not sure if its even worth - if the performance suffers as there will be another layer in between.

Example MIDI DIN2USB does not work with Leonardo

I did test example MIDI_DIN2USB from USB-MIDI library v1.12 with Arduino Pro Micro (Leonardo)

Sending control change B0,07,7f from PC to Arduino USB MIDI.
logging of the (modified) sketch printed out the correct bytes were received from Arduino USB,
but they were not forwarded to my MIDI device.

  • Testing with other library works (connecting MIDI DIN to USB MIDI bidirectional w. SysEx, So the hardware seems ok.

For testing, i was just connecting MIDI DIN out -> MIDI DIN in on my Arduino board.
(The way then would be PC -> Arduino USB -> Arduino DIN out -> Arduino DIN in -> Arduino USB -> PC)

I sended again from PC -> USB
3 times nothing was received from serial MIDI.
When sending the same control change to USB the 4th time, it got fancy:
Suddenly data was received from Serial MIDI but not the original data, (see logging below)
It was forwarded to USB and on the PC but it received b0,00,00 like hell
It did not stop to send it again and again, I had to unplug the usb cable to stop it.

All best
Uli Schmidt

here the sketch and logging:

#define VERBOSE

#include <USB-MIDI.h>
USING_NAMESPACE_MIDI;

typedef USBMIDI_NAMESPACE::usbMidiTransport __umt;
typedef MIDI_NAMESPACE::MidiInterface<__umt> __ss;
__umt usbMIDI(0);  // cableNr
__ss MIDICoreUSB((__umt&)usbMIDI);

typedef Message<MIDI_NAMESPACE::DefaultSettings::SysExMaxSize> MidiMessage;

MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDICoreSerial);


void setup() {
#ifdef VERBOSE
  Serial.begin(115200);
#endif

  MIDICoreUSB.setHandleMessage(onUsbMessage);
  MIDICoreSerial.setHandleMessage(onSerialMessage);

  MIDICoreUSB.begin(MIDI_CHANNEL_OMNI);
  MIDICoreSerial.begin(MIDI_CHANNEL_OMNI);

  //  MIDICoreUSB.turnThruOff();
  //  MIDICoreSerial.turnThruOff();

}

void loop() {
  MIDICoreUSB.read();
  MIDICoreSerial.read();
}

// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void onUsbMessage(const MidiMessage& message) {
  MIDICoreSerial.send(message);
#ifdef VERBOSE
  printMsg("usb ", message);
#endif
}

void onSerialMessage(const MidiMessage& message) {
  MIDICoreUSB.send(message);

#ifdef VERBOSE
  printMsg("ser ", message);
#endif
}

#ifdef VERBOSE
void printMsg(const char* from, const MidiMessage& message) {
  Serial.print(from);
  Serial.print(message.type, HEX);

  switch (message.type & 0xf0) {
    case 0xf0:  // sysex
      Serial.print(" SysEx size=");
      Serial.println(message.getSysExSize());
      return;
    case 0xc0:  // ProgramChange - 1 byte messages
    case 0xd0:  // AfterTouchChannel
      Serial.print(" ");
      Serial.print(message.data1, HEX);
      break;
    case 0x80:  // NoteOff - 2 byte messages
    case 0x90:  // NoteOn
    case 0xa0:  // AfterTouchPoly
    case 0xb0:  // ControlChange
    case 0xe0:  // PitchBend
      Serial.print(" ");
      Serial.print(message.data1, HEX);
      Serial.print(" ");
      Serial.print(message.data2, HEX);
      break;
    default:
      break;
  }
  Serial.print(" len=");
  Serial.print(message.length);
  Serial.print(" valid=");
  Serial.print(message.valid);
  Serial.print(" channel=");
  Serial.println(message.channel, HEX);

}
#endif

01:18:10.615 -> usb B0 7 7F
01:18:12.436 -> usb B0 7 7F
01:18:14.015 -> usb B0 7 7F
01:18:14.015 -> ser B0 B0 B0
01:18:14.015 -> ser B0 30 30
01:18:14.015 -> ser B0 30 30
01:18:14.015 -> ser B0 30 30
01:18:14.015 -> ser B0 30 30
01:18:14.015 -> ser B0 30 30
01:18:14.015 -> ser B0 30 30
01:18:14.015 -> ser B0 30 30
......................... goes on forever!

SysEx mode not work

Hello, first of all thank you very much for this great work!

When I tried your “example\SysEx” on the Arduino Due platform, I found that the package was not complete.

Image below is from MIDI Monitor on macOS

image

And I try to use USBPcap to capture the USB port data( file below can be open by wireShark)

test_20210121.pcap.zip
image

seems only first 3 byte transport stable

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.