Working on thru.
This commit is contained in:
parent
8c9d289216
commit
d78cace1b2
|
|
@ -117,7 +117,8 @@ public:
|
|||
inline void setInputChannel(Channel inChannel);
|
||||
|
||||
public:
|
||||
static inline MidiType getTypeFromStatusByte(byte inStatus);
|
||||
static inline MidiType getTypeFromStatusByte(StatusByte inStatus);
|
||||
static inline byte getMessageLength(StatusByte inStatus);
|
||||
static inline bool isChannelMessage(MidiType inType);
|
||||
static inline bool isRealtimeMessage(MidiType inType);
|
||||
|
||||
|
|
@ -210,7 +211,6 @@ private:
|
|||
|
||||
private:
|
||||
ThruFlags mThruFlags;
|
||||
bool mForwardCurrentMessage;
|
||||
|
||||
#endif // MIDI_BUILD_THRU
|
||||
|
||||
|
|
|
|||
145
src/MIDI.hpp
145
src/MIDI.hpp
|
|
@ -485,7 +485,7 @@ bool MidiInterface<SerialPort>::parse()
|
|||
// - Look for other bytes in buffer, call parser recursively,
|
||||
// until the message is assembled or the buffer is empty.
|
||||
// Else, add the extracted byte to the pending message, and check validity.
|
||||
// When the message is done, store it.
|
||||
// When the message is recomposed, notify the caller.
|
||||
|
||||
const byte extracted = mSerial.read();
|
||||
|
||||
|
|
@ -530,17 +530,16 @@ bool MidiInterface<SerialPort>::parse()
|
|||
}
|
||||
}
|
||||
|
||||
switch (getTypeFromStatusByte(mPendingMessage[0]))
|
||||
mPendingMessageExpectedLenght = getMessageLength(mPendingMessage[0]);
|
||||
|
||||
if (mPendingMessageExpectedLenght == 1)
|
||||
{
|
||||
// 1 byte messages
|
||||
case Start:
|
||||
case Continue:
|
||||
case Stop:
|
||||
case Clock:
|
||||
case ActiveSensing:
|
||||
case SystemReset:
|
||||
case TuneRequest:
|
||||
// Handle the message type directly here.
|
||||
// RealTime and 1 byte messages -> send & handle rightaway
|
||||
if (shouldMessageBeForwarded(mPendingMessage[0]))
|
||||
{
|
||||
mSerial.write(mPendingMessage[0]);
|
||||
}
|
||||
|
||||
mMessage.type = getTypeFromStatusByte(mPendingMessage[0]);
|
||||
mMessage.channel = 0;
|
||||
mMessage.data1 = 0;
|
||||
|
|
@ -556,45 +555,32 @@ bool MidiInterface<SerialPort>::parse()
|
|||
mPendingMessageExpectedLenght = 0;
|
||||
|
||||
return true;
|
||||
break;
|
||||
|
||||
// 2 bytes messages
|
||||
case ProgramChange:
|
||||
case AfterTouchChannel:
|
||||
case TimeCodeQuarterFrame:
|
||||
case SongSelect:
|
||||
mPendingMessageExpectedLenght = 2;
|
||||
break;
|
||||
|
||||
// 3 bytes messages
|
||||
case NoteOn:
|
||||
case NoteOff:
|
||||
case ControlChange:
|
||||
case PitchBend:
|
||||
case AfterTouchPoly:
|
||||
case SongPosition:
|
||||
mPendingMessageExpectedLenght = 3;
|
||||
break;
|
||||
|
||||
case SystemExclusive:
|
||||
// The message can be any lenght
|
||||
}
|
||||
else if (mPendingMessageExpectedLenght == 0xff)
|
||||
{
|
||||
// SysEx: The message can be any length
|
||||
// between 3 and MIDI_SYSEX_ARRAY_SIZE bytes
|
||||
mPendingMessageExpectedLenght = MIDI_SYSEX_ARRAY_SIZE;
|
||||
mRunningStatus_RX = InvalidType;
|
||||
mMessage.sysexArray[0] = SystemExclusive;
|
||||
break;
|
||||
|
||||
case InvalidType:
|
||||
default:
|
||||
// This is obviously wrong. Let's get the hell out'a here.
|
||||
|
||||
}
|
||||
else if (mPendingMessageExpectedLenght == 0)
|
||||
{
|
||||
// Parse error
|
||||
resetInput();
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
// Then update the index of the pending message.
|
||||
mPendingMessageIndex++;
|
||||
|
||||
if (shouldMessageBeForwarded(mPendingMessage[0]))
|
||||
{
|
||||
mSerial.write(mPendingMessage[0]);
|
||||
}
|
||||
|
||||
#if USE_1BYTE_PARSING
|
||||
// Message is not complete.
|
||||
return false;
|
||||
|
|
@ -603,7 +589,6 @@ bool MidiInterface<SerialPort>::parse()
|
|||
// to parse the rest of the message.
|
||||
return parse();
|
||||
#endif
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -612,14 +597,12 @@ bool MidiInterface<SerialPort>::parse()
|
|||
{
|
||||
// Reception of status bytes in the middle of an uncompleted message
|
||||
// are allowed only for interleaved Real Time message or EOX
|
||||
switch (extracted)
|
||||
if (isRealtimeMessage(extracted))
|
||||
{
|
||||
case Clock:
|
||||
case Start:
|
||||
case Continue:
|
||||
case Stop:
|
||||
case ActiveSensing:
|
||||
case SystemReset:
|
||||
if (shouldMessageBeForwarded(extracted)
|
||||
{
|
||||
mSerial.write(extracted);
|
||||
}
|
||||
|
||||
// Here we will have to extract the one-byte message,
|
||||
// pass it to the structure for being read outside
|
||||
|
|
@ -634,13 +617,16 @@ bool MidiInterface<SerialPort>::parse()
|
|||
mMessage.channel = 0;
|
||||
mMessage.valid = true;
|
||||
return true;
|
||||
|
||||
break;
|
||||
|
||||
// End of Exclusive
|
||||
case 0xF7:
|
||||
}
|
||||
else if (extracted == 0xF7)
|
||||
{
|
||||
if (mMessage.sysexArray[0] == SystemExclusive)
|
||||
{
|
||||
if (shouldMessageBeForwarded(SystemExclusive)
|
||||
{
|
||||
mSerial.write(extracted);
|
||||
}
|
||||
|
||||
// Store the last byte (EOX)
|
||||
mMessage.sysexArray[mPendingMessageIndex++] = 0xF7;
|
||||
|
||||
|
|
@ -655,24 +641,27 @@ bool MidiInterface<SerialPort>::parse()
|
|||
resetInput();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Well well well.. error.
|
||||
resetInput();
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
// Parse error: unexpected status byte
|
||||
}
|
||||
}
|
||||
|
||||
// Add extracted data byte to pending message
|
||||
if (mPendingMessage[0] == SystemExclusive)
|
||||
{
|
||||
mMessage.sysexArray[mPendingMessageIndex] = extracted;
|
||||
}
|
||||
else
|
||||
{
|
||||
mPendingMessage[mPendingMessageIndex] = extracted;
|
||||
}
|
||||
|
||||
if (shouldMessageBeForwarded(mPendingMessage[0])
|
||||
{
|
||||
mSerial.write(extracted);
|
||||
}
|
||||
|
||||
// Now we are going to check if we have reached the end of the message
|
||||
if (mPendingMessageIndex >= (mPendingMessageExpectedLenght - 1))
|
||||
|
|
@ -823,7 +812,7 @@ const byte* MidiInterface<SerialPort>::getSysExArray() const
|
|||
return mMessage.sysexArray;
|
||||
}
|
||||
|
||||
/*! \brief Get the lenght of the System Exclusive array.
|
||||
/*! \brief Get the length of the System Exclusive array.
|
||||
|
||||
It is coded using data1 as LSB and data2 as MSB.
|
||||
\return The array's length, in bytes.
|
||||
|
|
@ -868,7 +857,7 @@ void MidiInterface<SerialPort>::setInputChannel(Channel inChannel)
|
|||
made public so you can handle MidiTypes more easily.
|
||||
*/
|
||||
template<class SerialPort>
|
||||
MidiType MidiInterface<SerialPort>::getTypeFromStatusByte(byte inStatus)
|
||||
MidiType MidiInterface<SerialPort>::getTypeFromStatusByte(StatusByte inStatus)
|
||||
{
|
||||
if ((inStatus < 0x80) ||
|
||||
(inStatus == 0xF4) ||
|
||||
|
|
@ -879,6 +868,38 @@ MidiType MidiInterface<SerialPort>::getTypeFromStatusByte(byte inStatus)
|
|||
else return (MidiType)inStatus;
|
||||
}
|
||||
|
||||
template<class SerialPort>
|
||||
byte MidiInterface<SerialPort>::getMessageLength(StatusByte inStatus)
|
||||
{
|
||||
const MidiType type = getTypeFromStatusByte(inStatus);
|
||||
if (isRealtimeMessage(type) || type == TuneRequest)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else if (type == NoteOn ||
|
||||
type == NoteOff ||
|
||||
type == ControlChange ||
|
||||
type == PitchBend ||
|
||||
type == AfterTouchPoly ||
|
||||
type == SongPosition)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
else if (type == ProgramChange ||
|
||||
type == AfterTouchChannel ||
|
||||
type == TimeCodeQuarterFrame ||
|
||||
type == SongSelect)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
else if (type == SystemExclusive)
|
||||
{
|
||||
return 0xff; // SysEx messages can have variable length
|
||||
}
|
||||
|
||||
return 0; // Unknown message type
|
||||
}
|
||||
|
||||
template<class SerialPort>
|
||||
bool MidiInterface<SerialPort>::isChannelMessage(MidiType inType)
|
||||
{
|
||||
|
|
@ -1088,7 +1109,7 @@ bool MidiInterface<SerialPort>::shouldMessageBeForwarded(StatusByte inStatus) co
|
|||
else
|
||||
{
|
||||
// Unknown message or junk
|
||||
return false;
|
||||
return hasThruFlag(ThruFilterFlags::junk);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -61,27 +61,26 @@ enum MidiType
|
|||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/*! Enumeration of Thru filter modes */
|
||||
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.
|
||||
};
|
||||
|
||||
/*! Enumeration of Thru filter modes
|
||||
@see setThruFilterMode
|
||||
*/
|
||||
struct ThruFilterFlags
|
||||
{
|
||||
enum
|
||||
{
|
||||
off = 0
|
||||
off = 0 ///< Thru disabled (nothing passes through).
|
||||
|
||||
, channelSame = 1
|
||||
, channelDifferent = 2
|
||||
, channelSame = (1 << 0) ///< Only the messages on the Input Channel will be sent back.
|
||||
, channelDifferent = (1 << 1) ///< All the messages but the ones on the Input Channel will be sent back.
|
||||
, channel = channelSame | channelDifferent
|
||||
, system = 4
|
||||
, realtime = 8
|
||||
, all = channel | system | realtime
|
||||
, systemExclusive = (1 << 2)
|
||||
, systemCommon = (1 << 3)
|
||||
, systemRealtime = (1 << 4)
|
||||
, system = systemExclusive | systemCommon | systemRealtime
|
||||
, junk = (1 << 7) ///< Send mis-formated data back (unadvisable)
|
||||
|
||||
/// Fully enabled Thru (every incoming message is sent back).
|
||||
, all = channel | system
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue