Allow MIDIDecoder to handle multiple messages per pass

This commit is contained in:
Jack Andersen 2018-08-24 22:37:26 -10:00
parent f73e4f08fa
commit fd2a92e2c2
1 changed files with 135 additions and 135 deletions

View File

@ -41,124 +41,31 @@ MIDIDecoder::receiveBytes(std::vector<uint8_t>::const_iterator begin,
std::vector<uint8_t>::const_iterator end) std::vector<uint8_t>::const_iterator end)
{ {
std::vector<uint8_t>::const_iterator it = begin; std::vector<uint8_t>::const_iterator it = begin;
if (it == end) while (it != end)
return begin;
uint8_t a = *it++;
uint8_t b;
if (a & 0x80)
m_status = a;
else
it--;
if (m_status == 0xff)
{ {
/* Meta events (ignored for now) */ uint8_t a = *it++;
if (it == end) uint8_t b;
return begin; if (a & 0x80)
a = *it++; m_status = a;
else
it--;
uint32_t length; if (m_status == 0xff)
_readContinuedValue(it, end, length);
it += length;
}
else
{
uint8_t chan = m_status & 0xf;
switch (Status(m_status & 0xf0))
{
case Status::NoteOff:
{ {
/* Meta events (ignored for now) */
if (it == end) if (it == end)
return begin; return begin;
a = *it++; a = *it++;
if (it == end)
return begin; uint32_t length;
b = *it++; _readContinuedValue(it, end, length);
m_out.noteOff(chan, clamp7(a), clamp7(b)); it += length;
break; } else
}
case Status::NoteOn:
{ {
if (it == end) uint8_t chan = m_status & 0xf;
return begin; switch (Status(m_status & 0xf0))
a = *it++;
if (it == end)
return begin;
b = *it++;
m_out.noteOn(chan, clamp7(a), clamp7(b));
break;
}
case Status::NotePressure:
{
if (it == end)
return begin;
a = *it++;
if (it == end)
return begin;
b = *it++;
m_out.notePressure(chan, clamp7(a), clamp7(b));
break;
}
case Status::ControlChange:
{
if (it == end)
return begin;
a = *it++;
if (it == end)
return begin;
b = *it++;
m_out.controlChange(chan, clamp7(a), clamp7(b));
break;
}
case Status::ProgramChange:
{
if (it == end)
return begin;
a = *it++;
m_out.programChange(chan, clamp7(a));
break;
}
case Status::ChannelPressure:
{
if (it == end)
return begin;
a = *it++;
m_out.channelPressure(chan, clamp7(a));
break;
}
case Status::PitchBend:
{
if (it == end)
return begin;
a = *it++;
if (it == end)
return begin;
b = *it++;
m_out.pitchBend(chan, clamp7(b) * 128 + clamp7(a));
break;
}
case Status::SysEx:
{
switch (Status(m_status & 0xff))
{ {
case Status::SysEx: case Status::NoteOff:
{
uint32_t len;
if (!_readContinuedValue(it, end, len) || end - it < len)
return begin;
m_out.sysex(&*it, len);
break;
}
case Status::TimecodeQuarterFrame:
{
if (it == end)
return begin;
a = *it++;
m_out.timeCodeQuarterFrame(a >> 4 & 0x7, a & 0xf);
break;
}
case Status::SongPositionPointer:
{ {
if (it == end) if (it == end)
return begin; return begin;
@ -166,43 +73,136 @@ MIDIDecoder::receiveBytes(std::vector<uint8_t>::const_iterator begin,
if (it == end) if (it == end)
return begin; return begin;
b = *it++; b = *it++;
m_out.songPositionPointer(clamp7(b) * 128 + clamp7(a)); m_out.noteOff(chan, clamp7(a), clamp7(b));
break; break;
} }
case Status::SongSelect: case Status::NoteOn:
{ {
if (it == end) if (it == end)
return begin; return begin;
a = *it++; a = *it++;
m_out.songSelect(clamp7(a)); if (it == end)
return begin;
b = *it++;
m_out.noteOn(chan, clamp7(a), clamp7(b));
break; break;
} }
case Status::TuneRequest: case Status::NotePressure:
m_out.tuneRequest(); {
if (it == end)
return begin;
a = *it++;
if (it == end)
return begin;
b = *it++;
m_out.notePressure(chan, clamp7(a), clamp7(b));
break;
}
case Status::ControlChange:
{
if (it == end)
return begin;
a = *it++;
if (it == end)
return begin;
b = *it++;
m_out.controlChange(chan, clamp7(a), clamp7(b));
break;
}
case Status::ProgramChange:
{
if (it == end)
return begin;
a = *it++;
m_out.programChange(chan, clamp7(a));
break;
}
case Status::ChannelPressure:
{
if (it == end)
return begin;
a = *it++;
m_out.channelPressure(chan, clamp7(a));
break;
}
case Status::PitchBend:
{
if (it == end)
return begin;
a = *it++;
if (it == end)
return begin;
b = *it++;
m_out.pitchBend(chan, clamp7(b) * 128 + clamp7(a));
break;
}
case Status::SysEx:
{
switch (Status(m_status & 0xff))
{
case Status::SysEx:
{
uint32_t len;
if (!_readContinuedValue(it, end, len) || end - it < len)
return begin;
m_out.sysex(&*it, len);
break;
}
case Status::TimecodeQuarterFrame:
{
if (it == end)
return begin;
a = *it++;
m_out.timeCodeQuarterFrame(a >> 4 & 0x7, a & 0xf);
break;
}
case Status::SongPositionPointer:
{
if (it == end)
return begin;
a = *it++;
if (it == end)
return begin;
b = *it++;
m_out.songPositionPointer(clamp7(b) * 128 + clamp7(a));
break;
}
case Status::SongSelect:
{
if (it == end)
return begin;
a = *it++;
m_out.songSelect(clamp7(a));
break;
}
case Status::TuneRequest:
m_out.tuneRequest();
break;
case Status::Start:
m_out.startSeq();
break;
case Status::Continue:
m_out.continueSeq();
break;
case Status::Stop:
m_out.stopSeq();
break;
case Status::Reset:
m_out.reset();
break;
case Status::SysExTerm:
case Status::TimingClock:
case Status::ActiveSensing:
default:
break;
}
break;
}
default:
break; break;
case Status::Start:
m_out.startSeq();
break;
case Status::Continue:
m_out.continueSeq();
break;
case Status::Stop:
m_out.stopSeq();
break;
case Status::Reset:
m_out.reset();
break;
case Status::SysExTerm:
case Status::TimingClock:
case Status::ActiveSensing:
default: break;
} }
break;
}
default: break;
} }
} }
return it; return it;
} }