Merge branch 'settings' into dev
This commit is contained in:
commit
1ff874c70d
21
src/MIDI.cpp
21
src/MIDI.cpp
|
|
@ -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.
|
||||||
|
|
|
||||||
65
src/MIDI.h
65
src/MIDI.h
|
|
@ -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"
|
||||||
|
|
|
||||||
333
src/MIDI.hpp
333
src/MIDI.hpp
|
|
@ -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))
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue