Merge branch 'settings' into dev

This commit is contained in:
Francois Best 2014-06-11 08:02:57 +02:00
commit 1ff874c70d
5 changed files with 258 additions and 300 deletions

View File

@ -25,27 +25,6 @@
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#if !(MIDI_BUILD_INPUT) && !(MIDI_BUILD_OUTPUT)
# error To use MIDI, you need to enable at least input or output.
#endif
#if MIDI_BUILD_THRU && !(MIDI_BUILD_OUTPUT)
# error For thru to work, you need to enable output.
#endif
#if MIDI_BUILD_THRU && !(MIDI_BUILD_INPUT)
# error For thru to work, you need to enable input.
#endif
// -----------------------------------------------------------------------------
#if MIDI_AUTO_INSTANCIATE && defined(ARDUINO)
MIDI_CREATE_INSTANCE(MIDI_DEFAULT_SERIAL_CLASS,
MIDI_DEFAULT_SERIAL_PORT,
MIDI);
#endif
// -----------------------------------------------------------------------------
BEGIN_MIDI_NAMESPACE BEGIN_MIDI_NAMESPACE
/*! \brief Encode System Exclusive messages. /*! \brief Encode System Exclusive messages.

View File

@ -26,10 +26,6 @@
#include "midi_Settings.h" #include "midi_Settings.h"
#include "midi_Defs.h" #include "midi_Defs.h"
#ifdef FSE_AVR
#include <ak47.h>
#endif
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
BEGIN_MIDI_NAMESPACE BEGIN_MIDI_NAMESPACE
@ -40,12 +36,12 @@ the hardware interface, meaning you can use HardwareSerial, SoftwareSerial
or ak47's Uart classes. The only requirement is that the class implements or ak47's Uart classes. The only requirement is that the class implements
the begin, read, write and available methods. the begin, read, write and available methods.
*/ */
template<class SerialPort> template<class SerialPort, class Settings = DefaultSettings>
class MidiInterface class MidiInterface
{ {
public: public:
MidiInterface(SerialPort& inSerial); inline MidiInterface(SerialPort& inSerial);
~MidiInterface(); inline ~MidiInterface();
public: public:
void begin(Channel inChannel = 1); void begin(Channel inChannel = 1);
@ -53,8 +49,6 @@ public:
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// MIDI Output // MIDI Output
#if MIDI_BUILD_OUTPUT
public: public:
inline void sendNoteOn(DataByte inNoteNumber, inline void sendNoteOn(DataByte inNoteNumber,
DataByte inVelocity, DataByte inVelocity,
@ -100,17 +94,9 @@ public:
DataByte inData2, DataByte inData2,
Channel inChannel); Channel inChannel);
private:
inline StatusByte getStatus(MidiType inType,
Channel inChannel) const;
#endif // MIDI_BUILD_OUTPUT
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// MIDI Input // MIDI Input
#if MIDI_BUILD_INPUT
public: public:
inline bool read(); inline bool read();
inline bool read(Channel inChannel); inline bool read(Channel inChannel);
@ -133,25 +119,10 @@ public:
static inline Channel getChannelFromStatusByte(byte inStatus); static inline Channel getChannelFromStatusByte(byte inStatus);
static inline bool isChannelMessage(MidiType inType); static inline bool isChannelMessage(MidiType inType);
private:
bool parse();
inline void handleNullVelocityNoteOnAsNoteOff();
inline bool inputFilter(Channel inChannel);
inline void resetInput();
private:
StatusByte mRunningStatus_RX;
Channel mInputChannel;
byte mPendingMessage[3];
unsigned mPendingMessageExpectedLenght;
unsigned mPendingMessageIndex;
Message mMessage;
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Input Callbacks // Input Callbacks
#if MIDI_USE_CALLBACKS
public: public:
inline void setHandleNoteOff(void (*fptr)(byte channel, byte note, byte velocity)); inline void setHandleNoteOff(void (*fptr)(byte channel, byte note, byte velocity));
inline void setHandleNoteOn(void (*fptr)(byte channel, byte note, byte velocity)); inline void setHandleNoteOn(void (*fptr)(byte channel, byte note, byte velocity));
@ -196,14 +167,9 @@ private:
void (*mActiveSensingCallback)(void); void (*mActiveSensingCallback)(void);
void (*mSystemResetCallback)(void); void (*mSystemResetCallback)(void);
#endif // MIDI_USE_CALLBACKS
#endif // MIDI_BUILD_INPUT
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// MIDI Soft Thru // MIDI Soft Thru
#if MIDI_BUILD_THRU
public: public:
inline MidiFilterMode getFilterMode() const; inline MidiFilterMode getFilterMode() const;
inline bool getThruState() const; inline bool getThruState() const;
@ -216,11 +182,28 @@ public:
private: private:
void thruFilter(byte inChannel); void thruFilter(byte inChannel);
private:
bool parse();
inline void handleNullVelocityNoteOnAsNoteOff();
inline bool inputFilter(Channel inChannel);
inline void resetInput();
private: private:
bool mThruActivated : 1; bool mThruActivated : 1;
MidiFilterMode mThruFilterMode : 7; MidiFilterMode mThruFilterMode : 7;
#endif // MIDI_BUILD_THRU private:
StatusByte mRunningStatus_RX;
Channel mInputChannel;
byte mPendingMessage[3];
unsigned mPendingMessageExpectedLenght;
unsigned mPendingMessageIndex;
Message mMessage;
private:
inline StatusByte getStatus(MidiType inType,
Channel inChannel) const;
#if MIDI_USE_RUNNING_STATUS #if MIDI_USE_RUNNING_STATUS
@ -241,10 +224,4 @@ END_MIDI_NAMESPACE
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#if MIDI_AUTO_INSTANCIATE && defined(ARDUINO)
extern MIDI_NAMESPACE::MidiInterface<MIDI_DEFAULT_SERIAL_CLASS> MIDI;
#endif
// -----------------------------------------------------------------------------
#include "MIDI.hpp" #include "MIDI.hpp"

View File

@ -26,8 +26,8 @@
BEGIN_MIDI_NAMESPACE BEGIN_MIDI_NAMESPACE
/// \brief Constructor for MidiInterface. /// \brief Constructor for MidiInterface.
template<class SerialPort> template<class SerialPort, class Settings>
MidiInterface<SerialPort>::MidiInterface(SerialPort& inSerial) inline MidiInterface<SerialPort, Settings>::MidiInterface(SerialPort& inSerial)
: mSerial(inSerial) : mSerial(inSerial)
{ {
#if MIDI_BUILD_INPUT && MIDI_USE_CALLBACKS #if MIDI_BUILD_INPUT && MIDI_USE_CALLBACKS
@ -56,8 +56,8 @@ MidiInterface<SerialPort>::MidiInterface(SerialPort& inSerial)
This is not really useful for the Arduino, as it is never called... This is not really useful for the Arduino, as it is never called...
*/ */
template<class SerialPort> template<class SerialPort, class Settings>
MidiInterface<SerialPort>::~MidiInterface() inline MidiInterface<SerialPort, Settings>::~MidiInterface()
{ {
} }
@ -69,21 +69,22 @@ MidiInterface<SerialPort>::~MidiInterface()
- Input channel set to 1 if no value is specified - Input channel set to 1 if no value is specified
- Full thru mirroring - Full thru mirroring
*/ */
template<class SerialPort> template<class SerialPort, class Settings>
void MidiInterface<SerialPort>::begin(Channel inChannel) void MidiInterface<SerialPort, Settings>::begin(Channel inChannel)
{ {
// Initialise the Serial port // Initialise the Serial port
#if defined(ARDUINO) #if defined(FSE_AVR)
mSerial.begin(MIDI_BAUDRATE); mSerial. template open<Settings::BaudRate>();
#elif defined(FSE_AVR) #else
mSerial. template open<MIDI_BAUDRATE>(); mSerial.begin(Settings::BaudRate);
#endif #endif
#if MIDI_BUILD_OUTPUT && MIDI_USE_RUNNING_STATUS #if MIDI_BUILD_OUTPUT
if (Settings::UseRunningStatus)
{
mRunningStatus_TX = InvalidType; mRunningStatus_TX = InvalidType;
}
#endif // MIDI_BUILD_OUTPUT && MIDI_USE_RUNNING_STATUS #endif // MIDI_BUILD_OUTPUT
#if MIDI_BUILD_INPUT #if MIDI_BUILD_INPUT
@ -133,8 +134,8 @@ void MidiInterface<SerialPort>::begin(Channel inChannel)
This is an internal method, use it only if you need to send raw data This is an internal method, use it only if you need to send raw data
from your code, at your own risks. from your code, at your own risks.
*/ */
template<class SerialPort> template<class SerialPort, class Settings>
void MidiInterface<SerialPort>::send(MidiType inType, void MidiInterface<SerialPort, Settings>::send(MidiType inType,
DataByte inData1, DataByte inData1,
DataByte inData2, DataByte inData2,
Channel inChannel) Channel inChannel)
@ -142,13 +143,12 @@ void MidiInterface<SerialPort>::send(MidiType inType,
// Then test if channel is valid // Then test if channel is valid
if (inChannel >= MIDI_CHANNEL_OFF || if (inChannel >= MIDI_CHANNEL_OFF ||
inChannel == MIDI_CHANNEL_OMNI || inChannel == MIDI_CHANNEL_OMNI ||
inType < NoteOff) inType < 0x80)
{
if (Settings::UseRunningStatus)
{ {
#if MIDI_USE_RUNNING_STATUS
mRunningStatus_TX = InvalidType; mRunningStatus_TX = InvalidType;
#endif }
return; // Don't send anything return; // Don't send anything
} }
@ -160,29 +160,33 @@ void MidiInterface<SerialPort>::send(MidiType inType,
const StatusByte status = getStatus(inType, inChannel); const StatusByte status = getStatus(inType, inChannel);
#if MIDI_USE_RUNNING_STATUS if (Settings::UseRunningStatus)
// Check Running Status {
if (mRunningStatus_TX != status) if (mRunningStatus_TX != status)
{ {
// New message, memorise and send header // New message, memorise and send header
mRunningStatus_TX = status; mRunningStatus_TX = status;
mSerial.write(mRunningStatus_TX); mSerial.write(mRunningStatus_TX);
} }
#else }
else
{
// Don't care about running status, send the status byte. // Don't care about running status, send the status byte.
mSerial.write(status); mSerial.write(status);
#endif }
// Then send data // Then send data
mSerial.write(inData1); mSerial.write(inData1);
if (inType != ProgramChange && inType != AfterTouchChannel) if (inType != ProgramChange && inType != AfterTouchChannel)
{
mSerial.write(inData2); mSerial.write(inData2);
}
return;
} }
else if (inType >= TuneRequest && inType <= SystemReset) else if (inType >= TuneRequest && inType <= SystemReset)
{
sendRealTime(inType); // System Real-time and 1 byte. sendRealTime(inType); // System Real-time and 1 byte.
} }
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -195,8 +199,8 @@ void MidiInterface<SerialPort>::send(MidiType inType,
Take a look at the values, names and frequencies of notes here: Take a look at the values, names and frequencies of notes here:
http://www.phys.unsw.edu.au/jw/notes.html http://www.phys.unsw.edu.au/jw/notes.html
*/ */
template<class SerialPort> template<class SerialPort, class Settings>
void MidiInterface<SerialPort>::sendNoteOn(DataByte inNoteNumber, void MidiInterface<SerialPort, Settings>::sendNoteOn(DataByte inNoteNumber,
DataByte inVelocity, DataByte inVelocity,
Channel inChannel) Channel inChannel)
{ {
@ -210,12 +214,12 @@ void MidiInterface<SerialPort>::sendNoteOn(DataByte inNoteNumber,
Note: you can send NoteOn with zero velocity to make a NoteOff, this is based Note: you can send NoteOn with zero velocity to make a NoteOff, this is based
on the Running Status principle, to avoid sending status messages and thus on the Running Status principle, to avoid sending status messages and thus
sending only NoteOn data. This method will always send a real NoteOff message. sending only NoteOn data. sendNoteOff will always send a real NoteOff message.
Take a look at the values, names and frequencies of notes here: Take a look at the values, names and frequencies of notes here:
http://www.phys.unsw.edu.au/jw/notes.html http://www.phys.unsw.edu.au/jw/notes.html
*/ */
template<class SerialPort> template<class SerialPort, class Settings>
void MidiInterface<SerialPort>::sendNoteOff(DataByte inNoteNumber, void MidiInterface<SerialPort, Settings>::sendNoteOff(DataByte inNoteNumber,
DataByte inVelocity, DataByte inVelocity,
Channel inChannel) Channel inChannel)
{ {
@ -226,8 +230,8 @@ void MidiInterface<SerialPort>::sendNoteOff(DataByte inNoteNumber,
\param inProgramNumber The Program to select (0 to 127). \param inProgramNumber The Program to select (0 to 127).
\param inChannel The channel on which the message will be sent (1 to 16). \param inChannel The channel on which the message will be sent (1 to 16).
*/ */
template<class SerialPort> template<class SerialPort, class Settings>
void MidiInterface<SerialPort>::sendProgramChange(DataByte inProgramNumber, void MidiInterface<SerialPort, Settings>::sendProgramChange(DataByte inProgramNumber,
Channel inChannel) Channel inChannel)
{ {
send(ProgramChange, inProgramNumber, 0, inChannel); send(ProgramChange, inProgramNumber, 0, inChannel);
@ -239,8 +243,8 @@ void MidiInterface<SerialPort>::sendProgramChange(DataByte inProgramNumber,
\param inChannel The channel on which the message will be sent (1 to 16). \param inChannel The channel on which the message will be sent (1 to 16).
@see MidiControlChangeNumber @see MidiControlChangeNumber
*/ */
template<class SerialPort> template<class SerialPort, class Settings>
void MidiInterface<SerialPort>::sendControlChange(DataByte inControlNumber, void MidiInterface<SerialPort, Settings>::sendControlChange(DataByte inControlNumber,
DataByte inControlValue, DataByte inControlValue,
Channel inChannel) Channel inChannel)
{ {
@ -252,8 +256,8 @@ void MidiInterface<SerialPort>::sendControlChange(DataByte inControlNumber,
\param inPressure The amount of AfterTouch to apply (0 to 127). \param inPressure The amount of AfterTouch to apply (0 to 127).
\param inChannel The channel on which the message will be sent (1 to 16). \param inChannel The channel on which the message will be sent (1 to 16).
*/ */
template<class SerialPort> template<class SerialPort, class Settings>
void MidiInterface<SerialPort>::sendPolyPressure(DataByte inNoteNumber, void MidiInterface<SerialPort, Settings>::sendPolyPressure(DataByte inNoteNumber,
DataByte inPressure, DataByte inPressure,
Channel inChannel) Channel inChannel)
{ {
@ -264,8 +268,8 @@ void MidiInterface<SerialPort>::sendPolyPressure(DataByte inNoteNumber,
\param inPressure The amount of AfterTouch to apply to all notes. \param inPressure The amount of AfterTouch to apply to all notes.
\param inChannel The channel on which the message will be sent (1 to 16). \param inChannel The channel on which the message will be sent (1 to 16).
*/ */
template<class SerialPort> template<class SerialPort, class Settings>
void MidiInterface<SerialPort>::sendAfterTouch(DataByte inPressure, void MidiInterface<SerialPort, Settings>::sendAfterTouch(DataByte inPressure,
Channel inChannel) Channel inChannel)
{ {
send(AfterTouchChannel, inPressure, 0, inChannel); send(AfterTouchChannel, inPressure, 0, inChannel);
@ -277,8 +281,8 @@ void MidiInterface<SerialPort>::sendAfterTouch(DataByte inPressure,
center value is 0. center value is 0.
\param inChannel The channel on which the message will be sent (1 to 16). \param inChannel The channel on which the message will be sent (1 to 16).
*/ */
template<class SerialPort> template<class SerialPort, class Settings>
void MidiInterface<SerialPort>::sendPitchBend(int inPitchValue, void MidiInterface<SerialPort, Settings>::sendPitchBend(int inPitchValue,
Channel inChannel) Channel inChannel)
{ {
const unsigned bend = inPitchValue - MIDI_PITCHBEND_MIN; const unsigned bend = inPitchValue - MIDI_PITCHBEND_MIN;
@ -292,11 +296,11 @@ void MidiInterface<SerialPort>::sendPitchBend(int inPitchValue,
and +1.0f (max upwards bend), center value is 0.0f. and +1.0f (max upwards bend), center value is 0.0f.
\param inChannel The channel on which the message will be sent (1 to 16). \param inChannel The channel on which the message will be sent (1 to 16).
*/ */
template<class SerialPort> template<class SerialPort, class Settings>
void MidiInterface<SerialPort>::sendPitchBend(double inPitchValue, void MidiInterface<SerialPort, Settings>::sendPitchBend(double inPitchValue,
Channel inChannel) Channel inChannel)
{ {
const int value = inPitchValue * MIDI_PITCHBEND_MAX; const int value = inPitchValue * MIDI_PITCHBEND_MAX * Settings::Toto;
sendPitchBend(value, inChannel); sendPitchBend(value, inChannel);
} }
@ -309,29 +313,32 @@ void MidiInterface<SerialPort>::sendPitchBend(double inPitchValue,
default value for ArrayContainsBoundaries is set to 'false' for compatibility default value for ArrayContainsBoundaries is set to 'false' for compatibility
with previous versions of the library. with previous versions of the library.
*/ */
template<class SerialPort> template<class SerialPort, class Settings>
void MidiInterface<SerialPort>::sendSysEx(unsigned inLength, void MidiInterface<SerialPort, Settings>::sendSysEx(unsigned inLength,
const byte* inArray, const byte* inArray,
bool inArrayContainsBoundaries) bool inArrayContainsBoundaries)
{ {
if (inArrayContainsBoundaries == false) const bool writeBeginEndBytes = !inArrayContainsBoundaries;
if (writeBeginEndBytes)
{ {
mSerial.write(0xf0); mSerial.write(0xf0);
}
for (unsigned i = 0; i < inLength; ++i) for (unsigned i = 0; i < inLength; ++i)
{
mSerial.write(inArray[i]); mSerial.write(inArray[i]);
}
if (writeBeginEndBytes)
{
mSerial.write(0xf7); mSerial.write(0xf7);
} }
else
{
for (unsigned i = 0; i < inLength; ++i)
mSerial.write(inArray[i]);
}
#if MIDI_USE_RUNNING_STATUS if (Settings::UseRunningStatus)
{
mRunningStatus_TX = InvalidType; mRunningStatus_TX = InvalidType;
#endif }
} }
/*! \brief Send a Tune Request message. /*! \brief Send a Tune Request message.
@ -339,8 +346,8 @@ void MidiInterface<SerialPort>::sendSysEx(unsigned inLength,
When a MIDI unit receives this message, When a MIDI unit receives this message,
it should tune its oscillators (if equipped with any). it should tune its oscillators (if equipped with any).
*/ */
template<class SerialPort> template<class SerialPort, class Settings>
void MidiInterface<SerialPort>::sendTuneRequest() void MidiInterface<SerialPort, Settings>::sendTuneRequest()
{ {
sendRealTime(TuneRequest); sendRealTime(TuneRequest);
} }
@ -351,8 +358,8 @@ void MidiInterface<SerialPort>::sendTuneRequest()
\param inValuesNibble MTC data \param inValuesNibble MTC data
See MIDI Specification for more information. See MIDI Specification for more information.
*/ */
template<class SerialPort> template<class SerialPort, class Settings>
void MidiInterface<SerialPort>::sendTimeCodeQuarterFrame(DataByte inTypeNibble, void MidiInterface<SerialPort, Settings>::sendTimeCodeQuarterFrame(DataByte inTypeNibble,
DataByte inValuesNibble) DataByte inValuesNibble)
{ {
const byte data = (((inTypeNibble & 0x07) << 4) | (inValuesNibble & 0x0f)); const byte data = (((inTypeNibble & 0x07) << 4) | (inValuesNibble & 0x0f));
@ -365,42 +372,45 @@ void MidiInterface<SerialPort>::sendTimeCodeQuarterFrame(DataByte inTypeNibble,
\param inData if you want to encode directly the nibbles in your program, \param inData if you want to encode directly the nibbles in your program,
you can send the byte here. you can send the byte here.
*/ */
template<class SerialPort> template<class SerialPort, class Settings>
void MidiInterface<SerialPort>::sendTimeCodeQuarterFrame(DataByte inData) void MidiInterface<SerialPort, Settings>::sendTimeCodeQuarterFrame(DataByte inData)
{ {
mSerial.write((byte)TimeCodeQuarterFrame); mSerial.write((byte)TimeCodeQuarterFrame);
mSerial.write(inData); mSerial.write(inData);
#if MIDI_USE_RUNNING_STATUS if (Settings::UseRunningStatus)
{
mRunningStatus_TX = InvalidType; mRunningStatus_TX = InvalidType;
#endif }
} }
/*! \brief Send a Song Position Pointer message. /*! \brief Send a Song Position Pointer message.
\param inBeats The number of beats since the start of the song. \param inBeats The number of beats since the start of the song.
*/ */
template<class SerialPort> template<class SerialPort, class Settings>
void MidiInterface<SerialPort>::sendSongPosition(unsigned inBeats) void MidiInterface<SerialPort, Settings>::sendSongPosition(unsigned inBeats)
{ {
mSerial.write((byte)SongPosition); mSerial.write((byte)SongPosition);
mSerial.write(inBeats & 0x7f); mSerial.write(inBeats & 0x7f);
mSerial.write((inBeats >> 7) & 0x7f); mSerial.write((inBeats >> 7) & 0x7f);
#if MIDI_USE_RUNNING_STATUS if (Settings::UseRunningStatus)
{
mRunningStatus_TX = InvalidType; mRunningStatus_TX = InvalidType;
#endif }
} }
/*! \brief Send a Song Select message */ /*! \brief Send a Song Select message */
template<class SerialPort> template<class SerialPort, class Settings>
void MidiInterface<SerialPort>::sendSongSelect(DataByte inSongNumber) void MidiInterface<SerialPort, Settings>::sendSongSelect(DataByte inSongNumber)
{ {
mSerial.write((byte)SongSelect); mSerial.write((byte)SongSelect);
mSerial.write(inSongNumber & 0x7f); mSerial.write(inSongNumber & 0x7f);
#if MIDI_USE_RUNNING_STATUS if (Settings::UseRunningStatus)
{
mRunningStatus_TX = InvalidType; mRunningStatus_TX = InvalidType;
#endif }
} }
/*! \brief Send a Real Time (one byte) message. /*! \brief Send a Real Time (one byte) message.
@ -410,8 +420,8 @@ void MidiInterface<SerialPort>::sendSongSelect(DataByte inSongNumber)
You can also send a Tune Request with this method. You can also send a Tune Request with this method.
@see MidiType @see MidiType
*/ */
template<class SerialPort> template<class SerialPort, class Settings>
void MidiInterface<SerialPort>::sendRealTime(MidiType inType) void MidiInterface<SerialPort, Settings>::sendRealTime(MidiType inType)
{ {
switch (inType) switch (inType)
{ {
@ -432,17 +442,18 @@ void MidiInterface<SerialPort>::sendRealTime(MidiType inType)
// Do not cancel Running Status for real-time messages as they can be // Do not cancel Running Status for real-time messages as they can be
// interleaved within any message. Though, TuneRequest can be sent here, // interleaved within any message. Though, TuneRequest can be sent here,
// and as it is a System Common message, it must reset Running Status. // and as it is a System Common message, it must reset Running Status.
#if MIDI_USE_RUNNING_STATUS if (Settings::UseRunningStatus && inType == TuneRequest)
if (inType == TuneRequest) mRunningStatus_TX = InvalidType; {
#endif mRunningStatus_TX = InvalidType;
}
} }
/*! @} */ // End of doc group MIDI Output /*! @} */ // End of doc group MIDI Output
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
template<class SerialPort> template<class SerialPort, class Settings>
StatusByte MidiInterface<SerialPort>::getStatus(MidiType inType, StatusByte MidiInterface<SerialPort, Settings>::getStatus(MidiType inType,
Channel inChannel) const Channel inChannel) const
{ {
return ((byte)inType | ((inChannel - 1) & 0x0f)); return ((byte)inType | ((inChannel - 1) & 0x0f));
@ -469,16 +480,16 @@ StatusByte MidiInterface<SerialPort>::getStatus(MidiType inType,
it is sent back on the MIDI output. it is sent back on the MIDI output.
@see see setInputChannel() @see see setInputChannel()
*/ */
template<class SerialPort> template<class SerialPort, class Settings>
inline bool MidiInterface<SerialPort>::read() inline bool MidiInterface<SerialPort, Settings>::read()
{ {
return read(mInputChannel); return read(mInputChannel);
} }
/*! \brief Read messages on a specified channel. /*! \brief Read messages on a specified channel.
*/ */
template<class SerialPort> template<class SerialPort, class Settings>
inline bool MidiInterface<SerialPort>::read(Channel inChannel) inline bool MidiInterface<SerialPort, Settings>::read(Channel inChannel)
{ {
if (inChannel >= MIDI_CHANNEL_OFF) if (inChannel >= MIDI_CHANNEL_OFF)
return false; // MIDI Input disabled. return false; // MIDI Input disabled.
@ -504,8 +515,8 @@ inline bool MidiInterface<SerialPort>::read(Channel inChannel)
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Private method: MIDI parser // Private method: MIDI parser
template<class SerialPort> template<class SerialPort, class Settings>
bool MidiInterface<SerialPort>::parse() bool MidiInterface<SerialPort, Settings>::parse()
{ {
if (mSerial.available() == 0) if (mSerial.available() == 0)
// No data available. // No data available.
@ -768,33 +779,34 @@ bool MidiInterface<SerialPort>::parse()
// Then update the index of the pending message. // Then update the index of the pending message.
mPendingMessageIndex++; mPendingMessageIndex++;
#if USE_1BYTE_PARSING if (Settings::Use1ByteParsing)
{
// Message is not complete. // Message is not complete.
return false; return false;
#else }
// Call the parser recursively else
// to parse the rest of the message. {
// Call the parser recursively to parse the rest of the message.
return parse(); return parse();
#endif }
} }
} }
} }
// Private method, see midi_Settings.h for documentation // Private method, see midi_Settings.h for documentation
template<class SerialPort> template<class SerialPort, class Settings>
inline void MidiInterface<SerialPort>::handleNullVelocityNoteOnAsNoteOff() inline void MidiInterface<SerialPort, Settings>::handleNullVelocityNoteOnAsNoteOff()
{ {
#if MIDI_HANDLE_NULL_VELOCITY_NOTE_ON_AS_NOTE_OFF if (Settings::HandleNullVelocityNoteOnAsNoteOff &&
if (getType() == NoteOn && getData2() == 0) getType() == NoteOn && getData2() == 0)
{ {
mMessage.type = NoteOff; mMessage.type = NoteOff;
} }
#endif
} }
// Private method: check if the received message is on the listened channel // Private method: check if the received message is on the listened channel
template<class SerialPort> template<class SerialPort, class Settings>
inline bool MidiInterface<SerialPort>::inputFilter(Channel inChannel) inline bool MidiInterface<SerialPort, Settings>::inputFilter(Channel inChannel)
{ {
// This method handles recognition of channel // This method handles recognition of channel
// (to know if the message is destinated to the Arduino) // (to know if the message is destinated to the Arduino)
@ -825,8 +837,8 @@ inline bool MidiInterface<SerialPort>::inputFilter(Channel inChannel)
} }
// Private method: reset input attributes // Private method: reset input attributes
template<class SerialPort> template<class SerialPort, class Settings>
inline void MidiInterface<SerialPort>::resetInput() inline void MidiInterface<SerialPort, Settings>::resetInput()
{ {
mPendingMessageIndex = 0; mPendingMessageIndex = 0;
mPendingMessageExpectedLenght = 0; mPendingMessageExpectedLenght = 0;
@ -839,8 +851,8 @@ inline void MidiInterface<SerialPort>::resetInput()
Returns an enumerated type. @see MidiType Returns an enumerated type. @see MidiType
*/ */
template<class SerialPort> template<class SerialPort, class Settings>
MidiType MidiInterface<SerialPort>::getType() const MidiType MidiInterface<SerialPort, Settings>::getType() const
{ {
return mMessage.type; return mMessage.type;
} }
@ -850,22 +862,22 @@ MidiType MidiInterface<SerialPort>::getType() const
\return Channel range is 1 to 16. \return Channel range is 1 to 16.
For non-channel messages, this will return 0. For non-channel messages, this will return 0.
*/ */
template<class SerialPort> template<class SerialPort, class Settings>
Channel MidiInterface<SerialPort>::getChannel() const Channel MidiInterface<SerialPort, Settings>::getChannel() const
{ {
return mMessage.channel; return mMessage.channel;
} }
/*! \brief Get the first data byte of the last received message. */ /*! \brief Get the first data byte of the last received message. */
template<class SerialPort> template<class SerialPort, class Settings>
DataByte MidiInterface<SerialPort>::getData1() const DataByte MidiInterface<SerialPort, Settings>::getData1() const
{ {
return mMessage.data1; return mMessage.data1;
} }
/*! \brief Get the second data byte of the last received message. */ /*! \brief Get the second data byte of the last received message. */
template<class SerialPort> template<class SerialPort, class Settings>
DataByte MidiInterface<SerialPort>::getData2() const DataByte MidiInterface<SerialPort, Settings>::getData2() const
{ {
return mMessage.data2; return mMessage.data2;
} }
@ -874,8 +886,8 @@ DataByte MidiInterface<SerialPort>::getData2() const
@see getSysExArrayLength to get the array's length in bytes. @see getSysExArrayLength to get the array's length in bytes.
*/ */
template<class SerialPort> template<class SerialPort, class Settings>
const byte* MidiInterface<SerialPort>::getSysExArray() const const byte* MidiInterface<SerialPort, Settings>::getSysExArray() const
{ {
return mMessage.sysexArray; return mMessage.sysexArray;
} }
@ -885,24 +897,25 @@ const byte* MidiInterface<SerialPort>::getSysExArray() const
It is coded using data1 as LSB and data2 as MSB. It is coded using data1 as LSB and data2 as MSB.
\return The array's length, in bytes. \return The array's length, in bytes.
*/ */
template<class SerialPort> template<class SerialPort, class Settings>
unsigned MidiInterface<SerialPort>::getSysExArrayLength() const unsigned MidiInterface<SerialPort, Settings>::getSysExArrayLength() const
{ {
const unsigned size = ((unsigned)(mMessage.data2) << 8) | mMessage.data1; static const unsigned maxSize = Settings::SysExArraySize;
return (size > MIDI_SYSEX_ARRAY_SIZE) ? MIDI_SYSEX_ARRAY_SIZE : size; const unsigned size = (unsigned(mMessage.data2) << 8) | mMessage.data1;
return (size > maxSize) ? maxSize : size;
} }
/*! \brief Check if a valid message is stored in the structure. */ /*! \brief Check if a valid message is stored in the structure. */
template<class SerialPort> template<class SerialPort, class Settings>
bool MidiInterface<SerialPort>::check() const bool MidiInterface<SerialPort, Settings>::check() const
{ {
return mMessage.valid; return mMessage.valid;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
template<class SerialPort> template<class SerialPort, class Settings>
Channel MidiInterface<SerialPort>::getInputChannel() const Channel MidiInterface<SerialPort, Settings>::getInputChannel() const
{ {
return mInputChannel; return mInputChannel;
} }
@ -911,8 +924,8 @@ Channel MidiInterface<SerialPort>::getInputChannel() const
\param inChannel the channel value. Valid values are 1 to 16, MIDI_CHANNEL_OMNI \param inChannel the channel value. Valid values are 1 to 16, MIDI_CHANNEL_OMNI
if you want to listen to all channels, and MIDI_CHANNEL_OFF to disable input. if you want to listen to all channels, and MIDI_CHANNEL_OFF to disable input.
*/ */
template<class SerialPort> template<class SerialPort, class Settings>
void MidiInterface<SerialPort>::setInputChannel(Channel inChannel) void MidiInterface<SerialPort, Settings>::setInputChannel(Channel inChannel)
{ {
mInputChannel = inChannel; mInputChannel = inChannel;
} }
@ -924,8 +937,8 @@ void MidiInterface<SerialPort>::setInputChannel(Channel inChannel)
This is a utility static method, used internally, This is a utility static method, used internally,
made public so you can handle MidiTypes more easily. made public so you can handle MidiTypes more easily.
*/ */
template<class SerialPort> template<class SerialPort, class Settings>
MidiType MidiInterface<SerialPort>::getTypeFromStatusByte(byte inStatus) MidiType MidiInterface<SerialPort, Settings>::getTypeFromStatusByte(byte inStatus)
{ {
if ((inStatus < 0x80) || if ((inStatus < 0x80) ||
(inStatus == 0xf4) || (inStatus == 0xf4) ||
@ -939,22 +952,22 @@ MidiType MidiInterface<SerialPort>::getTypeFromStatusByte(byte inStatus)
if (inStatus < 0xf0) if (inStatus < 0xf0)
{ {
// Channel message, remove channel nibble. // Channel message, remove channel nibble.
return (MidiType)(inStatus & 0xf0); return MidiType(inStatus & 0xf0);
} }
return (MidiType)inStatus; return MidiType(inStatus);
} }
/*! \brief Returns channel in the range 1-16 /*! \brief Returns channel in the range 1-16
*/ */
template<class SerialPort> template<class SerialPort, class Settings>
inline Channel MidiInterface<SerialPort>::getChannelFromStatusByte(byte inStatus) inline Channel MidiInterface<SerialPort, Settings>::getChannelFromStatusByte(byte inStatus)
{ {
return (inStatus & 0x0f) + 1; return (inStatus & 0x0f) + 1;
} }
template<class SerialPort> template<class SerialPort, class Settings>
bool MidiInterface<SerialPort>::isChannelMessage(MidiType inType) bool MidiInterface<SerialPort, Settings>::isChannelMessage(MidiType inType)
{ {
return (inType == NoteOff || return (inType == NoteOff ||
inType == NoteOn || inType == NoteOn ||
@ -973,24 +986,24 @@ bool MidiInterface<SerialPort>::isChannelMessage(MidiType inType)
@{ @{
*/ */
template<class SerialPort> void MidiInterface<SerialPort>::setHandleNoteOff(void (*fptr)(byte channel, byte note, byte velocity)) { mNoteOffCallback = fptr; } template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleNoteOff(void (*fptr)(byte channel, byte note, byte velocity)) { mNoteOffCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandleNoteOn(void (*fptr)(byte channel, byte note, byte velocity)) { mNoteOnCallback = fptr; } template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleNoteOn(void (*fptr)(byte channel, byte note, byte velocity)) { mNoteOnCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandleAfterTouchPoly(void (*fptr)(byte channel, byte note, byte pressure)) { mAfterTouchPolyCallback = fptr; } template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleAfterTouchPoly(void (*fptr)(byte channel, byte note, byte pressure)) { mAfterTouchPolyCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandleControlChange(void (*fptr)(byte channel, byte number, byte value)) { mControlChangeCallback = fptr; } template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleControlChange(void (*fptr)(byte channel, byte number, byte value)) { mControlChangeCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandleProgramChange(void (*fptr)(byte channel, byte number)) { mProgramChangeCallback = fptr; } template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleProgramChange(void (*fptr)(byte channel, byte number)) { mProgramChangeCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandleAfterTouchChannel(void (*fptr)(byte channel, byte pressure)) { mAfterTouchChannelCallback = fptr; } template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleAfterTouchChannel(void (*fptr)(byte channel, byte pressure)) { mAfterTouchChannelCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandlePitchBend(void (*fptr)(byte channel, int bend)) { mPitchBendCallback = fptr; } template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandlePitchBend(void (*fptr)(byte channel, int bend)) { mPitchBendCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandleSystemExclusive(void (*fptr)(byte* array, byte size)) { mSystemExclusiveCallback = fptr; } template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleSystemExclusive(void (*fptr)(byte* array, byte size)) { mSystemExclusiveCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandleTimeCodeQuarterFrame(void (*fptr)(byte data)) { mTimeCodeQuarterFrameCallback = fptr; } template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleTimeCodeQuarterFrame(void (*fptr)(byte data)) { mTimeCodeQuarterFrameCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandleSongPosition(void (*fptr)(unsigned beats)) { mSongPositionCallback = fptr; } template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleSongPosition(void (*fptr)(unsigned beats)) { mSongPositionCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandleSongSelect(void (*fptr)(byte songnumber)) { mSongSelectCallback = fptr; } template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleSongSelect(void (*fptr)(byte songnumber)) { mSongSelectCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandleTuneRequest(void (*fptr)(void)) { mTuneRequestCallback = fptr; } template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleTuneRequest(void (*fptr)(void)) { mTuneRequestCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandleClock(void (*fptr)(void)) { mClockCallback = fptr; } template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleClock(void (*fptr)(void)) { mClockCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandleStart(void (*fptr)(void)) { mStartCallback = fptr; } template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleStart(void (*fptr)(void)) { mStartCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandleContinue(void (*fptr)(void)) { mContinueCallback = fptr; } template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleContinue(void (*fptr)(void)) { mContinueCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandleStop(void (*fptr)(void)) { mStopCallback = fptr; } template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleStop(void (*fptr)(void)) { mStopCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandleActiveSensing(void (*fptr)(void)) { mActiveSensingCallback = fptr; } template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleActiveSensing(void (*fptr)(void)) { mActiveSensingCallback = fptr; }
template<class SerialPort> void MidiInterface<SerialPort>::setHandleSystemReset(void (*fptr)(void)) { mSystemResetCallback = fptr; } template<class SerialPort, class Settings> void MidiInterface<SerialPort, Settings>::setHandleSystemReset(void (*fptr)(void)) { mSystemResetCallback = fptr; }
/*! \brief Detach an external function from the given type. /*! \brief Detach an external function from the given type.
@ -998,8 +1011,8 @@ template<class SerialPort> void MidiInterface<SerialPort>::setHandleSystemReset(
\param inType The type of message to unbind. \param inType The type of message to unbind.
When a message of this type is received, no function will be called. When a message of this type is received, no function will be called.
*/ */
template<class SerialPort> template<class SerialPort, class Settings>
void MidiInterface<SerialPort>::disconnectCallbackFromType(MidiType inType) void MidiInterface<SerialPort, Settings>::disconnectCallbackFromType(MidiType inType)
{ {
switch (inType) switch (inType)
{ {
@ -1029,8 +1042,8 @@ void MidiInterface<SerialPort>::disconnectCallbackFromType(MidiType inType)
/*! @} */ // End of doc group MIDI Callbacks /*! @} */ // End of doc group MIDI Callbacks
// Private - launch callback function based on received type. // Private - launch callback function based on received type.
template<class SerialPort> template<class SerialPort, class Settings>
void MidiInterface<SerialPort>::launchCallback() void MidiInterface<SerialPort, Settings>::launchCallback()
{ {
// The order is mixed to allow frequent messages to trigger their callback faster. // The order is mixed to allow frequent messages to trigger their callback faster.
switch (mMessage.type) switch (mMessage.type)
@ -1090,8 +1103,8 @@ void MidiInterface<SerialPort>::launchCallback()
@see MidiFilterMode @see MidiFilterMode
*/ */
template<class SerialPort> template<class SerialPort, class Settings>
void MidiInterface<SerialPort>::setThruFilterMode(MidiFilterMode inThruFilterMode) void MidiInterface<SerialPort, Settings>::setThruFilterMode(MidiFilterMode inThruFilterMode)
{ {
mThruFilterMode = inThruFilterMode; mThruFilterMode = inThruFilterMode;
if (mThruFilterMode != Off) if (mThruFilterMode != Off)
@ -1100,27 +1113,27 @@ void MidiInterface<SerialPort>::setThruFilterMode(MidiFilterMode inThruFilterMod
mThruActivated = false; mThruActivated = false;
} }
template<class SerialPort> template<class SerialPort, class Settings>
MidiFilterMode MidiInterface<SerialPort>::getFilterMode() const MidiFilterMode MidiInterface<SerialPort, Settings>::getFilterMode() const
{ {
return mThruFilterMode; return mThruFilterMode;
} }
template<class SerialPort> template<class SerialPort, class Settings>
bool MidiInterface<SerialPort>::getThruState() const bool MidiInterface<SerialPort, Settings>::getThruState() const
{ {
return mThruActivated; return mThruActivated;
} }
template<class SerialPort> template<class SerialPort, class Settings>
void MidiInterface<SerialPort>::turnThruOn(MidiFilterMode inThruFilterMode) void MidiInterface<SerialPort, Settings>::turnThruOn(MidiFilterMode inThruFilterMode)
{ {
mThruActivated = true; mThruActivated = true;
mThruFilterMode = inThruFilterMode; mThruFilterMode = inThruFilterMode;
} }
template<class SerialPort> template<class SerialPort, class Settings>
void MidiInterface<SerialPort>::turnThruOff() void MidiInterface<SerialPort, Settings>::turnThruOff()
{ {
mThruActivated = false; mThruActivated = false;
mThruFilterMode = Off; mThruFilterMode = Off;
@ -1134,8 +1147,8 @@ void MidiInterface<SerialPort>::turnThruOff()
// to output unless filter is set to Off. // to output unless filter is set to Off.
// - Channel messages are passed to the output whether their channel // - Channel messages are passed to the output whether their channel
// is matching the input channel and the filter setting // is matching the input channel and the filter setting
template<class SerialPort> template<class SerialPort, class Settings>
void MidiInterface<SerialPort>::thruFilter(Channel inChannel) void MidiInterface<SerialPort, Settings>::thruFilter(Channel inChannel)
{ {
// If the feature is disabled, don't do anything. // If the feature is disabled, don't do anything.
if (!mThruActivated || (mThruFilterMode == Off)) if (!mThruActivated || (mThruFilterMode == Off))

View File

@ -24,6 +24,7 @@
#pragma once #pragma once
#include "midi_Namespace.h" #include "midi_Namespace.h"
#include "midi_Settings.h"
#include <inttypes.h> #include <inttypes.h>
BEGIN_MIDI_NAMESPACE BEGIN_MIDI_NAMESPACE
@ -40,7 +41,6 @@ BEGIN_MIDI_NAMESPACE
// Type definitions // Type definitions
typedef uint8_t byte; typedef uint8_t byte;
typedef byte StatusByte; typedef byte StatusByte;
typedef byte DataByte; typedef byte DataByte;
typedef byte Channel; typedef byte Channel;
@ -163,7 +163,6 @@ enum MidiControlChangeNumber
*/ */
struct Message struct Message
{ {
/*! The MIDI channel on which the message was recieved. /*! The MIDI channel on which the message was recieved.
\n Value goes from 1 to 16. \n Value goes from 1 to 16.
*/ */
@ -196,7 +195,6 @@ struct Message
validity means the message respects the MIDI norm. validity means the message respects the MIDI norm.
*/ */
bool valid; bool valid;
}; };
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -209,11 +207,12 @@ struct Message
#define MIDI_CREATE_INSTANCE(Type, SerialPort, Name) \ #define MIDI_CREATE_INSTANCE(Type, SerialPort, Name) \
midi::MidiInterface<Type> Name((Type&)SerialPort); midi::MidiInterface<Type> Name((Type&)SerialPort);
/*! \brief Shortcut for MIDI Interface class with template argument. /*! \brief Create an instance of the library attached to a serial port with
The class name for a MIDI object using the hardware UART would be custom settings.
midi::MidiInterface<HardwareSerial>, when the macro is MIDI_CLASS(HardwareSerial). @see DefaultSettings
@see MIDI_CREATE_INSTANCE
*/ */
#define MIDI_CLASS(Type) \ #define MIDI_CREATE_CUSTOM_INSTANCE(Type, SerialPort, Name, Settings) \
midi::MidiInterface<Type> midi::MidiInterface<Type, Settings> Name((Type&)SerialPort);
END_MIDI_NAMESPACE END_MIDI_NAMESPACE

View File

@ -44,36 +44,6 @@
#define MIDI_USE_CALLBACKS 1 #define MIDI_USE_CALLBACKS 1
// -----------------------------------------------------------------------------
// Create a MIDI object automatically on the port defined with MIDI_SERIAL_PORT.
#ifndef MIDI_AUTO_INSTANCIATE
# ifdef ARDUINO
# define MIDI_AUTO_INSTANCIATE 1
# else
# define MIDI_AUTO_INSTANCIATE 0 ///< @see MIDI_CREATE_INSTANCE
# endif
#endif
// -----------------------------------------------------------------------------
// Default serial port configuration (if MIDI_AUTO_INSTANCIATE is set)
// Set the default port to use for MIDI.
#if MIDI_AUTO_INSTANCIATE
# ifdef ARDUINO
# include "Arduino.h"
# ifdef USBCON
# define MIDI_DEFAULT_SERIAL_PORT Serial1 // For Leonardo
# else
# define MIDI_DEFAULT_SERIAL_PORT Serial // For other Arduinos
# endif
# define MIDI_DEFAULT_SERIAL_CLASS HardwareSerial
# include "HardwareSerial.h"
# else
# error Auto-instanciation disabled. Use MIDI_CREATE_INSTANCE macro.
# endif
#endif
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Misc. options // Misc. options
@ -99,4 +69,24 @@
BEGIN_MIDI_NAMESPACE BEGIN_MIDI_NAMESPACE
/*! \brief Default Settings Traits struct
To change the default settings, don't edit them there, create a subclass and
override the values in that subclass, then use the MIDI_CREATE_CUSTOM_INSTANCE
macro to create your instance. The settings you don't override will keep their
default value. Eg:
struct MySettings : public midi::DefaultSettings
{
static const bool UseRunningStatus = false; // Messes with my old equipment!
};
MIDI_CREATE_CUSTOM_INSTANCE(HardwareSerial, Serial2, midi, MySettings);
*/
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;
};
END_MIDI_NAMESPACE END_MIDI_NAMESPACE