Quake wip.
This commit is contained in:
parent
5a42cb006d
commit
4b8b38aeaf
258
src/MIDI.cpp
258
src/MIDI.cpp
|
|
@ -2,7 +2,7 @@
|
|||
* @file MIDI.cpp
|
||||
* Project Arduino MIDI Library
|
||||
* @brief MIDI Library for the Arduino
|
||||
* @version 3.2
|
||||
* @version 4.0
|
||||
* @author Francois Best
|
||||
* @date 24/02/11
|
||||
* license GPL Forty Seven Effects - 2011
|
||||
|
|
@ -12,6 +12,7 @@
|
|||
#include <stdlib.h>
|
||||
#include "Arduino.h" // If using an old (pre-1.0) version of Arduino,
|
||||
// use WConstants.h instead of Arduino.h
|
||||
|
||||
#if MIDI_USE_SOFTWARE_SERIAL
|
||||
|
||||
// Note: Make sure the following relative path is correct.
|
||||
|
|
@ -26,14 +27,17 @@ SoftwareSerial softSerialClass(MIDI_SOFTSERIAL_RX_PIN,
|
|||
#endif // MIDI_USE_SOFTWARE_SERIAL
|
||||
|
||||
|
||||
/*! \brief Main instance (the class comes pre-instantiated). */
|
||||
MIDI_Class MIDI;
|
||||
#if MIDI_AUTO_INSTANCIATE
|
||||
midi::MidiInterface MIDI;
|
||||
#endif
|
||||
|
||||
|
||||
/*! \brief Default constructor for MIDI_Class. */
|
||||
MIDI_Class::MIDI_Class()
|
||||
BEGIN_MIDI_NAMESPACE
|
||||
|
||||
/*! \brief Default constructor for MidiInterface. */
|
||||
MidiInterface::MidiInterface()
|
||||
{
|
||||
#if COMPILE_MIDI_IN && USE_CALLBACKS
|
||||
#if MIDI_BUILD_INPUT && USE_CALLBACKS
|
||||
|
||||
// Initialise callbacks to NULL pointer
|
||||
mNoteOffCallback = NULL;
|
||||
|
|
@ -59,11 +63,11 @@ MIDI_Class::MIDI_Class()
|
|||
}
|
||||
|
||||
|
||||
/*! \brief Default destructor for MIDI_Class.
|
||||
/*! \brief Default destructor for MidiInterface.
|
||||
|
||||
This is not really useful for the Arduino, as it is never called...
|
||||
*/
|
||||
MIDI_Class::~MIDI_Class()
|
||||
MidiInterface::~MidiInterface()
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -75,19 +79,19 @@ MIDI_Class::~MIDI_Class()
|
|||
- Input channel set to 1 if no value is specified
|
||||
- Full thru mirroring
|
||||
*/
|
||||
void MIDI_Class::begin(const byte inChannel)
|
||||
void MidiInterface::begin(const byte inChannel)
|
||||
{
|
||||
// Initialise the Serial port
|
||||
MIDI_SERIAL_PORT.begin(MIDI_BAUDRATE);
|
||||
|
||||
#if COMPILE_MIDI_OUT && USE_RUNNING_STATUS
|
||||
#if MIDI_BUILD_OUTPUT && MIDI_USE_RUNNING_STATUS
|
||||
|
||||
mRunningStatus_TX = InvalidType;
|
||||
|
||||
#endif // COMPILE_MIDI_OUT && USE_RUNNING_STATUS
|
||||
#endif // MIDI_BUILD_OUTPUT && MIDI_USE_RUNNING_STATUS
|
||||
|
||||
|
||||
#if COMPILE_MIDI_IN
|
||||
#if MIDI_BUILD_INPUT
|
||||
|
||||
mInputChannel = inChannel;
|
||||
mRunningStatus_RX = InvalidType;
|
||||
|
|
@ -100,10 +104,10 @@ void MIDI_Class::begin(const byte inChannel)
|
|||
mMessage.data1 = 0;
|
||||
mMessage.data2 = 0;
|
||||
|
||||
#endif // COMPILE_MIDI_IN
|
||||
#endif // MIDI_BUILD_INPUT
|
||||
|
||||
|
||||
#if (COMPILE_MIDI_IN && COMPILE_MIDI_OUT && COMPILE_MIDI_THRU) // Thru
|
||||
#if (MIDI_BUILD_INPUT && MIDI_BUILD_OUTPUT && MIDI_BUILD_THRU) // Thru
|
||||
|
||||
mThruFilterMode = Full;
|
||||
mThruActivated = true;
|
||||
|
|
@ -117,14 +121,7 @@ void MIDI_Class::begin(const byte inChannel)
|
|||
// MIDI Output
|
||||
// =============================================================================
|
||||
|
||||
#if COMPILE_MIDI_OUT
|
||||
|
||||
// Private method for generating a status byte from channel and type
|
||||
const byte MIDI_Class::genstatus(const kMIDIType inType,
|
||||
const byte inChannel) const
|
||||
{
|
||||
return ((byte)inType | ((inChannel-1) & 0x0F));
|
||||
}
|
||||
#if MIDI_BUILD_OUTPUT
|
||||
|
||||
|
||||
/*! \brief Generate and send a MIDI message from the values given.
|
||||
|
|
@ -138,7 +135,7 @@ const byte MIDI_Class::genstatus(const kMIDIType inType,
|
|||
This is an internal method, use it only if you need to send raw data
|
||||
from your code, at your own risks.
|
||||
*/
|
||||
void MIDI_Class::send(kMIDIType type,
|
||||
void MidiInterface::send(MidiType type,
|
||||
byte data1,
|
||||
byte data2,
|
||||
byte channel)
|
||||
|
|
@ -149,7 +146,7 @@ void MIDI_Class::send(kMIDIType type,
|
|||
type < NoteOff)
|
||||
{
|
||||
|
||||
#if USE_RUNNING_STATUS
|
||||
#if MIDI_USE_RUNNING_STATUS
|
||||
mRunningStatus_TX = InvalidType;
|
||||
#endif
|
||||
|
||||
|
|
@ -164,7 +161,7 @@ void MIDI_Class::send(kMIDIType type,
|
|||
|
||||
byte statusbyte = genstatus(type,channel);
|
||||
|
||||
#if USE_RUNNING_STATUS
|
||||
#if MIDI_USE_RUNNING_STATUS
|
||||
// Check Running Status
|
||||
if (mRunningStatus_TX != statusbyte)
|
||||
{
|
||||
|
|
@ -198,7 +195,7 @@ void MIDI_Class::send(kMIDIType type,
|
|||
Take a look at the values, names and frequencies of notes here:
|
||||
http://www.phys.unsw.edu.au/jw/notes.html
|
||||
*/
|
||||
void MIDI_Class::sendNoteOn(byte NoteNumber,
|
||||
void MidiInterface::sendNoteOn(byte NoteNumber,
|
||||
byte Velocity,
|
||||
byte Channel)
|
||||
{
|
||||
|
|
@ -217,7 +214,7 @@ void MIDI_Class::sendNoteOn(byte NoteNumber,
|
|||
Take a look at the values, names and frequencies of notes here:
|
||||
http://www.phys.unsw.edu.au/jw/notes.html
|
||||
*/
|
||||
void MIDI_Class::sendNoteOff(byte NoteNumber,
|
||||
void MidiInterface::sendNoteOff(byte NoteNumber,
|
||||
byte Velocity,
|
||||
byte Channel)
|
||||
{
|
||||
|
|
@ -229,7 +226,7 @@ void MIDI_Class::sendNoteOff(byte NoteNumber,
|
|||
\param ProgramNumber The Program to select (0 to 127).
|
||||
\param Channel The channel on which the message will be sent (1 to 16).
|
||||
*/
|
||||
void MIDI_Class::sendProgramChange(byte ProgramNumber,
|
||||
void MidiInterface::sendProgramChange(byte ProgramNumber,
|
||||
byte Channel)
|
||||
{
|
||||
send(ProgramChange,ProgramNumber,0,Channel);
|
||||
|
|
@ -244,7 +241,7 @@ void MIDI_Class::sendProgramChange(byte ProgramNumber,
|
|||
See the detailed controllers numbers & description here:
|
||||
http://www.somascape.org/midi/tech/spec.html#ctrlnums
|
||||
*/
|
||||
void MIDI_Class::sendControlChange(byte ControlNumber,
|
||||
void MidiInterface::sendControlChange(byte ControlNumber,
|
||||
byte ControlValue,
|
||||
byte Channel)
|
||||
{
|
||||
|
|
@ -257,7 +254,7 @@ void MIDI_Class::sendControlChange(byte ControlNumber,
|
|||
\param Pressure The amount of AfterTouch to apply (0 to 127).
|
||||
\param Channel The channel on which the message will be sent (1 to 16).
|
||||
*/
|
||||
void MIDI_Class::sendPolyPressure(byte NoteNumber,
|
||||
void MidiInterface::sendPolyPressure(byte NoteNumber,
|
||||
byte Pressure,
|
||||
byte Channel)
|
||||
{
|
||||
|
|
@ -269,7 +266,7 @@ void MIDI_Class::sendPolyPressure(byte NoteNumber,
|
|||
\param Pressure The amount of AfterTouch to apply to all notes.
|
||||
\param Channel The channel on which the message will be sent (1 to 16).
|
||||
*/
|
||||
void MIDI_Class::sendAfterTouch(byte Pressure,
|
||||
void MidiInterface::sendAfterTouch(byte Pressure,
|
||||
byte Channel)
|
||||
{
|
||||
send(AfterTouchChannel,Pressure,0,Channel);
|
||||
|
|
@ -282,7 +279,7 @@ void MIDI_Class::sendAfterTouch(byte Pressure,
|
|||
center value is 0.
|
||||
\param Channel The channel on which the message will be sent (1 to 16).
|
||||
*/
|
||||
void MIDI_Class::sendPitchBend(int PitchValue,
|
||||
void MidiInterface::sendPitchBend(int PitchValue,
|
||||
byte Channel)
|
||||
{
|
||||
const unsigned int bend = PitchValue - MIDI_PITCHBEND_MIN;
|
||||
|
|
@ -296,7 +293,7 @@ void MIDI_Class::sendPitchBend(int PitchValue,
|
|||
and +1.0f (max upwards bend), center value is 0.0f.
|
||||
\param Channel The channel on which the message will be sent (1 to 16).
|
||||
*/
|
||||
void MIDI_Class::sendPitchBend(double PitchValue,
|
||||
void MidiInterface::sendPitchBend(double PitchValue,
|
||||
byte Channel)
|
||||
{
|
||||
const int pitchval = PitchValue * MIDI_PITCHBEND_MAX;
|
||||
|
|
@ -313,7 +310,7 @@ void MIDI_Class::sendPitchBend(double PitchValue,
|
|||
default value for ArrayContainsBoundaries is set to 'false' for compatibility
|
||||
with previous versions of the library.
|
||||
*/
|
||||
void MIDI_Class::sendSysEx(int length,
|
||||
void MidiInterface::sendSysEx(int length,
|
||||
const byte *const array,
|
||||
bool ArrayContainsBoundaries)
|
||||
{
|
||||
|
|
@ -332,7 +329,7 @@ void MIDI_Class::sendSysEx(int length,
|
|||
MIDI_SERIAL_PORT.write(array[i]);
|
||||
}
|
||||
|
||||
#if USE_RUNNING_STATUS
|
||||
#if MIDI_USE_RUNNING_STATUS
|
||||
mRunningStatus_TX = InvalidType;
|
||||
#endif
|
||||
}
|
||||
|
|
@ -343,7 +340,7 @@ void MIDI_Class::sendSysEx(int length,
|
|||
When a MIDI unit receives this message,
|
||||
it should tune its oscillators (if equipped with any).
|
||||
*/
|
||||
void MIDI_Class::sendTuneRequest()
|
||||
void MidiInterface::sendTuneRequest()
|
||||
{
|
||||
sendRealTime(TuneRequest);
|
||||
}
|
||||
|
|
@ -355,7 +352,7 @@ void MIDI_Class::sendTuneRequest()
|
|||
\param ValuesNibble MTC data
|
||||
See MIDI Specification for more information.
|
||||
*/
|
||||
void MIDI_Class::sendTimeCodeQuarterFrame(byte TypeNibble, byte ValuesNibble)
|
||||
void MidiInterface::sendTimeCodeQuarterFrame(byte TypeNibble, byte ValuesNibble)
|
||||
{
|
||||
const byte data = ( ((TypeNibble & 0x07) << 4) | (ValuesNibble & 0x0F) );
|
||||
sendTimeCodeQuarterFrame(data);
|
||||
|
|
@ -368,12 +365,12 @@ void MIDI_Class::sendTimeCodeQuarterFrame(byte TypeNibble, byte ValuesNibble)
|
|||
\param data if you want to encode directly the nibbles in your program,
|
||||
you can send the byte here.
|
||||
*/
|
||||
void MIDI_Class::sendTimeCodeQuarterFrame(byte data)
|
||||
void MidiInterface::sendTimeCodeQuarterFrame(byte data)
|
||||
{
|
||||
MIDI_SERIAL_PORT.write((byte)TimeCodeQuarterFrame);
|
||||
MIDI_SERIAL_PORT.write(data);
|
||||
|
||||
#if USE_RUNNING_STATUS
|
||||
#if MIDI_USE_RUNNING_STATUS
|
||||
mRunningStatus_TX = InvalidType;
|
||||
#endif
|
||||
}
|
||||
|
|
@ -382,25 +379,25 @@ void MIDI_Class::sendTimeCodeQuarterFrame(byte data)
|
|||
/*! \brief Send a Song Position Pointer message.
|
||||
\param Beats The number of beats since the start of the song.
|
||||
*/
|
||||
void MIDI_Class::sendSongPosition(unsigned int Beats)
|
||||
void MidiInterface::sendSongPosition(unsigned int Beats)
|
||||
{
|
||||
MIDI_SERIAL_PORT.write((byte)SongPosition);
|
||||
MIDI_SERIAL_PORT.write(Beats & 0x7F);
|
||||
MIDI_SERIAL_PORT.write((Beats >> 7) & 0x7F);
|
||||
|
||||
#if USE_RUNNING_STATUS
|
||||
#if MIDI_USE_RUNNING_STATUS
|
||||
mRunningStatus_TX = InvalidType;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Send a Song Select message */
|
||||
void MIDI_Class::sendSongSelect(byte SongNumber)
|
||||
void MidiInterface::sendSongSelect(byte SongNumber)
|
||||
{
|
||||
MIDI_SERIAL_PORT.write((byte)SongSelect);
|
||||
MIDI_SERIAL_PORT.write(SongNumber & 0x7F);
|
||||
|
||||
#if USE_RUNNING_STATUS
|
||||
#if MIDI_USE_RUNNING_STATUS
|
||||
mRunningStatus_TX = InvalidType;
|
||||
#endif
|
||||
}
|
||||
|
|
@ -411,9 +408,9 @@ void MIDI_Class::sendSongSelect(byte SongNumber)
|
|||
\param Type The available Real Time types are:
|
||||
Start, Stop, Continue, Clock, ActiveSensing and SystemReset.
|
||||
You can also send a Tune Request with this method.
|
||||
@see kMIDIType
|
||||
@see MidiType
|
||||
*/
|
||||
void MIDI_Class::sendRealTime(kMIDIType Type)
|
||||
void MidiInterface::sendRealTime(MidiType Type)
|
||||
{
|
||||
switch (Type)
|
||||
{
|
||||
|
|
@ -434,19 +431,19 @@ void MIDI_Class::sendRealTime(kMIDIType Type)
|
|||
// Do not cancel Running Status for real-time messages as they can be
|
||||
// interleaved within any message. Though, TuneRequest can be sent here,
|
||||
// and as it is a System Common message, it must reset Running Status.
|
||||
#if USE_RUNNING_STATUS
|
||||
#if MIDI_USE_RUNNING_STATUS
|
||||
if (Type == TuneRequest) mRunningStatus_TX = InvalidType;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // COMPILE_MIDI_OUT
|
||||
#endif // MIDI_BUILD_OUTPUT
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// MIDI Input
|
||||
// =============================================================================
|
||||
|
||||
#if COMPILE_MIDI_IN
|
||||
#if MIDI_BUILD_INPUT
|
||||
|
||||
/*! \brief Read a MIDI message from the serial port
|
||||
using the main input channel (see setInputChannel() for reference).
|
||||
|
|
@ -456,7 +453,7 @@ void MIDI_Class::sendRealTime(kMIDIType Type)
|
|||
If the Thru is enabled and the messages matches the filter,
|
||||
it is sent back on the MIDI output.
|
||||
*/
|
||||
bool MIDI_Class::read()
|
||||
bool MidiInterface::read()
|
||||
{
|
||||
return read(mInputChannel);
|
||||
}
|
||||
|
|
@ -465,7 +462,7 @@ bool MIDI_Class::read()
|
|||
/*! \brief Reading/thru-ing method, the same as read()
|
||||
with a given input channel to read on.
|
||||
*/
|
||||
bool MIDI_Class::read(const byte inChannel)
|
||||
bool MidiInterface::read(const byte inChannel)
|
||||
{
|
||||
if (inChannel >= MIDI_CHANNEL_OFF)
|
||||
return false; // MIDI Input disabled.
|
||||
|
|
@ -475,7 +472,7 @@ bool MIDI_Class::read(const byte inChannel)
|
|||
if (input_filter(inChannel))
|
||||
{
|
||||
|
||||
#if (COMPILE_MIDI_OUT && COMPILE_MIDI_THRU)
|
||||
#if (MIDI_BUILD_OUTPUT && MIDI_BUILD_THRU)
|
||||
thru_filter(inChannel);
|
||||
#endif
|
||||
|
||||
|
|
@ -491,7 +488,7 @@ bool MIDI_Class::read(const byte inChannel)
|
|||
|
||||
|
||||
// Private method: MIDI parser
|
||||
bool MIDI_Class::parse(byte inChannel)
|
||||
bool MidiInterface::parse(byte inChannel)
|
||||
{
|
||||
const byte bytes_available = MIDI_SERIAL_PORT.available();
|
||||
|
||||
|
|
@ -662,7 +659,7 @@ bool MIDI_Class::parse(byte inChannel)
|
|||
// This is done by leaving the pending message as is,
|
||||
// it will be completed on next calls.
|
||||
|
||||
mMessage.type = (kMIDIType)extracted;
|
||||
mMessage.type = (MidiType)extracted;
|
||||
mMessage.data1 = 0;
|
||||
mMessage.data2 = 0;
|
||||
mMessage.channel = 0;
|
||||
|
|
@ -779,7 +776,7 @@ bool MIDI_Class::parse(byte inChannel)
|
|||
|
||||
|
||||
// Private method: check if the received message is on the listened channel
|
||||
bool MIDI_Class::input_filter(byte inChannel)
|
||||
bool MidiInterface::input_filter(byte inChannel)
|
||||
{
|
||||
// This method handles recognition of channel
|
||||
// (to know if the message is destinated to the Arduino)
|
||||
|
|
@ -811,7 +808,7 @@ bool MIDI_Class::input_filter(byte inChannel)
|
|||
|
||||
|
||||
// Private method: reset input attributes
|
||||
void MIDI_Class::reset_input_attributes()
|
||||
void MidiInterface::reset_input_attributes()
|
||||
{
|
||||
mPendingMessageIndex = 0;
|
||||
mPendingMessageExpectedLenght = 0;
|
||||
|
|
@ -819,102 +816,30 @@ void MIDI_Class::reset_input_attributes()
|
|||
}
|
||||
|
||||
|
||||
// Getters
|
||||
/*! \brief Get the last received message's type
|
||||
|
||||
Returns an enumerated type. @see kMIDIType
|
||||
*/
|
||||
kMIDIType MIDI_Class::getType() const
|
||||
{
|
||||
return mMessage.type;
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Get the channel of the message stored in the structure.
|
||||
|
||||
\return Channel range is 1 to 16.
|
||||
For non-channel messages, this will return 0.
|
||||
*/
|
||||
byte MIDI_Class::getChannel() const
|
||||
{
|
||||
return mMessage.channel;
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Get the first data byte of the last received message. */
|
||||
byte MIDI_Class::getData1() const
|
||||
{
|
||||
return mMessage.data1;
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Get the second data byte of the last received message. */
|
||||
byte MIDI_Class::getData2() const
|
||||
{
|
||||
return mMessage.data2;
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Get the System Exclusive byte array.
|
||||
|
||||
@see getSysExArrayLength to get the array's length in bytes.
|
||||
*/
|
||||
const byte * MIDI_Class::getSysExArray() const
|
||||
{
|
||||
return mMessage.sysex_array;
|
||||
}
|
||||
|
||||
/*! \brief Get the lenght of the System Exclusive array.
|
||||
|
||||
It is coded using data1 as LSB and data2 as MSB.
|
||||
\return The array's length, in bytes.
|
||||
*/
|
||||
unsigned int MIDI_Class::getSysExArrayLength() const
|
||||
{
|
||||
const unsigned int size = ((unsigned)(mMessage.data2) << 8) | mMessage.data1;
|
||||
return (size > MIDI_SYSEX_ARRAY_SIZE) ? MIDI_SYSEX_ARRAY_SIZE : size;
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Check if a valid message is stored in the structure. */
|
||||
bool MIDI_Class::check() const
|
||||
{
|
||||
return mMessage.valid;
|
||||
}
|
||||
|
||||
|
||||
// Setters
|
||||
/*! \brief Set the value for the input MIDI channel
|
||||
\param Channel 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 MIDI input.
|
||||
*/
|
||||
void MIDI_Class::setInputChannel(const byte Channel)
|
||||
{
|
||||
mInputChannel = Channel;
|
||||
}
|
||||
|
||||
|
||||
#if USE_CALLBACKS
|
||||
|
||||
void MIDI_Class::setHandleNoteOff(void (*fptr)(byte channel, byte note, byte velocity)) { mNoteOffCallback = fptr; }
|
||||
void MIDI_Class::setHandleNoteOn(void (*fptr)(byte channel, byte note, byte velocity)) { mNoteOnCallback = fptr; }
|
||||
void MIDI_Class::setHandleAfterTouchPoly(void (*fptr)(byte channel, byte note, byte pressure)) { mAfterTouchPolyCallback = fptr; }
|
||||
void MIDI_Class::setHandleControlChange(void (*fptr)(byte channel, byte number, byte value)) { mControlChangeCallback = fptr; }
|
||||
void MIDI_Class::setHandleProgramChange(void (*fptr)(byte channel, byte number)) { mProgramChangeCallback = fptr; }
|
||||
void MIDI_Class::setHandleAfterTouchChannel(void (*fptr)(byte channel, byte pressure)) { mAfterTouchChannelCallback = fptr; }
|
||||
void MIDI_Class::setHandlePitchBend(void (*fptr)(byte channel, int bend)) { mPitchBendCallback = fptr; }
|
||||
void MIDI_Class::setHandleSystemExclusive(void (*fptr)(byte * array, byte size)) { mSystemExclusiveCallback = fptr; }
|
||||
void MIDI_Class::setHandleTimeCodeQuarterFrame(void (*fptr)(byte data)) { mTimeCodeQuarterFrameCallback = fptr; }
|
||||
void MIDI_Class::setHandleSongPosition(void (*fptr)(unsigned int beats)) { mSongPositionCallback = fptr; }
|
||||
void MIDI_Class::setHandleSongSelect(void (*fptr)(byte songnumber)) { mSongSelectCallback = fptr; }
|
||||
void MIDI_Class::setHandleTuneRequest(void (*fptr)(void)) { mTuneRequestCallback = fptr; }
|
||||
void MIDI_Class::setHandleClock(void (*fptr)(void)) { mClockCallback = fptr; }
|
||||
void MIDI_Class::setHandleStart(void (*fptr)(void)) { mStartCallback = fptr; }
|
||||
void MIDI_Class::setHandleContinue(void (*fptr)(void)) { mContinueCallback = fptr; }
|
||||
void MIDI_Class::setHandleStop(void (*fptr)(void)) { mStopCallback = fptr; }
|
||||
void MIDI_Class::setHandleActiveSensing(void (*fptr)(void)) { mActiveSensingCallback = fptr; }
|
||||
void MIDI_Class::setHandleSystemReset(void (*fptr)(void)) { mSystemResetCallback = fptr; }
|
||||
void MidiInterface::setHandleNoteOff(void (*fptr)(byte channel, byte note, byte velocity)) { mNoteOffCallback = fptr; }
|
||||
void MidiInterface::setHandleNoteOn(void (*fptr)(byte channel, byte note, byte velocity)) { mNoteOnCallback = fptr; }
|
||||
void MidiInterface::setHandleAfterTouchPoly(void (*fptr)(byte channel, byte note, byte pressure)) { mAfterTouchPolyCallback = fptr; }
|
||||
void MidiInterface::setHandleControlChange(void (*fptr)(byte channel, byte number, byte value)) { mControlChangeCallback = fptr; }
|
||||
void MidiInterface::setHandleProgramChange(void (*fptr)(byte channel, byte number)) { mProgramChangeCallback = fptr; }
|
||||
void MidiInterface::setHandleAfterTouchChannel(void (*fptr)(byte channel, byte pressure)) { mAfterTouchChannelCallback = fptr; }
|
||||
void MidiInterface::setHandlePitchBend(void (*fptr)(byte channel, int bend)) { mPitchBendCallback = fptr; }
|
||||
void MidiInterface::setHandleSystemExclusive(void (*fptr)(byte * array, byte size)) { mSystemExclusiveCallback = fptr; }
|
||||
void MidiInterface::setHandleTimeCodeQuarterFrame(void (*fptr)(byte data)) { mTimeCodeQuarterFrameCallback = fptr; }
|
||||
void MidiInterface::setHandleSongPosition(void (*fptr)(unsigned int beats)) { mSongPositionCallback = fptr; }
|
||||
void MidiInterface::setHandleSongSelect(void (*fptr)(byte songnumber)) { mSongSelectCallback = fptr; }
|
||||
void MidiInterface::setHandleTuneRequest(void (*fptr)(void)) { mTuneRequestCallback = fptr; }
|
||||
void MidiInterface::setHandleClock(void (*fptr)(void)) { mClockCallback = fptr; }
|
||||
void MidiInterface::setHandleStart(void (*fptr)(void)) { mStartCallback = fptr; }
|
||||
void MidiInterface::setHandleContinue(void (*fptr)(void)) { mContinueCallback = fptr; }
|
||||
void MidiInterface::setHandleStop(void (*fptr)(void)) { mStopCallback = fptr; }
|
||||
void MidiInterface::setHandleActiveSensing(void (*fptr)(void)) { mActiveSensingCallback = fptr; }
|
||||
void MidiInterface::setHandleSystemReset(void (*fptr)(void)) { mSystemResetCallback = fptr; }
|
||||
|
||||
|
||||
/*! \brief Detach an external function from the given type.
|
||||
|
|
@ -923,7 +848,7 @@ void MIDI_Class::setHandleSystemReset(void (*fptr)(void))
|
|||
\param Type The type of message to unbind.
|
||||
When a message of this type is received, no function will be called.
|
||||
*/
|
||||
void MIDI_Class::disconnectCallbackFromType(kMIDIType Type)
|
||||
void MidiInterface::disconnectCallbackFromType(MidiType Type)
|
||||
{
|
||||
switch (Type)
|
||||
{
|
||||
|
|
@ -952,7 +877,7 @@ void MIDI_Class::disconnectCallbackFromType(kMIDIType Type)
|
|||
|
||||
|
||||
// Private - launch callback function based on received type.
|
||||
void MIDI_Class::launchCallback()
|
||||
void MidiInterface::launchCallback()
|
||||
{
|
||||
// The order is mixed to allow frequent messages to trigger their callback faster.
|
||||
switch (mMessage.type)
|
||||
|
|
@ -994,49 +919,18 @@ void MIDI_Class::launchCallback()
|
|||
#endif // USE_CALLBACKS
|
||||
|
||||
|
||||
#endif // COMPILE_MIDI_IN
|
||||
#endif // MIDI_BUILD_INPUT
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// MIDI Soft Thru
|
||||
// =============================================================================
|
||||
|
||||
#if (COMPILE_MIDI_IN && COMPILE_MIDI_OUT && COMPILE_MIDI_THRU)
|
||||
|
||||
/*! \brief Set the filter for thru mirroring
|
||||
\param inThruFilterMode a filter mode
|
||||
|
||||
@see kThruFilterMode
|
||||
*/
|
||||
void MIDI_Class::setThruFilterMode(kThruFilterMode inThruFilterMode)
|
||||
{
|
||||
mThruFilterMode = inThruFilterMode;
|
||||
if (mThruFilterMode != Off)
|
||||
mThruActivated = true;
|
||||
else
|
||||
mThruActivated = false;
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Setter method: turn message mirroring on. */
|
||||
void MIDI_Class::turnThruOn(kThruFilterMode inThruFilterMode)
|
||||
{
|
||||
mThruActivated = true;
|
||||
mThruFilterMode = inThruFilterMode;
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Setter method: turn message mirroring off. */
|
||||
void MIDI_Class::turnThruOff()
|
||||
{
|
||||
mThruActivated = false;
|
||||
mThruFilterMode = Off;
|
||||
}
|
||||
|
||||
#if (MIDI_BUILD_INPUT && MIDI_BUILD_OUTPUT && MIDI_BUILD_THRU)
|
||||
|
||||
// This method is called upon reception of a message
|
||||
// and takes care of Thru filtering and sending.
|
||||
void MIDI_Class::thru_filter(byte inChannel)
|
||||
void MidiInterface::thru_filter(byte inChannel)
|
||||
{
|
||||
|
||||
/*
|
||||
|
|
@ -1142,3 +1036,5 @@ void MIDI_Class::thru_filter(byte inChannel)
|
|||
}
|
||||
|
||||
#endif // Thru
|
||||
|
||||
END_MIDI_NAMESPACE
|
||||
|
|
|
|||
393
src/MIDI.h
393
src/MIDI.h
|
|
@ -2,7 +2,7 @@
|
|||
* @file MIDI.h
|
||||
* Project Arduino MIDI Library
|
||||
* @brief MIDI Library for the Arduino
|
||||
* @version 3.2
|
||||
* @version 4.0
|
||||
* @author Francois Best
|
||||
* @date 24/02/11
|
||||
* license GPL Forty Seven Effects - 2011
|
||||
|
|
@ -15,313 +15,101 @@
|
|||
#include "midi_Settings.h"
|
||||
#include "midi_Defs.h"
|
||||
|
||||
/*
|
||||
###############################################################
|
||||
# #
|
||||
# CONFIGURATION AREA #
|
||||
# #
|
||||
# Here are a few settings you can change to customize #
|
||||
# the library for your own project. You can for example #
|
||||
# choose to compile only parts of it so you gain flash #
|
||||
# space and optimise the speed of your sketch. #
|
||||
# #
|
||||
###############################################################
|
||||
BEGIN_MIDI_NAMESPACE
|
||||
|
||||
/*! \brief The main class for MIDI handling.
|
||||
*/
|
||||
|
||||
|
||||
#define COMPILE_MIDI_IN 1 // Set this setting to 1 to use the MIDI input.
|
||||
#define COMPILE_MIDI_OUT 1 // Set this setting to 1 to use the MIDI output.
|
||||
#define COMPILE_MIDI_THRU 1 // Set this setting to 1 to use the MIDI Soft Thru feature
|
||||
// Please note that the Thru will work only when both COMPILE_MIDI_IN and COMPILE_MIDI_OUT set to 1.
|
||||
|
||||
|
||||
#define MIDI_SERIAL_PORT Serial // Change the number (to Serial1 for example) if you want
|
||||
// to use a different serial port for MIDI I/O.
|
||||
|
||||
#define MIDI_USE_SOFTWARE_SERIAL 0 // Set to 1 to use SoftwareSerial instead of native serial ports.
|
||||
#define MIDI_SOFTSERIAL_RX_PIN 1 // This pin number will be used for MIDI Input
|
||||
#define MIDI_SOFTSERIAL_TX_PIN 2 // This pin number will be used for MIDI Output.
|
||||
|
||||
|
||||
#define USE_RUNNING_STATUS 1 // Running status enables short messages when sending multiple values
|
||||
// of the same type and channel.
|
||||
// Set to 0 if you have troubles controlling your hardware.
|
||||
|
||||
|
||||
#define USE_CALLBACKS 1 // Set this to 1 if you want to use callback handlers (to bind your functions to the library).
|
||||
// To use the callbacks, you need to have COMPILE_MIDI_IN set to 1
|
||||
|
||||
#define USE_1BYTE_PARSING 1 // Each call to MIDI.read will only parse one byte (might be faster).
|
||||
|
||||
|
||||
// END OF CONFIGURATION AREA
|
||||
// (do not modify anything under this line unless you know what you are doing)
|
||||
|
||||
|
||||
#define MIDI_BAUDRATE 31250
|
||||
|
||||
#define MIDI_CHANNEL_OMNI 0
|
||||
#define MIDI_CHANNEL_OFF 17 // and over
|
||||
|
||||
#define MIDI_SYSEX_ARRAY_SIZE 255 // Maximum size is 65535 bytes.
|
||||
|
||||
#define MIDI_PITCHBEND_MIN -8192
|
||||
#define MIDI_PITCHBEND_MAX 8191
|
||||
|
||||
|
||||
|
||||
/*! Type definition for practical use
|
||||
(because "unsigned char" is a bit long to write.. )
|
||||
*/
|
||||
typedef uint8_t byte;
|
||||
typedef uint16_t word;
|
||||
|
||||
|
||||
/*! Enumeration of MIDI types */
|
||||
enum kMIDIType
|
||||
{
|
||||
NoteOff = 0x80, ///< Note Off
|
||||
NoteOn = 0x90, ///< Note On
|
||||
AfterTouchPoly = 0xA0, ///< Polyphonic AfterTouch
|
||||
ControlChange = 0xB0, ///< Control Change / Channel Mode
|
||||
ProgramChange = 0xC0, ///< Program Change
|
||||
AfterTouchChannel = 0xD0, ///< Channel (monophonic) AfterTouch
|
||||
PitchBend = 0xE0, ///< Pitch Bend
|
||||
SystemExclusive = 0xF0, ///< System Exclusive
|
||||
TimeCodeQuarterFrame = 0xF1, ///< System Common - MIDI Time Code Quarter Frame
|
||||
SongPosition = 0xF2, ///< System Common - Song Position Pointer
|
||||
SongSelect = 0xF3, ///< System Common - Song Select
|
||||
TuneRequest = 0xF6, ///< System Common - Tune Request
|
||||
Clock = 0xF8, ///< System Real Time - Timing Clock
|
||||
Start = 0xFA, ///< System Real Time - Start
|
||||
Continue = 0xFB, ///< System Real Time - Continue
|
||||
Stop = 0xFC, ///< System Real Time - Stop
|
||||
ActiveSensing = 0xFE, ///< System Real Time - Active Sensing
|
||||
SystemReset = 0xFF, ///< System Real Time - System Reset
|
||||
InvalidType = 0x00 ///< For notifying errors
|
||||
};
|
||||
|
||||
/*! Enumeration of Thru filter modes */
|
||||
enum kThruFilterMode {
|
||||
Off = 0, ///< Thru disabled (nothing passes through).
|
||||
Full = 1, ///< Fully enabled Thru (every incoming message is sent back).
|
||||
SameChannel = 2, ///< Only the messages on the Input Channel will be sent back.
|
||||
DifferentChannel = 3 ///< All the messages but the ones on the Input Channel will be sent back.
|
||||
};
|
||||
|
||||
|
||||
enum eMIDICCNumber
|
||||
{
|
||||
// High resolution Continuous Controllers MSB (+32 for LSB) ----------------
|
||||
BankSelect = 0,
|
||||
ModulationWheel = 1,
|
||||
BreathController = 2,
|
||||
// CC3 undefined
|
||||
FootController = 4,
|
||||
PortamentoTime = 5,
|
||||
DataEntry = 6,
|
||||
ChannelVolume = 7,
|
||||
Balance = 8,
|
||||
// CC9 undefined
|
||||
Pan = 10,
|
||||
ExpressionController = 11,
|
||||
EffectControl1 = 12,
|
||||
EffectControl2 = 13,
|
||||
// CC14 undefined
|
||||
// CC15 undefined
|
||||
GeneralPurposeController1 = 16,
|
||||
GeneralPurposeController2 = 17,
|
||||
GeneralPurposeController3 = 18,
|
||||
GeneralPurposeController4 = 19,
|
||||
|
||||
// Switches ----------------------------------------------------------------
|
||||
Sustain = 64,
|
||||
Portamento = 65,
|
||||
Sostenuto = 66,
|
||||
SoftPedal = 67,
|
||||
Legato = 68,
|
||||
Hold2 = 69,
|
||||
|
||||
// Low resolution continuous controllers -----------------------------------
|
||||
SoundController1 = 70, ///< Synth: Sound Variation FX: Exciter On/Off
|
||||
SoundController2 = 71, ///< Synth: Harmonic Content FX: Compressor On/Off
|
||||
SoundController3 = 72, ///< Synth: Release Time FX: Distortion On/Off
|
||||
SoundController4 = 73, ///< Synth: Attack Time FX: EQ On/Off
|
||||
SoundController5 = 74, ///< Synth: Brightness FX: Expander On/Off
|
||||
SoundController6 = 75, ///< Synth: Decay Time FX: Reverb On/Off
|
||||
SoundController7 = 76, ///< Synth: Vibrato Rate FX: Delay On/Off
|
||||
SoundController8 = 77, ///< Synth: Vibrato Depth FX: Pitch Transpose On/Off
|
||||
SoundController9 = 78, ///< Synth: Vibrato Delay FX: Flange/Chorus On/Off
|
||||
SoundController10 = 79, ///< Synth: Undefined FX: Special Effects On/Off
|
||||
GeneralPurposeController5 = 80,
|
||||
GeneralPurposeController6 = 81,
|
||||
GeneralPurposeController7 = 82,
|
||||
GeneralPurposeController8 = 83,
|
||||
PortamentoControl = 84,
|
||||
// CC85 to CC90 undefined
|
||||
Effects1 = 91, ///< Reverb send level
|
||||
Effects2 = 92, ///< Tremolo depth
|
||||
Effects3 = 93, ///< Chorus send level
|
||||
Effects4 = 94, ///< Celeste depth
|
||||
Effects5 = 95, ///< Phaser depth
|
||||
|
||||
// Channel Mode messages ---------------------------------------------------
|
||||
AllSoundOff = 120,
|
||||
ResetAllControllers = 121,
|
||||
LocalControl = 122,
|
||||
AllNotesOff = 123,
|
||||
OmniModeOff = 124,
|
||||
OmniModeOn = 125,
|
||||
MonoModeOn = 126,
|
||||
PolyModeOn = 127
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*! The midimsg structure contains decoded data
|
||||
of a MIDI message read from the serial port
|
||||
with read() or thru().
|
||||
*/
|
||||
struct midimsg
|
||||
{
|
||||
|
||||
/*! The MIDI channel on which the message was recieved.
|
||||
\n Value goes from 1 to 16.
|
||||
*/
|
||||
byte channel;
|
||||
|
||||
/*! The type of the message
|
||||
(see the define section for types reference)
|
||||
*/
|
||||
kMIDIType type;
|
||||
|
||||
/*! The first data byte.
|
||||
\n Value goes from 0 to 127.
|
||||
*/
|
||||
byte data1;
|
||||
|
||||
/*! The second data byte.
|
||||
If the message is only 2 bytes long, this one is null.
|
||||
\n Value goes from 0 to 127.
|
||||
*/
|
||||
byte data2;
|
||||
|
||||
/*! System Exclusive dedicated byte array.
|
||||
\n Array length is stocked on 16 bits,
|
||||
in data1 (LSB) and data2 (MSB)
|
||||
*/
|
||||
byte sysex_array[MIDI_SYSEX_ARRAY_SIZE];
|
||||
|
||||
/*! This boolean indicates if the message is valid or not.
|
||||
There is no channel consideration here,
|
||||
validity means the message respects the MIDI norm.
|
||||
*/
|
||||
bool valid;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/*! \brief The main class for MIDI handling.\n
|
||||
See member descriptions to know how to use it,
|
||||
or check out the examples supplied with the library.
|
||||
*/
|
||||
class MIDI_Class
|
||||
//template<typename Uart>
|
||||
class MidiInterface
|
||||
{
|
||||
public:
|
||||
MidiInterface();
|
||||
~MidiInterface();
|
||||
|
||||
public:
|
||||
|
||||
// =========================================================================
|
||||
// Constructor and Destructor
|
||||
|
||||
MIDI_Class();
|
||||
~MIDI_Class();
|
||||
|
||||
void begin(const byte inChannel = 1);
|
||||
void begin(byte inChannel = 1);
|
||||
|
||||
|
||||
// =========================================================================
|
||||
// -------------------------------------------------------------------------
|
||||
// MIDI Output
|
||||
|
||||
#if COMPILE_MIDI_OUT // Start compilation block
|
||||
#if MIDI_BUILD_OUTPUT
|
||||
|
||||
public:
|
||||
void sendNoteOn(byte inNoteNumber,
|
||||
byte inVelocity,
|
||||
Channel inChannel);
|
||||
|
||||
void sendNoteOn(byte NoteNumber,byte Velocity,byte Channel);
|
||||
void sendNoteOff(byte NoteNumber,byte Velocity,byte Channel);
|
||||
void sendProgramChange(byte ProgramNumber,byte Channel);
|
||||
void sendControlChange(byte ControlNumber, byte ControlValue,byte Channel);
|
||||
void sendPitchBend(int PitchValue,byte Channel);
|
||||
void sendPitchBend(double PitchValue,byte Channel);
|
||||
void sendPolyPressure(byte NoteNumber,byte Pressure,byte Channel);
|
||||
void sendAfterTouch(byte Pressure,byte Channel);
|
||||
void sendSysEx(int length, const byte *const array,bool ArrayContainsBoundaries = false);
|
||||
void sendTimeCodeQuarterFrame(byte TypeNibble, byte ValuesNibble);
|
||||
void sendTimeCodeQuarterFrame(byte data);
|
||||
void sendSongPosition(unsigned int Beats);
|
||||
void sendSongSelect(byte SongNumber);
|
||||
void sendNoteOff(byte inNoteNumber,
|
||||
byte inVelocity,
|
||||
Channel inChannel);
|
||||
|
||||
void sendProgramChange(byte inProgramNumber,
|
||||
Channel inChannel);
|
||||
|
||||
void sendControlChange(byte inControlNumber,
|
||||
byte inControlValue,
|
||||
Channel inChannel);
|
||||
|
||||
void sendPitchBend(int inPitchValue, Channel inChannel);
|
||||
void sendPitchBend(double inPitchValue, Channel inChannel);
|
||||
|
||||
void sendPolyPressure(byte inNoteNumber,
|
||||
byte inPressure,
|
||||
Channel inChannel);
|
||||
|
||||
void sendAfterTouch(byte inPressure,
|
||||
Channel inChannel);
|
||||
|
||||
void sendSysEx(unsigned int inLength,
|
||||
const byte* inArray,
|
||||
bool inArrayContainsBoundaries = false);
|
||||
|
||||
void sendTimeCodeQuarterFrame(byte inTypeNibble,
|
||||
byte inValuesNibble);
|
||||
void sendTimeCodeQuarterFrame(byte inData);
|
||||
|
||||
void sendSongPosition(unsigned int inBeats);
|
||||
void sendSongSelect(byte inSongNumber);
|
||||
void sendTuneRequest();
|
||||
void sendRealTime(kMIDIType Type);
|
||||
void sendRealTime(MidiType inType);
|
||||
|
||||
void send(kMIDIType type, byte param1, byte param2, byte channel);
|
||||
void send(MidiType inType,
|
||||
DataByte inData1,
|
||||
DataByte inData2,
|
||||
Channel inChannel);
|
||||
|
||||
private:
|
||||
inline StatusByte getStatus(MidiType inType,
|
||||
Channel inChannel) const;
|
||||
|
||||
const byte genstatus(const kMIDIType inType,const byte inChannel) const;
|
||||
#endif // MIDI_BUILD_OUTPUT
|
||||
|
||||
|
||||
// Attributes
|
||||
#if USE_RUNNING_STATUS
|
||||
byte mRunningStatus_TX;
|
||||
#endif // USE_RUNNING_STATUS
|
||||
|
||||
#endif // COMPILE_MIDI_OUT
|
||||
|
||||
|
||||
|
||||
// =========================================================================
|
||||
// -------------------------------------------------------------------------
|
||||
// MIDI Input
|
||||
|
||||
#if COMPILE_MIDI_IN // Start compilation block
|
||||
#if MIDI_BUILD_INPUT
|
||||
|
||||
public:
|
||||
|
||||
bool read();
|
||||
bool read(const byte Channel);
|
||||
bool read(Channel inChannel);
|
||||
|
||||
// Getters
|
||||
kMIDIType getType() const;
|
||||
byte getChannel() const;
|
||||
byte getData1() const;
|
||||
byte getData2() const;
|
||||
const byte * getSysExArray() const;
|
||||
unsigned int getSysExArrayLength() const;
|
||||
bool check() const;
|
||||
public:
|
||||
inline MidiType getType() const;
|
||||
inline Channel getChannel() const;
|
||||
inline DataByte getData1() const;
|
||||
inline DataByte getData2() const;
|
||||
inline const byte* getSysExArray() const;
|
||||
inline unsigned int getSysExArrayLength() const;
|
||||
inline bool check() const;
|
||||
|
||||
byte getInputChannel() const
|
||||
{
|
||||
return mInputChannel;
|
||||
}
|
||||
|
||||
// Setters
|
||||
void setInputChannel(const byte Channel);
|
||||
|
||||
/*! \brief Extract an enumerated MIDI type from a status byte.
|
||||
|
||||
This is a utility static method, used internally, made public so you can handle kMIDITypes more easily.
|
||||
*/
|
||||
static inline const kMIDIType getTypeFromStatusByte(const byte inStatus)
|
||||
{
|
||||
if ((inStatus < 0x80) ||
|
||||
(inStatus == 0xF4) ||
|
||||
(inStatus == 0xF5) ||
|
||||
(inStatus == 0xF9) ||
|
||||
(inStatus == 0xFD)) return InvalidType; // data bytes and undefined.
|
||||
if (inStatus < 0xF0) return (kMIDIType)(inStatus & 0xF0); // Channel message, remove channel nibble.
|
||||
else return (kMIDIType)inStatus;
|
||||
}
|
||||
public:
|
||||
inline Channel getInputChannel() const;
|
||||
inline void setInputChannel(Channel inChannel);
|
||||
|
||||
public:
|
||||
static inline MidiType getTypeFromStatusByte(const byte inStatus);
|
||||
|
||||
private:
|
||||
|
||||
|
|
@ -366,7 +154,7 @@ public:
|
|||
void setHandleActiveSensing(void (*fptr)(void));
|
||||
void setHandleSystemReset(void (*fptr)(void));
|
||||
|
||||
void disconnectCallbackFromType(kMIDIType Type);
|
||||
void disconnectCallbackFromType(MidiType Type);
|
||||
|
||||
private:
|
||||
|
||||
|
|
@ -393,39 +181,46 @@ private:
|
|||
|
||||
#endif // USE_CALLBACKS
|
||||
|
||||
#endif // COMPILE_MIDI_IN
|
||||
#endif // MIDI_BUILD_INPUT
|
||||
|
||||
|
||||
// =========================================================================
|
||||
// MIDI Soft Thru
|
||||
|
||||
#if (COMPILE_MIDI_IN && COMPILE_MIDI_OUT && COMPILE_MIDI_THRU)
|
||||
#if (MIDI_BUILD_INPUT && MIDI_BUILD_OUTPUT && MIDI_BUILD_THRU)
|
||||
|
||||
public:
|
||||
inline MidiFilterMode getFilterMode() const;
|
||||
inline bool getThruState() const;
|
||||
|
||||
// Getters
|
||||
kThruFilterMode getFilterMode() const { return mThruFilterMode; }
|
||||
bool getThruState() const { return mThruActivated; }
|
||||
|
||||
|
||||
// Setters
|
||||
void turnThruOn(kThruFilterMode inThruFilterMode = Full);
|
||||
void turnThruOff();
|
||||
|
||||
void setThruFilterMode(const kThruFilterMode inThruFilterMode);
|
||||
inline void turnThruOn(MidiFilterMode inThruFilterMode = Full);
|
||||
inline void turnThruOff();
|
||||
inline void setThruFilterMode(MidiFilterMode inThruFilterMode);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
void thru_filter(byte inChannel);
|
||||
|
||||
bool mThruActivated;
|
||||
kThruFilterMode mThruFilterMode;
|
||||
bool mThruActivated : 1;
|
||||
MidiFilterMode mThruFilterMode : 7;
|
||||
|
||||
#endif // Thru
|
||||
|
||||
|
||||
|
||||
// Attributes
|
||||
#if MIDI_USE_RUNNING_STATUS
|
||||
StatusByte mRunningStatus_TX;
|
||||
#endif // MIDI_USE_RUNNING_STATUS
|
||||
|
||||
|
||||
};
|
||||
|
||||
extern MIDI_Class MIDI;
|
||||
END_MIDI_NAMESPACE
|
||||
|
||||
#endif // LIB_MIDI_H_
|
||||
#if MIDI_AUTO_INSTANCIATE
|
||||
extern midi::MidiInterface MIDI;
|
||||
#endif
|
||||
|
||||
#include "midi_Inline.hpp"
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* @file midi_Defs.h
|
||||
* Project Arduino MIDI Library
|
||||
* @brief MIDI Library for the Arduino - Definitions
|
||||
* @version 3.5
|
||||
* @version 4.0
|
||||
* @author Francois Best
|
||||
* @date 24/02/11
|
||||
* license GPL Forty Seven Effects - 2011
|
||||
|
|
@ -15,23 +15,31 @@
|
|||
|
||||
BEGIN_MIDI_NAMESPACE
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#define MIDI_CHANNEL_OMNI 0
|
||||
#define MIDI_CHANNEL_OFF 17 // and over
|
||||
#define MIDI_CHANNEL_OFF 17 // and over
|
||||
|
||||
#define MIDI_PITCHBEND_MIN -8192
|
||||
#define MIDI_PITCHBEND_MAX 8191
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Type definitions
|
||||
|
||||
/*! Type definition for practical use
|
||||
(because "unsigned char" is a bit long to write.. )
|
||||
*/
|
||||
typedef uint8_t byte;
|
||||
typedef uint16_t word;
|
||||
|
||||
typedef byte StatusByte;
|
||||
typedef byte DataByte;
|
||||
typedef byte Channel;
|
||||
typedef byte FilterMode;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/*! Enumeration of MIDI types */
|
||||
enum kMIDIType
|
||||
enum MidiType
|
||||
{
|
||||
InvalidType = 0x00, ///< For notifying errors
|
||||
NoteOff = 0x80, ///< Note Off
|
||||
NoteOn = 0x90, ///< Note On
|
||||
AfterTouchPoly = 0xA0, ///< Polyphonic AfterTouch
|
||||
|
|
@ -50,19 +58,22 @@ enum kMIDIType
|
|||
Stop = 0xFC, ///< System Real Time - Stop
|
||||
ActiveSensing = 0xFE, ///< System Real Time - Active Sensing
|
||||
SystemReset = 0xFF, ///< System Real Time - System Reset
|
||||
InvalidType = 0x00 ///< For notifying errors
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/*! Enumeration of Thru filter modes */
|
||||
enum kThruFilterMode {
|
||||
enum MidiFilterMode
|
||||
{
|
||||
Off = 0, ///< Thru disabled (nothing passes through).
|
||||
Full = 1, ///< Fully enabled Thru (every incoming message is sent back).
|
||||
SameChannel = 2, ///< Only the messages on the Input Channel will be sent back.
|
||||
DifferentChannel = 3 ///< All the messages but the ones on the Input Channel will be sent back.
|
||||
DifferentChannel = 3, ///< All the messages but the ones on the Input Channel will be sent back.
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
enum eMIDICCNumber
|
||||
enum MidiControlChangeNumber
|
||||
{
|
||||
// High resolution Continuous Controllers MSB (+32 for LSB) ----------------
|
||||
BankSelect = 0,
|
||||
|
|
@ -92,7 +103,7 @@ enum eMIDICCNumber
|
|||
Sostenuto = 66,
|
||||
SoftPedal = 67,
|
||||
Legato = 68,
|
||||
Hold2 = 69,
|
||||
Hold = 69,
|
||||
|
||||
// Low resolution continuous controllers -----------------------------------
|
||||
SoundController1 = 70, ///< Synth: Sound Variation FX: Exciter On/Off
|
||||
|
|
@ -129,40 +140,41 @@ enum eMIDICCNumber
|
|||
};
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/*! The midimsg structure contains decoded data
|
||||
of a MIDI message read from the serial port
|
||||
with read() or thru().
|
||||
*/
|
||||
struct midimsg
|
||||
struct Message
|
||||
{
|
||||
|
||||
/*! The MIDI channel on which the message was recieved.
|
||||
\n Value goes from 1 to 16.
|
||||
*/
|
||||
byte channel;
|
||||
Channel channel;
|
||||
|
||||
/*! The type of the message
|
||||
(see the define section for types reference)
|
||||
(see the MidiType enum for types reference)
|
||||
*/
|
||||
kMIDIType type;
|
||||
MidiType type;
|
||||
|
||||
/*! The first data byte.
|
||||
\n Value goes from 0 to 127.
|
||||
*/
|
||||
byte data1;
|
||||
DataByte data1;
|
||||
|
||||
/*! The second data byte.
|
||||
If the message is only 2 bytes long, this one is null.
|
||||
\n Value goes from 0 to 127.
|
||||
*/
|
||||
byte data2;
|
||||
DataByte data2;
|
||||
|
||||
/*! System Exclusive dedicated byte array.
|
||||
\n Array length is stocked on 16 bits,
|
||||
in data1 (LSB) and data2 (MSB)
|
||||
*/
|
||||
byte sysex_array[MIDI_SYSEX_ARRAY_SIZE];
|
||||
DataByte sysex_array[MIDI_SYSEX_ARRAY_SIZE];
|
||||
|
||||
/*! This boolean indicates if the message is valid or not.
|
||||
There is no channel consideration here,
|
||||
|
|
@ -172,5 +184,4 @@ struct midimsg
|
|||
|
||||
};
|
||||
|
||||
|
||||
END_MIDI_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -0,0 +1,167 @@
|
|||
/*!
|
||||
* @file midi_Inline.hpp
|
||||
* Project Arduino MIDI Library
|
||||
* @brief MIDI Library for the Arduino - Inline implementations
|
||||
* @version 4.0
|
||||
* @author Francois Best
|
||||
* @date 24/02/11
|
||||
* license GPL Forty Seven Effects - 2011
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
BEGIN_MIDI_NAMESPACE
|
||||
|
||||
#if MIDI_BUILD_OUTPUT
|
||||
|
||||
StatusByte MidiInterface::getStatus(kMIDIType inType,
|
||||
Channel inChannel) const
|
||||
{
|
||||
return ((byte)inType | ((inChannel - 1) & 0x0F));
|
||||
}
|
||||
|
||||
#endif // MIDI_BUILD_OUTPUT
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#if MIDI_BUILD_INPUT
|
||||
|
||||
/*! \brief Get the last received message's type
|
||||
|
||||
Returns an enumerated type. @see MidiType
|
||||
*/
|
||||
MidiType MidiInterface::getType() const
|
||||
{
|
||||
return mMessage.type;
|
||||
}
|
||||
|
||||
/*! \brief Get the channel of the message stored in the structure.
|
||||
|
||||
\return Channel range is 1 to 16.
|
||||
For non-channel messages, this will return 0.
|
||||
*/
|
||||
Channel MidiInterface::getChannel() const
|
||||
{
|
||||
return mMessage.channel;
|
||||
}
|
||||
|
||||
/*! \brief Get the first data byte of the last received message. */
|
||||
DataByte MidiInterface::getData1() const
|
||||
{
|
||||
return mMessage.data1;
|
||||
}
|
||||
|
||||
/*! \brief Get the second data byte of the last received message. */
|
||||
DataByte MidiInterface::getData2() const
|
||||
{
|
||||
return mMessage.data2;
|
||||
}
|
||||
|
||||
/*! \brief Get the System Exclusive byte array.
|
||||
|
||||
@see getSysExArrayLength to get the array's length in bytes.
|
||||
*/
|
||||
const byte* MidiInterface::getSysExArray() const
|
||||
{
|
||||
return mMessage.sysex_array;
|
||||
}
|
||||
|
||||
/*! \brief Get the lenght of the System Exclusive array.
|
||||
|
||||
It is coded using data1 as LSB and data2 as MSB.
|
||||
\return The array's length, in bytes.
|
||||
*/
|
||||
unsigned int MidiInterface::getSysExArrayLength() const
|
||||
{
|
||||
const unsigned int size = ((unsigned)(mMessage.data2) << 8) | mMessage.data1;
|
||||
return (size > MIDI_SYSEX_ARRAY_SIZE) ? MIDI_SYSEX_ARRAY_SIZE : size;
|
||||
}
|
||||
|
||||
/*! \brief Check if a valid message is stored in the structure. */
|
||||
bool MidiInterface::check() const
|
||||
{
|
||||
return mMessage.valid;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
Channel MidiInterface::getInputChannel() const
|
||||
{
|
||||
return mInputChannel;
|
||||
}
|
||||
|
||||
/*! \brief Set the value for the input MIDI channel
|
||||
\param Channel 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.
|
||||
*/
|
||||
void MidiInterface::setInputChannel(Channel inChannel)
|
||||
{
|
||||
mInputChannel = inChannel;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/*! \brief Extract an enumerated MIDI type from a status byte.
|
||||
|
||||
This is a utility static method, used internally,
|
||||
made public so you can handle MidiTypes more easily.
|
||||
*/
|
||||
MidiType MidiInterface::getTypeFromStatusByte(const byte inStatus)
|
||||
{
|
||||
if ((inStatus < 0x80) ||
|
||||
(inStatus == 0xF4) ||
|
||||
(inStatus == 0xF5) ||
|
||||
(inStatus == 0xF9) ||
|
||||
(inStatus == 0xFD)) return InvalidType; // data bytes and undefined.
|
||||
if (inStatus < 0xF0) return (MidiType)(inStatus & 0xF0); // Channel message, remove channel nibble.
|
||||
else return (MidiType)inStatus;
|
||||
}
|
||||
|
||||
#endif // MIDI_BUILD_INPUT
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#if (MIDI_BUILD_INPUT && MIDI_BUILD_OUTPUT && MIDI_BUILD_THRU)
|
||||
|
||||
MidiFilterMode MidiInterface::getFilterMode() const
|
||||
{
|
||||
return mThruFilterMode;
|
||||
}
|
||||
|
||||
bool MidiInterface::getThruState() const
|
||||
{
|
||||
return mThruActivated;
|
||||
}
|
||||
|
||||
/*! \brief Setter method: turn message mirroring on. */
|
||||
void MidiInterface::turnThruOn(MidiFilterMode inThruFilterMode)
|
||||
{
|
||||
mThruActivated = true;
|
||||
mThruFilterMode = inThruFilterMode;
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Setter method: turn message mirroring off. */
|
||||
void MidiInterface::turnThruOff()
|
||||
{
|
||||
mThruActivated = false;
|
||||
mThruFilterMode = Off;
|
||||
}
|
||||
|
||||
/*! \brief Set the filter for thru mirroring
|
||||
\param inThruFilterMode a filter mode
|
||||
|
||||
@see MidiFilterMode
|
||||
*/
|
||||
void MidiInterface::setThruFilterMode(MidiFilterMode inThruFilterMode)
|
||||
{
|
||||
mThruFilterMode = inThruFilterMode;
|
||||
if (mThruFilterMode != Off)
|
||||
mThruActivated = true;
|
||||
else
|
||||
mThruActivated = false;
|
||||
}
|
||||
|
||||
#endif // MIDI_BUILD_THRU
|
||||
|
||||
END_MIDI_NAMESPACE
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
* @file midi_Namespace.h
|
||||
* Project Arduino MIDI Library
|
||||
* @brief MIDI Library for the Arduino - Namespace declaration
|
||||
* @version 3.5
|
||||
* @version 4.0
|
||||
* @author Francois Best
|
||||
* @date 24/02/11
|
||||
* license GPL Forty Seven Effects - 2011
|
||||
|
|
|
|||
|
|
@ -27,23 +27,25 @@ BEGIN_MIDI_NAMESPACE
|
|||
// (MIDI in, out, thru), or to 0 to disable the feature and save space.
|
||||
// Note that the Thru can only work if in and out are enabled.
|
||||
|
||||
#define MIDI_BUILD_INPUT 1
|
||||
#define MIDI_BUILD_OUTPUT 1
|
||||
#define MIDI_BUILD_THRU 1
|
||||
#define MIDI_BUILD_INPUT 1
|
||||
#define MIDI_BUILD_OUTPUT 1
|
||||
#define MIDI_BUILD_THRU 1
|
||||
|
||||
// Create a MIDI object automatically on the port defined with MIDI_SERIAL_PORT.
|
||||
#define MIDI_AUTO_INSTANCIATE 1
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Serial port configuration
|
||||
|
||||
// Change the number (to Serial1 for example)
|
||||
// if you want to use a different serial port for MIDI I/O.
|
||||
#define MIDI_SERIAL_PORT Serial
|
||||
// Set the default port to use for MIDI.
|
||||
#define MIDI_SERIAL_PORT Serial
|
||||
|
||||
// Software serial options
|
||||
#define MIDI_USE_SOFTWARE_SERIAL 0
|
||||
#define MIDI_USE_SOFTWARE_SERIAL 0
|
||||
|
||||
#if MIDI_USE_SOFTWARE_SERIAL
|
||||
#define MIDI_SOFTSERIAL_RX_PIN 1 // Pin number to use for MIDI Input
|
||||
#define MIDI_SOFTSERIAL_TX_PIN 2 // Pin number to use for MIDI Output.
|
||||
#define MIDI_SOFTSERIAL_RX_PIN 1 // Pin number to use for MIDI Input
|
||||
#define MIDI_SOFTSERIAL_TX_PIN 2 // Pin number to use for MIDI Output
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
@ -52,11 +54,10 @@ BEGIN_MIDI_NAMESPACE
|
|||
// Running status enables short messages when sending multiple values
|
||||
// of the same type and channel.
|
||||
// Set to 0 if you have troubles controlling your hardware.
|
||||
#define MIDI_USE_RUNNING_STATUS 1
|
||||
#define MIDI_USE_1BYTE_PARSING 1
|
||||
#define MIDI_USE_RUNNING_STATUS 1
|
||||
#define MIDI_USE_1BYTE_PARSING 1
|
||||
|
||||
|
||||
#define MIDI_BAUDRATE 31250
|
||||
#define MIDI_SYSEX_ARRAY_SIZE 255 // Maximum size is 65535 bytes.
|
||||
#define MIDI_BAUDRATE 31250
|
||||
#define MIDI_SYSEX_ARRAY_SIZE 255 // Maximum size is 65535 bytes.
|
||||
|
||||
END_MIDI_NAMESPACE
|
||||
|
|
|
|||
Loading…
Reference in New Issue