Quake wip.

This commit is contained in:
Francois Best 2012-09-05 18:32:42 +02:00
parent 5a42cb006d
commit 4b8b38aeaf
6 changed files with 395 additions and 525 deletions

View File

@ -2,7 +2,7 @@
* @file MIDI.cpp * @file MIDI.cpp
* Project Arduino MIDI Library * Project Arduino MIDI Library
* @brief MIDI Library for the Arduino * @brief MIDI Library for the Arduino
* @version 3.2 * @version 4.0
* @author Francois Best * @author Francois Best
* @date 24/02/11 * @date 24/02/11
* license GPL Forty Seven Effects - 2011 * license GPL Forty Seven Effects - 2011
@ -12,6 +12,7 @@
#include <stdlib.h> #include <stdlib.h>
#include "Arduino.h" // If using an old (pre-1.0) version of Arduino, #include "Arduino.h" // If using an old (pre-1.0) version of Arduino,
// use WConstants.h instead of Arduino.h // use WConstants.h instead of Arduino.h
#if MIDI_USE_SOFTWARE_SERIAL #if MIDI_USE_SOFTWARE_SERIAL
// Note: Make sure the following relative path is correct. // Note: Make sure the following relative path is correct.
@ -26,14 +27,17 @@ SoftwareSerial softSerialClass(MIDI_SOFTSERIAL_RX_PIN,
#endif // MIDI_USE_SOFTWARE_SERIAL #endif // MIDI_USE_SOFTWARE_SERIAL
/*! \brief Main instance (the class comes pre-instantiated). */ #if MIDI_AUTO_INSTANCIATE
MIDI_Class MIDI; midi::MidiInterface MIDI;
#endif
/*! \brief Default constructor for MIDI_Class. */ BEGIN_MIDI_NAMESPACE
MIDI_Class::MIDI_Class()
/*! \brief Default constructor for MidiInterface. */
MidiInterface::MidiInterface()
{ {
#if COMPILE_MIDI_IN && USE_CALLBACKS #if MIDI_BUILD_INPUT && USE_CALLBACKS
// Initialise callbacks to NULL pointer // Initialise callbacks to NULL pointer
mNoteOffCallback = NULL; 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... 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 - Input channel set to 1 if no value is specified
- Full thru mirroring - Full thru mirroring
*/ */
void MIDI_Class::begin(const byte inChannel) void MidiInterface::begin(const byte inChannel)
{ {
// Initialise the Serial port // Initialise the Serial port
MIDI_SERIAL_PORT.begin(MIDI_BAUDRATE); MIDI_SERIAL_PORT.begin(MIDI_BAUDRATE);
#if COMPILE_MIDI_OUT && USE_RUNNING_STATUS #if MIDI_BUILD_OUTPUT && MIDI_USE_RUNNING_STATUS
mRunningStatus_TX = InvalidType; 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; mInputChannel = inChannel;
mRunningStatus_RX = InvalidType; mRunningStatus_RX = InvalidType;
@ -100,10 +104,10 @@ void MIDI_Class::begin(const byte inChannel)
mMessage.data1 = 0; mMessage.data1 = 0;
mMessage.data2 = 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; mThruFilterMode = Full;
mThruActivated = true; mThruActivated = true;
@ -117,14 +121,7 @@ void MIDI_Class::begin(const byte inChannel)
// MIDI Output // MIDI Output
// ============================================================================= // =============================================================================
#if COMPILE_MIDI_OUT #if MIDI_BUILD_OUTPUT
// 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));
}
/*! \brief Generate and send a MIDI message from the values given. /*! \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 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.
*/ */
void MIDI_Class::send(kMIDIType type, void MidiInterface::send(MidiType type,
byte data1, byte data1,
byte data2, byte data2,
byte channel) byte channel)
@ -149,7 +146,7 @@ void MIDI_Class::send(kMIDIType type,
type < NoteOff) type < NoteOff)
{ {
#if USE_RUNNING_STATUS #if MIDI_USE_RUNNING_STATUS
mRunningStatus_TX = InvalidType; mRunningStatus_TX = InvalidType;
#endif #endif
@ -164,7 +161,7 @@ void MIDI_Class::send(kMIDIType type,
byte statusbyte = genstatus(type,channel); byte statusbyte = genstatus(type,channel);
#if USE_RUNNING_STATUS #if MIDI_USE_RUNNING_STATUS
// Check Running Status // Check Running Status
if (mRunningStatus_TX != statusbyte) 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: 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
*/ */
void MIDI_Class::sendNoteOn(byte NoteNumber, void MidiInterface::sendNoteOn(byte NoteNumber,
byte Velocity, byte Velocity,
byte Channel) byte Channel)
{ {
@ -217,7 +214,7 @@ void MIDI_Class::sendNoteOn(byte NoteNumber,
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
*/ */
void MIDI_Class::sendNoteOff(byte NoteNumber, void MidiInterface::sendNoteOff(byte NoteNumber,
byte Velocity, byte Velocity,
byte Channel) byte Channel)
{ {
@ -229,7 +226,7 @@ void MIDI_Class::sendNoteOff(byte NoteNumber,
\param ProgramNumber The Program to select (0 to 127). \param ProgramNumber The Program to select (0 to 127).
\param Channel The channel on which the message will be sent (1 to 16). \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) byte Channel)
{ {
send(ProgramChange,ProgramNumber,0,Channel); send(ProgramChange,ProgramNumber,0,Channel);
@ -244,7 +241,7 @@ void MIDI_Class::sendProgramChange(byte ProgramNumber,
See the detailed controllers numbers & description here: See the detailed controllers numbers & description here:
http://www.somascape.org/midi/tech/spec.html#ctrlnums http://www.somascape.org/midi/tech/spec.html#ctrlnums
*/ */
void MIDI_Class::sendControlChange(byte ControlNumber, void MidiInterface::sendControlChange(byte ControlNumber,
byte ControlValue, byte ControlValue,
byte Channel) byte Channel)
{ {
@ -257,7 +254,7 @@ void MIDI_Class::sendControlChange(byte ControlNumber,
\param Pressure The amount of AfterTouch to apply (0 to 127). \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). \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 Pressure,
byte Channel) byte Channel)
{ {
@ -269,7 +266,7 @@ void MIDI_Class::sendPolyPressure(byte NoteNumber,
\param Pressure The amount of AfterTouch to apply to all notes. \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). \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) byte Channel)
{ {
send(AfterTouchChannel,Pressure,0,Channel); send(AfterTouchChannel,Pressure,0,Channel);
@ -282,7 +279,7 @@ void MIDI_Class::sendAfterTouch(byte Pressure,
center value is 0. center value is 0.
\param Channel The channel on which the message will be sent (1 to 16). \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) byte Channel)
{ {
const unsigned int bend = PitchValue - MIDI_PITCHBEND_MIN; 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. 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). \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) byte Channel)
{ {
const int pitchval = PitchValue * MIDI_PITCHBEND_MAX; 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 default value for ArrayContainsBoundaries is set to 'false' for compatibility
with previous versions of the library. with previous versions of the library.
*/ */
void MIDI_Class::sendSysEx(int length, void MidiInterface::sendSysEx(int length,
const byte *const array, const byte *const array,
bool ArrayContainsBoundaries) bool ArrayContainsBoundaries)
{ {
@ -332,7 +329,7 @@ void MIDI_Class::sendSysEx(int length,
MIDI_SERIAL_PORT.write(array[i]); MIDI_SERIAL_PORT.write(array[i]);
} }
#if USE_RUNNING_STATUS #if MIDI_USE_RUNNING_STATUS
mRunningStatus_TX = InvalidType; mRunningStatus_TX = InvalidType;
#endif #endif
} }
@ -343,7 +340,7 @@ void MIDI_Class::sendSysEx(int length,
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).
*/ */
void MIDI_Class::sendTuneRequest() void MidiInterface::sendTuneRequest()
{ {
sendRealTime(TuneRequest); sendRealTime(TuneRequest);
} }
@ -355,7 +352,7 @@ void MIDI_Class::sendTuneRequest()
\param ValuesNibble MTC data \param ValuesNibble MTC data
See MIDI Specification for more information. 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) ); const byte data = ( ((TypeNibble & 0x07) << 4) | (ValuesNibble & 0x0F) );
sendTimeCodeQuarterFrame(data); 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, \param data if you want to encode directly the nibbles in your program,
you can send the byte here. 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((byte)TimeCodeQuarterFrame);
MIDI_SERIAL_PORT.write(data); MIDI_SERIAL_PORT.write(data);
#if USE_RUNNING_STATUS #if MIDI_USE_RUNNING_STATUS
mRunningStatus_TX = InvalidType; mRunningStatus_TX = InvalidType;
#endif #endif
} }
@ -382,25 +379,25 @@ void MIDI_Class::sendTimeCodeQuarterFrame(byte data)
/*! \brief Send a Song Position Pointer message. /*! \brief Send a Song Position Pointer message.
\param Beats The number of beats since the start of the song. \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((byte)SongPosition);
MIDI_SERIAL_PORT.write(Beats & 0x7F); MIDI_SERIAL_PORT.write(Beats & 0x7F);
MIDI_SERIAL_PORT.write((Beats >> 7) & 0x7F); MIDI_SERIAL_PORT.write((Beats >> 7) & 0x7F);
#if USE_RUNNING_STATUS #if MIDI_USE_RUNNING_STATUS
mRunningStatus_TX = InvalidType; mRunningStatus_TX = InvalidType;
#endif #endif
} }
/*! \brief Send a Song Select message */ /*! \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((byte)SongSelect);
MIDI_SERIAL_PORT.write(SongNumber & 0x7F); MIDI_SERIAL_PORT.write(SongNumber & 0x7F);
#if USE_RUNNING_STATUS #if MIDI_USE_RUNNING_STATUS
mRunningStatus_TX = InvalidType; mRunningStatus_TX = InvalidType;
#endif #endif
} }
@ -411,9 +408,9 @@ void MIDI_Class::sendSongSelect(byte SongNumber)
\param Type The available Real Time types are: \param Type The available Real Time types are:
Start, Stop, Continue, Clock, ActiveSensing and SystemReset. Start, Stop, Continue, Clock, ActiveSensing and SystemReset.
You can also send a Tune Request with this method. 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) 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 // 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 USE_RUNNING_STATUS #if MIDI_USE_RUNNING_STATUS
if (Type == TuneRequest) mRunningStatus_TX = InvalidType; if (Type == TuneRequest) mRunningStatus_TX = InvalidType;
#endif #endif
} }
#endif // COMPILE_MIDI_OUT #endif // MIDI_BUILD_OUTPUT
// ============================================================================= // =============================================================================
// MIDI Input // MIDI Input
// ============================================================================= // =============================================================================
#if COMPILE_MIDI_IN #if MIDI_BUILD_INPUT
/*! \brief Read a MIDI message from the serial port /*! \brief Read a MIDI message from the serial port
using the main input channel (see setInputChannel() for reference). 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, If the Thru is enabled and the messages matches the filter,
it is sent back on the MIDI output. it is sent back on the MIDI output.
*/ */
bool MIDI_Class::read() bool MidiInterface::read()
{ {
return read(mInputChannel); return read(mInputChannel);
} }
@ -465,7 +462,7 @@ bool MIDI_Class::read()
/*! \brief Reading/thru-ing method, the same as read() /*! \brief Reading/thru-ing method, the same as read()
with a given input channel to read on. 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) if (inChannel >= MIDI_CHANNEL_OFF)
return false; // MIDI Input disabled. return false; // MIDI Input disabled.
@ -475,7 +472,7 @@ bool MIDI_Class::read(const byte inChannel)
if (input_filter(inChannel)) if (input_filter(inChannel))
{ {
#if (COMPILE_MIDI_OUT && COMPILE_MIDI_THRU) #if (MIDI_BUILD_OUTPUT && MIDI_BUILD_THRU)
thru_filter(inChannel); thru_filter(inChannel);
#endif #endif
@ -491,7 +488,7 @@ bool MIDI_Class::read(const byte inChannel)
// Private method: MIDI parser // Private method: MIDI parser
bool MIDI_Class::parse(byte inChannel) bool MidiInterface::parse(byte inChannel)
{ {
const byte bytes_available = MIDI_SERIAL_PORT.available(); 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, // This is done by leaving the pending message as is,
// it will be completed on next calls. // it will be completed on next calls.
mMessage.type = (kMIDIType)extracted; mMessage.type = (MidiType)extracted;
mMessage.data1 = 0; mMessage.data1 = 0;
mMessage.data2 = 0; mMessage.data2 = 0;
mMessage.channel = 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 // 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 // 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)
@ -811,7 +808,7 @@ bool MIDI_Class::input_filter(byte inChannel)
// Private method: reset input attributes // Private method: reset input attributes
void MIDI_Class::reset_input_attributes() void MidiInterface::reset_input_attributes()
{ {
mPendingMessageIndex = 0; mPendingMessageIndex = 0;
mPendingMessageExpectedLenght = 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 #if USE_CALLBACKS
void MIDI_Class::setHandleNoteOff(void (*fptr)(byte channel, byte note, byte velocity)) { mNoteOffCallback = fptr; } void MidiInterface::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 MidiInterface::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 MidiInterface::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 MidiInterface::setHandleControlChange(void (*fptr)(byte channel, byte number, byte value)) { mControlChangeCallback = fptr; }
void MIDI_Class::setHandleProgramChange(void (*fptr)(byte channel, byte number)) { mProgramChangeCallback = fptr; } void MidiInterface::setHandleProgramChange(void (*fptr)(byte channel, byte number)) { mProgramChangeCallback = fptr; }
void MIDI_Class::setHandleAfterTouchChannel(void (*fptr)(byte channel, byte pressure)) { mAfterTouchChannelCallback = fptr; } void MidiInterface::setHandleAfterTouchChannel(void (*fptr)(byte channel, byte pressure)) { mAfterTouchChannelCallback = fptr; }
void MIDI_Class::setHandlePitchBend(void (*fptr)(byte channel, int bend)) { mPitchBendCallback = fptr; } void MidiInterface::setHandlePitchBend(void (*fptr)(byte channel, int bend)) { mPitchBendCallback = fptr; }
void MIDI_Class::setHandleSystemExclusive(void (*fptr)(byte * array, byte size)) { mSystemExclusiveCallback = fptr; } void MidiInterface::setHandleSystemExclusive(void (*fptr)(byte * array, byte size)) { mSystemExclusiveCallback = fptr; }
void MIDI_Class::setHandleTimeCodeQuarterFrame(void (*fptr)(byte data)) { mTimeCodeQuarterFrameCallback = fptr; } void MidiInterface::setHandleTimeCodeQuarterFrame(void (*fptr)(byte data)) { mTimeCodeQuarterFrameCallback = fptr; }
void MIDI_Class::setHandleSongPosition(void (*fptr)(unsigned int beats)) { mSongPositionCallback = fptr; } void MidiInterface::setHandleSongPosition(void (*fptr)(unsigned int beats)) { mSongPositionCallback = fptr; }
void MIDI_Class::setHandleSongSelect(void (*fptr)(byte songnumber)) { mSongSelectCallback = fptr; } void MidiInterface::setHandleSongSelect(void (*fptr)(byte songnumber)) { mSongSelectCallback = fptr; }
void MIDI_Class::setHandleTuneRequest(void (*fptr)(void)) { mTuneRequestCallback = fptr; } void MidiInterface::setHandleTuneRequest(void (*fptr)(void)) { mTuneRequestCallback = fptr; }
void MIDI_Class::setHandleClock(void (*fptr)(void)) { mClockCallback = fptr; } void MidiInterface::setHandleClock(void (*fptr)(void)) { mClockCallback = fptr; }
void MIDI_Class::setHandleStart(void (*fptr)(void)) { mStartCallback = fptr; } void MidiInterface::setHandleStart(void (*fptr)(void)) { mStartCallback = fptr; }
void MIDI_Class::setHandleContinue(void (*fptr)(void)) { mContinueCallback = fptr; } void MidiInterface::setHandleContinue(void (*fptr)(void)) { mContinueCallback = fptr; }
void MIDI_Class::setHandleStop(void (*fptr)(void)) { mStopCallback = fptr; } void MidiInterface::setHandleStop(void (*fptr)(void)) { mStopCallback = fptr; }
void MIDI_Class::setHandleActiveSensing(void (*fptr)(void)) { mActiveSensingCallback = fptr; } void MidiInterface::setHandleActiveSensing(void (*fptr)(void)) { mActiveSensingCallback = fptr; }
void MIDI_Class::setHandleSystemReset(void (*fptr)(void)) { mSystemResetCallback = fptr; } void MidiInterface::setHandleSystemReset(void (*fptr)(void)) { mSystemResetCallback = fptr; }
/*! \brief Detach an external function from the given type. /*! \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. \param Type 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.
*/ */
void MIDI_Class::disconnectCallbackFromType(kMIDIType Type) void MidiInterface::disconnectCallbackFromType(MidiType Type)
{ {
switch (Type) switch (Type)
{ {
@ -952,7 +877,7 @@ void MIDI_Class::disconnectCallbackFromType(kMIDIType Type)
// Private - launch callback function based on received 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. // The order is mixed to allow frequent messages to trigger their callback faster.
switch (mMessage.type) switch (mMessage.type)
@ -994,49 +919,18 @@ void MIDI_Class::launchCallback()
#endif // USE_CALLBACKS #endif // USE_CALLBACKS
#endif // COMPILE_MIDI_IN #endif // MIDI_BUILD_INPUT
// ============================================================================= // =============================================================================
// MIDI Soft Thru // MIDI Soft Thru
// ============================================================================= // =============================================================================
#if (COMPILE_MIDI_IN && COMPILE_MIDI_OUT && COMPILE_MIDI_THRU) #if (MIDI_BUILD_INPUT && MIDI_BUILD_OUTPUT && MIDI_BUILD_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;
}
// This method is called upon reception of a message // This method is called upon reception of a message
// and takes care of Thru filtering and sending. // 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 #endif // Thru
END_MIDI_NAMESPACE

View File

@ -2,7 +2,7 @@
* @file MIDI.h * @file MIDI.h
* Project Arduino MIDI Library * Project Arduino MIDI Library
* @brief MIDI Library for the Arduino * @brief MIDI Library for the Arduino
* @version 3.2 * @version 4.0
* @author Francois Best * @author Francois Best
* @date 24/02/11 * @date 24/02/11
* license GPL Forty Seven Effects - 2011 * license GPL Forty Seven Effects - 2011
@ -15,313 +15,101 @@
#include "midi_Settings.h" #include "midi_Settings.h"
#include "midi_Defs.h" #include "midi_Defs.h"
/* BEGIN_MIDI_NAMESPACE
###############################################################
# # /*! \brief The main class for MIDI handling.
# 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. #
# #
###############################################################
*/ */
//template<typename Uart>
class MidiInterface
#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
{ {
public:
MidiInterface();
~MidiInterface();
public: public:
void begin(byte inChannel = 1);
// =========================================================================
// Constructor and Destructor
MIDI_Class();
~MIDI_Class();
void begin(const byte inChannel = 1);
// ========================================================================= // -------------------------------------------------------------------------
// MIDI Output // MIDI Output
#if COMPILE_MIDI_OUT // Start compilation block #if MIDI_BUILD_OUTPUT
public:
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 sendTuneRequest();
void sendRealTime(kMIDIType Type);
void send(kMIDIType type, byte param1, byte param2, byte channel);
private:
const byte genstatus(const kMIDIType inType,const byte inChannel) const;
// 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
public: public:
void sendNoteOn(byte inNoteNumber,
byte inVelocity,
Channel inChannel);
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(MidiType inType);
void send(MidiType inType,
DataByte inData1,
DataByte inData2,
Channel inChannel);
private:
inline StatusByte getStatus(MidiType inType,
Channel inChannel) const;
#endif // MIDI_BUILD_OUTPUT
// -------------------------------------------------------------------------
// MIDI Input
#if MIDI_BUILD_INPUT
public:
bool read(); bool read();
bool read(const byte Channel); bool read(Channel inChannel);
// Getters public:
kMIDIType getType() const; inline MidiType getType() const;
byte getChannel() const; inline Channel getChannel() const;
byte getData1() const; inline DataByte getData1() const;
byte getData2() const; inline DataByte getData2() const;
const byte * getSysExArray() const; inline const byte* getSysExArray() const;
unsigned int getSysExArrayLength() const; inline unsigned int getSysExArrayLength() const;
bool check() const; inline bool check() const;
byte getInputChannel() const public:
{ inline Channel getInputChannel() const;
return mInputChannel; inline void setInputChannel(Channel inChannel);
}
// 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:
static inline MidiType getTypeFromStatusByte(const byte inStatus);
private: private:
@ -366,7 +154,7 @@ public:
void setHandleActiveSensing(void (*fptr)(void)); void setHandleActiveSensing(void (*fptr)(void));
void setHandleSystemReset(void (*fptr)(void)); void setHandleSystemReset(void (*fptr)(void));
void disconnectCallbackFromType(kMIDIType Type); void disconnectCallbackFromType(MidiType Type);
private: private:
@ -393,39 +181,46 @@ private:
#endif // USE_CALLBACKS #endif // USE_CALLBACKS
#endif // COMPILE_MIDI_IN #endif // MIDI_BUILD_INPUT
// ========================================================================= // =========================================================================
// MIDI Soft Thru // MIDI Soft Thru
#if (COMPILE_MIDI_IN && COMPILE_MIDI_OUT && COMPILE_MIDI_THRU) #if (MIDI_BUILD_INPUT && MIDI_BUILD_OUTPUT && MIDI_BUILD_THRU)
public: public:
inline MidiFilterMode getFilterMode() const;
inline bool getThruState() const;
// Getters inline void turnThruOn(MidiFilterMode inThruFilterMode = Full);
kThruFilterMode getFilterMode() const { return mThruFilterMode; } inline void turnThruOff();
bool getThruState() const { return mThruActivated; } inline void setThruFilterMode(MidiFilterMode inThruFilterMode);
// Setters
void turnThruOn(kThruFilterMode inThruFilterMode = Full);
void turnThruOff();
void setThruFilterMode(const kThruFilterMode inThruFilterMode);
private: private:
void thru_filter(byte inChannel); void thru_filter(byte inChannel);
bool mThruActivated; bool mThruActivated : 1;
kThruFilterMode mThruFilterMode; MidiFilterMode mThruFilterMode : 7;
#endif // Thru #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"

View File

@ -2,7 +2,7 @@
* @file midi_Defs.h * @file midi_Defs.h
* Project Arduino MIDI Library * Project Arduino MIDI Library
* @brief MIDI Library for the Arduino - Definitions * @brief MIDI Library for the Arduino - Definitions
* @version 3.5 * @version 4.0
* @author Francois Best * @author Francois Best
* @date 24/02/11 * @date 24/02/11
* license GPL Forty Seven Effects - 2011 * license GPL Forty Seven Effects - 2011
@ -15,23 +15,31 @@
BEGIN_MIDI_NAMESPACE BEGIN_MIDI_NAMESPACE
// -----------------------------------------------------------------------------
#define MIDI_CHANNEL_OMNI 0 #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_MIN -8192
#define MIDI_PITCHBEND_MAX 8191 #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 uint8_t byte;
typedef uint16_t word; typedef uint16_t word;
typedef byte StatusByte;
typedef byte DataByte;
typedef byte Channel;
typedef byte FilterMode;
// -----------------------------------------------------------------------------
/*! Enumeration of MIDI types */ /*! Enumeration of MIDI types */
enum kMIDIType enum MidiType
{ {
InvalidType = 0x00, ///< For notifying errors
NoteOff = 0x80, ///< Note Off NoteOff = 0x80, ///< Note Off
NoteOn = 0x90, ///< Note On NoteOn = 0x90, ///< Note On
AfterTouchPoly = 0xA0, ///< Polyphonic AfterTouch AfterTouchPoly = 0xA0, ///< Polyphonic AfterTouch
@ -50,19 +58,22 @@ enum kMIDIType
Stop = 0xFC, ///< System Real Time - Stop Stop = 0xFC, ///< System Real Time - Stop
ActiveSensing = 0xFE, ///< System Real Time - Active Sensing ActiveSensing = 0xFE, ///< System Real Time - Active Sensing
SystemReset = 0xFF, ///< System Real Time - System Reset SystemReset = 0xFF, ///< System Real Time - System Reset
InvalidType = 0x00 ///< For notifying errors
}; };
// -----------------------------------------------------------------------------
/*! Enumeration of Thru filter modes */ /*! Enumeration of Thru filter modes */
enum kThruFilterMode { enum MidiFilterMode
{
Off = 0, ///< Thru disabled (nothing passes through). Off = 0, ///< Thru disabled (nothing passes through).
Full = 1, ///< Fully enabled Thru (every incoming message is sent back). Full = 1, ///< Fully enabled Thru (every incoming message is sent back).
SameChannel = 2, ///< Only the messages on the Input Channel will be 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) ---------------- // High resolution Continuous Controllers MSB (+32 for LSB) ----------------
BankSelect = 0, BankSelect = 0,
@ -92,7 +103,7 @@ enum eMIDICCNumber
Sostenuto = 66, Sostenuto = 66,
SoftPedal = 67, SoftPedal = 67,
Legato = 68, Legato = 68,
Hold2 = 69, Hold = 69,
// Low resolution continuous controllers ----------------------------------- // Low resolution continuous controllers -----------------------------------
SoundController1 = 70, ///< Synth: Sound Variation FX: Exciter On/Off SoundController1 = 70, ///< Synth: Sound Variation FX: Exciter On/Off
@ -129,40 +140,41 @@ enum eMIDICCNumber
}; };
// -----------------------------------------------------------------------------
/*! The midimsg structure contains decoded data /*! The midimsg structure contains decoded data
of a MIDI message read from the serial port of a MIDI message read from the serial port
with read() or thru(). with read() or thru().
*/ */
struct midimsg 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.
*/ */
byte channel; Channel channel;
/*! The type of the message /*! 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. /*! The first data byte.
\n Value goes from 0 to 127. \n Value goes from 0 to 127.
*/ */
byte data1; DataByte data1;
/*! The second data byte. /*! The second data byte.
If the message is only 2 bytes long, this one is null. If the message is only 2 bytes long, this one is null.
\n Value goes from 0 to 127. \n Value goes from 0 to 127.
*/ */
byte data2; DataByte data2;
/*! System Exclusive dedicated byte array. /*! System Exclusive dedicated byte array.
\n Array length is stocked on 16 bits, \n Array length is stocked on 16 bits,
in data1 (LSB) and data2 (MSB) 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. /*! This boolean indicates if the message is valid or not.
There is no channel consideration here, There is no channel consideration here,
@ -172,5 +184,4 @@ struct midimsg
}; };
END_MIDI_NAMESPACE END_MIDI_NAMESPACE

167
src/midi_Inline.hpp Normal file
View File

@ -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

View File

@ -2,7 +2,7 @@
* @file midi_Namespace.h * @file midi_Namespace.h
* Project Arduino MIDI Library * Project Arduino MIDI Library
* @brief MIDI Library for the Arduino - Namespace declaration * @brief MIDI Library for the Arduino - Namespace declaration
* @version 3.5 * @version 4.0
* @author Francois Best * @author Francois Best
* @date 24/02/11 * @date 24/02/11
* license GPL Forty Seven Effects - 2011 * license GPL Forty Seven Effects - 2011

View File

@ -27,23 +27,25 @@ BEGIN_MIDI_NAMESPACE
// (MIDI in, out, thru), or to 0 to disable the feature and save space. // (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. // Note that the Thru can only work if in and out are enabled.
#define MIDI_BUILD_INPUT 1 #define MIDI_BUILD_INPUT 1
#define MIDI_BUILD_OUTPUT 1 #define MIDI_BUILD_OUTPUT 1
#define MIDI_BUILD_THRU 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 // Serial port configuration
// Change the number (to Serial1 for example) // Set the default port to use for MIDI.
// if you want to use a different serial port for MIDI I/O. #define MIDI_SERIAL_PORT Serial
#define MIDI_SERIAL_PORT Serial
// Software serial options // Software serial options
#define MIDI_USE_SOFTWARE_SERIAL 0 #define MIDI_USE_SOFTWARE_SERIAL 0
#if MIDI_USE_SOFTWARE_SERIAL #if MIDI_USE_SOFTWARE_SERIAL
#define MIDI_SOFTSERIAL_RX_PIN 1 // Pin number to use for MIDI Input #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_TX_PIN 2 // Pin number to use for MIDI Output
#endif #endif
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -52,11 +54,10 @@ BEGIN_MIDI_NAMESPACE
// Running status enables short messages when sending multiple values // Running status enables short messages when sending multiple values
// of the same type and channel. // of the same type and channel.
// Set to 0 if you have troubles controlling your hardware. // Set to 0 if you have troubles controlling your hardware.
#define MIDI_USE_RUNNING_STATUS 1 #define MIDI_USE_RUNNING_STATUS 1
#define MIDI_USE_1BYTE_PARSING 1 #define MIDI_USE_1BYTE_PARSING 1
#define MIDI_BAUDRATE 31250
#define MIDI_BAUDRATE 31250 #define MIDI_SYSEX_ARRAY_SIZE 255 // Maximum size is 65535 bytes.
#define MIDI_SYSEX_ARRAY_SIZE 255 // Maximum size is 65535 bytes.
END_MIDI_NAMESPACE END_MIDI_NAMESPACE