Fix SysEx size callback bug, using template settings instead of preprocessor macros.

This commit is contained in:
Francois Best 2014-06-11 09:09:08 +02:00
parent 1ff874c70d
commit 219340ea96
10 changed files with 225 additions and 190 deletions

View File

@ -4,6 +4,8 @@
// Here, when receiving any message on channel 4, the Arduino
// will blink a led and play back a note for 1 second.
MIDI_CREATE_DEFAULT_INSTANCE();
#define LED 13 // LED pin on Arduino Uno
void setup()

View File

@ -1,33 +1,39 @@
#include <MIDI.h>
MIDI_CREATE_DEFAULT_INSTANCE();
// -----------------------------------------------------------------------------
// This function will be automatically called when a NoteOn is received.
// It must be a void-returning function with the correct parameters,
// see documentation here:
// http://arduinomidilib.fortyseveneffects.com/a00022.html
void HandleNoteOn(byte channel, byte pitch, byte velocity)
void handleNoteOn(byte channel, byte pitch, byte velocity)
{
// Do whatever you want when you receive a Note On.
if (velocity == 0)
{
// This acts like a NoteOff. You can ask the library to call the NoteOff
// callback when receiving null-velocity NoteOn messages.
// See MIDI_HANDLE_NULL_VELOCITY_NOTE_ON_AS_NOTE_OFF in midi_Settings.h
}
// Do whatever you want when a note is pressed.
// Try to keep your callbacks short (no delays ect)
// otherwise it would slow down the loop() and have a bad impact
// on real-time performance.
}
void handleNoteOff(byte channel, byte pitch, byte velocity)
{
// Do something when the note is released.
// Note that NoteOn messages with 0 velocity are interpreted as NoteOffs.
}
// -----------------------------------------------------------------------------
void setup()
{
// Connect the HandleNoteOn function to the library,
// Connect the handleNoteOn function to the library,
// so it is called upon reception of a NoteOn.
MIDI.setHandleNoteOn(HandleNoteOn); // Put only the name of the function
MIDI.setHandleNoteOn(handleNoteOn); // Put only the name of the function
// Do the same for NoteOffs
MIDI.setHandleNoteOff(handleNoteOff);
// Initiate MIDI communications, listen to all channels
MIDI.begin(MIDI_CHANNEL_OMNI);

View File

@ -1,5 +1,9 @@
#include <MIDI.h>
MIDI_CREATE_DEFAULT_INSTANCE();
// -----------------------------------------------------------------------------
// This example shows the old way of checking for input messages.
// It's simpler to use the callbacks now, check out the dedicated example.

View File

@ -2,6 +2,8 @@
#include "noteList.h"
#include "pitches.h"
MIDI_CREATE_DEFAULT_INSTANCE();
#ifdef ARDUINO_SAM_DUE // Due has no tone function (yet), overriden to prevent build errors.
#define tone(...)
#define noTone(...)

View File

@ -4,6 +4,7 @@ import sys
import os
import shutil
import subprocess
import argparse
from pprint import pprint
from midi import *
from tester import *
@ -138,28 +139,42 @@ class ArduinoMidiLibrary:
# ------------------------------------------------------------------------------
def main():
midiInterface = MidiInterface()
tester = Tester(midiInterface)
midiInterface.listenerCallback = tester.handleMidiInput
tester.checkThru([Midi.NoteOn, 64, 80])
tester.checkThru([Midi.AfterTouchChannel, 1])
tester.checkThru([2])
tester.checkThru([3])
tester.checkThru([Midi.NoteOn, 64, 0])
tester.checkThru([65, 127])
tester.checkThru([65, 0])
tester.checkThru([66, 127])
tester.checkThru([66, 0])
info = "Validator script for the Arduino MIDI Library."
arg_parser = argparse.ArgumentParser(description = info)
#lib = ArduinoMidiLibrary()
#lib.install()
#if lib.validate():
# print('Validation passed')
#else:
# print('Validation failed')
arg_parser.add_argument('--compile', '-c',
action="store_true",
help="Test compilation of the example sketches")
arg_parser.add_argument('--runtime', '-r',
action="store_true",
help="Test runtime")
args = arg_parser.parse_args()
if args.compile:
lib = ArduinoMidiLibrary()
lib.install()
if lib.validate():
print('Compilation test passed')
else:
print('Compilation test failed')
if args.runtime:
midiInterface = MidiInterface()
tester = Tester(midiInterface)
midiInterface.listenerCallback = tester.handleMidiInput
tester.checkThru([Midi.NoteOn, 64, 80])
tester.checkThru([Midi.AfterTouchChannel, 1])
tester.checkThru([2])
tester.checkThru([3])
tester.checkThru([Midi.NoteOn, 64, 0])
tester.checkThru([65, 127])
tester.checkThru([65, 0])
tester.checkThru([66, 127])
tester.checkThru([66, 0])
# ------------------------------------------------------------------------------

View File

@ -23,8 +23,9 @@
#pragma once
#include "midi_Settings.h"
#include "midi_Defs.h"
#include "midi_Settings.h"
#include "midi_Message.h"
// -----------------------------------------------------------------------------
@ -131,7 +132,7 @@ public:
inline void setHandleProgramChange(void (*fptr)(byte channel, byte number));
inline void setHandleAfterTouchChannel(void (*fptr)(byte channel, byte pressure));
inline void setHandlePitchBend(void (*fptr)(byte channel, int bend));
inline void setHandleSystemExclusive(void (*fptr)(byte * array, byte size));
inline void setHandleSystemExclusive(void (*fptr)(byte * array, unsigned size));
inline void setHandleTimeCodeQuarterFrame(void (*fptr)(byte data));
inline void setHandleSongPosition(void (*fptr)(unsigned beats));
inline void setHandleSongSelect(void (*fptr)(byte songnumber));
@ -155,7 +156,7 @@ private:
void (*mProgramChangeCallback)(byte channel, byte);
void (*mAfterTouchChannelCallback)(byte channel, byte);
void (*mPitchBendCallback)(byte channel, int);
void (*mSystemExclusiveCallback)(byte * array, byte size);
void (*mSystemExclusiveCallback)(byte * array, unsigned size);
void (*mTimeCodeQuarterFrameCallback)(byte data);
void (*mSongPositionCallback)(unsigned beats);
void (*mSongSelectCallback)(byte songnumber);
@ -192,25 +193,22 @@ private:
bool mThruActivated : 1;
MidiFilterMode mThruFilterMode : 7;
private:
typedef Message<Settings::SysExMaxSize> MidiMessage;
private:
StatusByte mRunningStatus_RX;
StatusByte mRunningStatus_TX;
Channel mInputChannel;
byte mPendingMessage[3];
unsigned mPendingMessageExpectedLenght;
unsigned mPendingMessageIndex;
Message mMessage;
MidiMessage mMessage;
private:
inline StatusByte getStatus(MidiType inType,
Channel inChannel) const;
#if MIDI_USE_RUNNING_STATUS
private:
StatusByte mRunningStatus_TX;
#endif
private:
SerialPort& mSerial;
};

View File

@ -79,18 +79,10 @@ void MidiInterface<SerialPort, Settings>::begin(Channel inChannel)
mSerial.begin(Settings::BaudRate);
#endif
#if MIDI_BUILD_OUTPUT
if (Settings::UseRunningStatus)
{
mRunningStatus_TX = InvalidType;
}
#endif // MIDI_BUILD_OUTPUT
#if MIDI_BUILD_INPUT
mInputChannel = inChannel;
mRunningStatus_TX = InvalidType;
mRunningStatus_RX = InvalidType;
mPendingMessageIndex = 0;
mPendingMessageExpectedLenght = 0;
@ -100,25 +92,14 @@ void MidiInterface<SerialPort, Settings>::begin(Channel inChannel)
mMessage.data1 = 0;
mMessage.data2 = 0;
#endif // MIDI_BUILD_INPUT
#if (MIDI_BUILD_INPUT && MIDI_BUILD_OUTPUT && MIDI_BUILD_THRU) // Thru
mThruFilterMode = Full;
mThruActivated = true;
#endif // Thru
}
// -----------------------------------------------------------------------------
// Output
// -----------------------------------------------------------------------------
#if MIDI_BUILD_OUTPUT
/*! \addtogroup output
@{
*/
@ -459,15 +440,10 @@ StatusByte MidiInterface<SerialPort, Settings>::getStatus(MidiType inType,
return ((byte)inType | ((inChannel - 1) & 0x0f));
}
#endif // MIDI_BUILD_OUTPUT
// -----------------------------------------------------------------------------
// Input
// -----------------------------------------------------------------------------
#if MIDI_BUILD_INPUT
/*! \addtogroup input
@{
*/
@ -505,9 +481,7 @@ inline bool MidiInterface<SerialPort, Settings>::read(Channel inChannel)
launchCallback();
}
#if MIDI_BUILD_THRU
thruFilter(inChannel);
#endif
return channelMatch;
}
@ -604,8 +578,8 @@ bool MidiInterface<SerialPort, Settings>::parse()
case SystemExclusive:
// The message can be any lenght
// between 3 and MIDI_SYSEX_ARRAY_SIZE bytes
mPendingMessageExpectedLenght = MIDI_SYSEX_ARRAY_SIZE;
// between 3 and MidiMessage::sSysExMaxSize bytes
mPendingMessageExpectedLenght = MidiMessage::sSysExMaxSize;
mRunningStatus_RX = InvalidType;
mMessage.sysexArray[0] = SystemExclusive;
break;
@ -693,8 +667,8 @@ bool MidiInterface<SerialPort, Settings>::parse()
mMessage.type = SystemExclusive;
// Get length
mMessage.data1 = mPendingMessageIndex & 0xff;
mMessage.data2 = mPendingMessageIndex >> 8;
mMessage.data1 = mPendingMessageIndex & 0xff; // LSB
mMessage.data2 = mPendingMessageIndex >> 8; // MSB
mMessage.channel = 0;
mMessage.valid = true;
@ -725,7 +699,7 @@ bool MidiInterface<SerialPort, Settings>::parse()
{
// "FML" case: fall down here with an overflown SysEx..
// This means we received the last possible data byte that can fit
// the buffer. If this happens, try increasing MIDI_SYSEX_ARRAY_SIZE.
// the buffer. If this happens, try increasing MidiMessage::sSysExMaxSize.
if (mPendingMessage[0] == SystemExclusive)
{
resetInput();
@ -852,7 +826,7 @@ inline void MidiInterface<SerialPort, Settings>::resetInput()
Returns an enumerated type. @see MidiType
*/
template<class SerialPort, class Settings>
MidiType MidiInterface<SerialPort, Settings>::getType() const
inline MidiType MidiInterface<SerialPort, Settings>::getType() const
{
return mMessage.type;
}
@ -863,21 +837,21 @@ MidiType MidiInterface<SerialPort, Settings>::getType() const
For non-channel messages, this will return 0.
*/
template<class SerialPort, class Settings>
Channel MidiInterface<SerialPort, Settings>::getChannel() const
inline Channel MidiInterface<SerialPort, Settings>::getChannel() const
{
return mMessage.channel;
}
/*! \brief Get the first data byte of the last received message. */
template<class SerialPort, class Settings>
DataByte MidiInterface<SerialPort, Settings>::getData1() const
inline DataByte MidiInterface<SerialPort, Settings>::getData1() const
{
return mMessage.data1;
}
/*! \brief Get the second data byte of the last received message. */
template<class SerialPort, class Settings>
DataByte MidiInterface<SerialPort, Settings>::getData2() const
inline DataByte MidiInterface<SerialPort, Settings>::getData2() const
{
return mMessage.data2;
}
@ -887,7 +861,7 @@ DataByte MidiInterface<SerialPort, Settings>::getData2() const
@see getSysExArrayLength to get the array's length in bytes.
*/
template<class SerialPort, class Settings>
const byte* MidiInterface<SerialPort, Settings>::getSysExArray() const
inline const byte* MidiInterface<SerialPort, Settings>::getSysExArray() const
{
return mMessage.sysexArray;
}
@ -898,16 +872,14 @@ const byte* MidiInterface<SerialPort, Settings>::getSysExArray() const
\return The array's length, in bytes.
*/
template<class SerialPort, class Settings>
unsigned MidiInterface<SerialPort, Settings>::getSysExArrayLength() const
inline unsigned MidiInterface<SerialPort, Settings>::getSysExArrayLength() const
{
static const unsigned maxSize = Settings::SysExArraySize;
const unsigned size = (unsigned(mMessage.data2) << 8) | mMessage.data1;
return (size > maxSize) ? maxSize : size;
return mMessage.getSysExSize();
}
/*! \brief Check if a valid message is stored in the structure. */
template<class SerialPort, class Settings>
bool MidiInterface<SerialPort, Settings>::check() const
inline bool MidiInterface<SerialPort, Settings>::check() const
{
return mMessage.valid;
}
@ -915,7 +887,7 @@ bool MidiInterface<SerialPort, Settings>::check() const
// -----------------------------------------------------------------------------
template<class SerialPort, class Settings>
Channel MidiInterface<SerialPort, Settings>::getInputChannel() const
inline Channel MidiInterface<SerialPort, Settings>::getInputChannel() const
{
return mInputChannel;
}
@ -925,7 +897,7 @@ Channel MidiInterface<SerialPort, Settings>::getInputChannel() const
if you want to listen to all channels, and MIDI_CHANNEL_OFF to disable input.
*/
template<class SerialPort, class Settings>
void MidiInterface<SerialPort, Settings>::setInputChannel(Channel inChannel)
inline void MidiInterface<SerialPort, Settings>::setInputChannel(Channel inChannel)
{
mInputChannel = inChannel;
}
@ -980,8 +952,6 @@ bool MidiInterface<SerialPort, Settings>::isChannelMessage(MidiType inType)
// -----------------------------------------------------------------------------
#if MIDI_USE_CALLBACKS
/*! \addtogroup callbacks
@{
*/
@ -993,7 +963,7 @@ template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settin
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleProgramChange(void (*fptr)(byte channel, byte number)) { mProgramChangeCallback = fptr; }
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleAfterTouchChannel(void (*fptr)(byte channel, byte pressure)) { mAfterTouchChannelCallback = fptr; }
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandlePitchBend(void (*fptr)(byte channel, int bend)) { mPitchBendCallback = fptr; }
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleSystemExclusive(void (*fptr)(byte* array, byte size)) { mSystemExclusiveCallback = fptr; }
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleSystemExclusive(void (*fptr)(byte* array, unsigned size)) { mSystemExclusiveCallback = fptr; }
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleTimeCodeQuarterFrame(void (*fptr)(byte data)) { mTimeCodeQuarterFrameCallback = fptr; }
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleSongPosition(void (*fptr)(unsigned beats)) { mSongPositionCallback = fptr; }
template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleSongSelect(void (*fptr)(byte songnumber)) { mSongSelectCallback = fptr; }
@ -1066,7 +1036,7 @@ void MidiInterface<SerialPort, Settings>::launchCallback()
case AfterTouchChannel: if (mAfterTouchChannelCallback != 0) mAfterTouchChannelCallback(mMessage.channel, mMessage.data1); break;
case ProgramChange: if (mProgramChangeCallback != 0) mProgramChangeCallback(mMessage.channel, mMessage.data1); break;
case SystemExclusive: if (mSystemExclusiveCallback != 0) mSystemExclusiveCallback(mMessage.sysexArray, mMessage.data1); break;
case SystemExclusive: if (mSystemExclusiveCallback != 0) mSystemExclusiveCallback(mMessage.sysexArray, mMessage.getSysExSize()); break;
// Occasional messages
case TimeCodeQuarterFrame: if (mTimeCodeQuarterFrameCallback != 0) mTimeCodeQuarterFrameCallback(mMessage.data1); break;
@ -1081,19 +1051,12 @@ void MidiInterface<SerialPort, Settings>::launchCallback()
}
}
#endif // MIDI_USE_CALLBACKS
/*! @} */ // End of doc group MIDI Input
#endif // MIDI_BUILD_INPUT
// -----------------------------------------------------------------------------
// Thru
// -----------------------------------------------------------------------------
#if (MIDI_BUILD_INPUT && MIDI_BUILD_OUTPUT && MIDI_BUILD_THRU)
/*! \addtogroup thru
@{
*/
@ -1238,8 +1201,6 @@ void MidiInterface<SerialPort, Settings>::thruFilter(Channel inChannel)
}
}
#endif // MIDI_BUILD_THRU
// -----------------------------------------------------------------------------
END_MIDI_NAMESPACE

View File

@ -24,8 +24,13 @@
#pragma once
#include "midi_Namespace.h"
#include "midi_Settings.h"
#if ARDUINO
#include <Arduino.h>
#else
#include <inttypes.h>
typedef uint8_t byte;
#endif
BEGIN_MIDI_NAMESPACE
@ -40,7 +45,6 @@ BEGIN_MIDI_NAMESPACE
// -----------------------------------------------------------------------------
// Type definitions
typedef uint8_t byte;
typedef byte StatusByte;
typedef byte DataByte;
typedef byte Channel;
@ -155,48 +159,6 @@ enum MidiControlChangeNumber
PolyModeOn = 127
};
// -----------------------------------------------------------------------------
/*! The midimsg structure contains decoded data of a MIDI message
read from the serial port with read()
*/
struct Message
{
/*! The MIDI channel on which the message was recieved.
\n Value goes from 1 to 16.
*/
Channel channel;
/*! The type of the message
(see the MidiType enum for types reference)
*/
MidiType type;
/*! The first data byte.
\n Value goes from 0 to 127.
*/
DataByte data1;
/*! The second data byte.
If the message is only 2 bytes long, this one is null.
\n Value goes from 0 to 127.
*/
DataByte data2;
/*! System Exclusive dedicated byte array.
\n Array length is stocked on 16 bits,
in data1 (LSB) and data2 (MSB)
*/
DataByte sysexArray[MIDI_SYSEX_ARRAY_SIZE];
/*! This boolean indicates if the message is valid or not.
There is no channel consideration here,
validity means the message respects the MIDI norm.
*/
bool valid;
};
// -----------------------------------------------------------------------------
/*! \brief Create an instance of the library attached to a serial port.
@ -207,6 +169,19 @@ struct Message
#define MIDI_CREATE_INSTANCE(Type, SerialPort, Name) \
midi::MidiInterface<Type> Name((Type&)SerialPort);
#if defined(ARDUINO_SAM_DUE) || defined(USBCON)
// Leonardo, Due and other USB boards use Serial1 by default.
#define MIDI_CREATE_DEFAULT_INSTANCE() \
MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI);
#else
/*! \brief Create an instance of the library with default name, serial port
and settings, for compatibility with sketches written with pre-v4.2 MIDI Lib,
or if you don't bother using custom names, serial port or settings.
*/
#define MIDI_CREATE_DEFAULT_INSTANCE() \
MIDI_CREATE_INSTANCE(HardwareSerial, Serial, MIDI);
#endif
/*! \brief Create an instance of the library attached to a serial port with
custom settings.
@see DefaultSettings

81
src/midi_Message.h Normal file
View File

@ -0,0 +1,81 @@
/*!
* @file midi_Message.h
* Project Arduino MIDI Library
* @brief MIDI Library for the Arduino - Message struct definition
* @version 4.1
* @author Francois Best
* @date 11/06/14
* @license GPL v3.0 - Copyright Forty Seven Effects 2014
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "midi_Namespace.h"
#include "midi_Defs.h"
BEGIN_MIDI_NAMESPACE
/*! The Message structure contains decoded data of a MIDI message
read from the serial port with read()
*/
template<unsigned SysExMaxSize>
struct Message
{
/*! The maximum size for the System Exclusive array.
*/
static const unsigned sSysExMaxSize = SysExMaxSize;
/*! The MIDI channel on which the message was recieved.
\n Value goes from 1 to 16.
*/
Channel channel;
/*! The type of the message
(see the MidiType enum for types reference)
*/
MidiType type;
/*! The first data byte.
\n Value goes from 0 to 127.
*/
DataByte data1;
/*! The second data byte.
If the message is only 2 bytes long, this one is null.
\n Value goes from 0 to 127.
*/
DataByte data2;
/*! System Exclusive dedicated byte array.
\n Array length is stocked on 16 bits,
in data1 (LSB) and data2 (MSB)
*/
DataByte sysexArray[sSysExMaxSize];
/*! This boolean indicates if the message is valid or not.
There is no channel consideration here,
validity means the message respects the MIDI norm.
*/
bool valid;
inline unsigned getSysExSize() const
{
const unsigned size = unsigned(data2) << 8 | data1;
return size > sSysExMaxSize ? sSysExMaxSize : size;
}
};
END_MIDI_NAMESPACE

View File

@ -23,47 +23,16 @@
#pragma once
#include "midi_Namespace.h"
// -----------------------------------------------------------------------------
// Here are a few settings you can change to customize
// the library for your own project. You can for example
// choose to compile only parts of it so you gain flash
// space and optimise the speed of your sketch.
// -----------------------------------------------------------------------------
#include "midi_Defs.h"
// Compilation flags. Set them to 1 to build the associated feature
// (MIDI in, out, thru), or to 0 to disable the feature and save space.
// Note that thru can work only if input and output are enabled.
#define MIDI_BUILD_INPUT 1
#define MIDI_BUILD_OUTPUT 1
#define MIDI_BUILD_THRU 1
#define MIDI_USE_CALLBACKS 1
// -----------------------------------------------------------------------------
// Misc. options
// Running status enables short messages when sending multiple values
// of the same type and channel.
// Set to 0 if you have troubles controlling your hardware.
#define MIDI_USE_RUNNING_STATUS 1
// NoteOn with 0 velocity should be handled as NoteOf.
// Set to 1 to get NoteOff events when receiving null-velocity NoteOn messages.
// Set to 0 to get NoteOn events when receiving null-velocity NoteOn messages.
#define MIDI_HANDLE_NULL_VELOCITY_NOTE_ON_AS_NOTE_OFF 1
// Setting this to 1 will make MIDI.read parse only one byte of data for each
// call when data is available. This can speed up your application if receiving
// a lot of traffic, but might induce MIDI Thru and treatment latency.
#define MIDI_USE_1BYTE_PARSING 1
#define MIDI_BAUDRATE 31250
#define MIDI_SYSEX_ARRAY_SIZE 255 // Maximum size is 65535 bytes.
#define MIDI_BUILD_INPUT 1
#define MIDI_BUILD_OUTPUT 1
#define MIDI_BUILD_THRU 1
#define MIDI_USE_CALLBACKS 1
// -----------------------------------------------------------------------------
@ -82,11 +51,33 @@ BEGIN_MIDI_NAMESPACE
*/
struct DefaultSettings
{
static const bool UseRunningStatus = true;
static const bool HandleNullVelocityNoteOnAsNoteOff = true;
static const bool Use1ByteParsing = true;
static const unsigned BaudRate = 31250;
static const unsigned SysExArraySize = 128;
/*! Running status enables short messages when sending multiple values
of the same type and channel.\n
Set to 0 if you have troubles controlling your hardware.
*/
static const bool UseRunningStatus = true;
/* NoteOn with 0 velocity should be handled as NoteOf.\n
Set to 1 to get NoteOff events when receiving null-velocity NoteOn messages.\n
Set to 0 to get NoteOn events when receiving null-velocity NoteOn messages.
*/
static const bool HandleNullVelocityNoteOnAsNoteOff = true;
// Setting this to 1 will make MIDI.read parse only one byte of data for each
// call when data is available. This can speed up your application if receiving
// a lot of traffic, but might induce MIDI Thru and treatment latency.
static const bool Use1ByteParsing = true;
/*! Override the default MIDI baudrate to transmit over USB serial, to
a decoding program such as Hairless MIDI (set baudrate to 115200)\n
http://projectgus.github.io/hairless-midiserial/
*/
static const long BaudRate = 31250;
/*! Maximum size of SysEx receivable. Decrease to save RAM if you don't expect
to receive SysEx, or adjust accordingly.
*/
static const unsigned SysExMaxSize = 128;
};
END_MIDI_NAMESPACE