Added detection of channel messages to fix running status.

This commit is contained in:
Francois Best 2012-10-09 08:28:24 +02:00
parent 5a55f715da
commit 6f0535be90
2 changed files with 51 additions and 46 deletions

View File

@ -109,7 +109,8 @@ public:
inline void setInputChannel(Channel inChannel); inline void setInputChannel(Channel inChannel);
public: public:
static inline MidiType getTypeFromStatusByte(const byte inStatus); static inline MidiType getTypeFromStatusByte(byte inStatus);
static inline bool isChannelMessage(MidiType inType);
private: private:
bool inputFilter(Channel inChannel); bool inputFilter(Channel inChannel);

View File

@ -514,50 +514,39 @@ bool MidiInterface<SerialPort>::parse(Channel inChannel)
mPendingMessage[0] = extracted; mPendingMessage[0] = extracted;
// Check for running status first // Check for running status first
switch (getTypeFromStatusByte(mRunningStatus_RX)) if (isChannelMessage(getTypeFromStatusByte(mRunningStatus_RX)))
{ {
// Only these types allow Running Status: // Only these types allow Running Status
case NoteOff:
case NoteOn:
case AfterTouchPoly:
case ControlChange:
case ProgramChange:
case AfterTouchChannel:
case PitchBend:
// If the status byte is not received, prepend it // If the status byte is not received, prepend it
// to the pending message // to the pending message
if (extracted < 0x80) if (extracted < 0x80)
{ {
mPendingMessage[0] = mRunningStatus_RX; mPendingMessage[0] = mRunningStatus_RX;
mPendingMessage[1] = extracted; mPendingMessage[1] = extracted;
mPendingMessageIndex = 1; mPendingMessageIndex = 1;
} }
// Else: well, we received another status byte, // Else: well, we received another status byte,
// so the running status does not apply here. // so the running status does not apply here.
// It will be updated upon completion of this message. // It will be updated upon completion of this message.
if (mPendingMessageIndex >= (mPendingMessageExpectedLenght-1)) if (mPendingMessageIndex >= (mPendingMessageExpectedLenght-1))
{ {
mMessage.type = getTypeFromStatusByte(mPendingMessage[0]); mMessage.type = getTypeFromStatusByte(mPendingMessage[0]);
mMessage.channel = (mPendingMessage[0] & 0x0F)+1; mMessage.channel = (mPendingMessage[0] & 0x0F)+1;
mMessage.data1 = mPendingMessage[1]; mMessage.data1 = mPendingMessage[1];
// Save data2 only if applicable // Save data2 only if applicable
if (mPendingMessageExpectedLenght == 3) if (mPendingMessageExpectedLenght == 3)
mMessage.data2 = mPendingMessage[2]; mMessage.data2 = mPendingMessage[2];
else else
mMessage.data2 = 0; mMessage.data2 = 0;
mPendingMessageIndex = 0; mPendingMessageIndex = 0;
mPendingMessageExpectedLenght = 0; mPendingMessageExpectedLenght = 0;
mMessage.valid = true; mMessage.valid = true;
return true; return true;
} }
break;
default:
// No running status
break;
} }
switch (getTypeFromStatusByte(mPendingMessage[0])) switch (getTypeFromStatusByte(mPendingMessage[0]))
@ -717,8 +706,11 @@ bool MidiInterface<SerialPort>::parse(Channel inChannel)
} }
mMessage.type = getTypeFromStatusByte(mPendingMessage[0]); mMessage.type = getTypeFromStatusByte(mPendingMessage[0]);
// Don't check if it is a Channel Message
mMessage.channel = (mPendingMessage[0] & 0x0F)+1; if (isChannelMessage(mMessage.type))
mMessage.channel = (mPendingMessage[0] & 0x0F)+1;
else
mMessage.channel = 0;
mMessage.data1 = mPendingMessage[1]; mMessage.data1 = mPendingMessage[1];
@ -908,7 +900,7 @@ void MidiInterface<SerialPort>::setInputChannel(Channel inChannel)
made public so you can handle MidiTypes more easily. made public so you can handle MidiTypes more easily.
*/ */
template<class SerialPort> template<class SerialPort>
MidiType MidiInterface<SerialPort>::getTypeFromStatusByte(const byte inStatus) MidiType MidiInterface<SerialPort>::getTypeFromStatusByte(byte inStatus)
{ {
if ((inStatus < 0x80) || if ((inStatus < 0x80) ||
(inStatus == 0xF4) || (inStatus == 0xF4) ||
@ -919,6 +911,18 @@ MidiType MidiInterface<SerialPort>::getTypeFromStatusByte(const byte inStatus)
else return (MidiType)inStatus; else return (MidiType)inStatus;
} }
template<class SerialPort>
bool MidiInterface<SerialPort>::isChannelMessage(MidiType inType)
{
return (inType == NoteOff ||
inType == NoteOn ||
inType == ControlChange ||
inType == AfterTouchPoly ||
inType == AfterTouchChannel ||
inType == PitchBend ||
inType == ProgramChange);
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#if MIDI_USE_CALLBACKS #if MIDI_USE_CALLBACKS