MIDI with Lumps
Thomas Hudson
thudson at cygnus.com
Sat Mar 27 19:25:15 CET 1999
The Dark force of dance wrote:
>
> So that only leaves my crappy software. I'll have to re-write it. You see I
> was trying to be smart. What I figured was that instead of dealing with
> each byte as they came in, I could stuff them all in a buffer, wait till
> there was 3 or more bytes in the buffer and then go hunting for a #B0H.
> Finding a B0 would then mean that there would be 2 more bytes containing
> data and they could all be processed at the same time.
Except that a system realtime message can interrupt any other message without
reseting running status. Also, if the previous message was #B0H, the status
byte won't be resent.
I have some C++ code I've been working on for parsing a midi stream. The
"Spray'something'" calls simply deliver each type of message on to whatever
wants to process them. This is only the parser method. If you need the
entire class let me know. You may be able to adapt this:
void MidiParser::parseMidi()
{
uchar next = readByte();
if (isStatus(next))
{
// If we receive a system realtime, we process immediately and
// then continue with out normally scheduled programming
if (isSystemRealTime(next))
SpraySystemRealTime(next,NOW);
// Set the sysex flag to start saving data bytes.
else if (isSystemExclusive(next))
_in_sysex = true;
// Any other channelized status byte
else
{
// Receiving any status byte other than SysRealTime terminates
// a System Exclusive message
if (_in_sysex)
SpraySystemExclusive(_sysex_buf,_data_count);
_running_status = next & 0xf0; // Strip off channel
_channel = next & 0x0f; // Save channel here
_data_count = 0; // Reset data count
}
}
else // data byte
{
if (_in_sysex)
{
if (_sysex_size == _data_count)
{
_sysex_size *= 2;
_sysex_buf = (uchar*)realloc(_sysex_buf,_sysex_size);
}
_sysex_buf[_data_count++] = next;
}
else
{
// Add data byte to buffer and check counts for each message type
_data_buf[_data_count++] = next;
switch (_running_status)
{
case NOTE_ON:
if (_data_count == 2)
{
SprayNoteOn(_channel,_data_buf[0],_data_buf[1]);
_data_count = 0;
}
break;
case NOTE_OFF:
if (_data_count == 2)
{
SprayNoteOff(_channel,_data_buf[0],_data_buf[1]);
_data_count = 0;
}
break;
case KEY_PRESSURE:
if (_data_count == 2)
{
SprayKeyPressure(_channel,_data_buf[0],_data_buf[1]);
_data_count = 0;
}
break;
case CONTROL_CHANGE:
if (_data_count == 2)
{
SprayControlChange(_channel,_data_buf[0],_data_buf[1]);
_data_count = 0;
}
break;
case PROGRAM_CHANGE:
if (_data_count == 1)
{
SprayProgramChange(_channel,_data_buf[0]);
_data_count = 0;
}
break;
case CHANNEL_PRESSURE:
if (_data_count == 1)
{
SprayChannelPressure(_channel,_data_buf[0]);
_data_count = 0;
}
break;
case PITCH_BEND:
if (_data_count == 2)
{
SprayPitchBend(_channel,_data_buf[0],_data_buf[1]);
_data_count = 0;
}
break;
case SYSTEM_COMMON:
if (_data_count == 2)
{
SpraySystemCommon(_running_status & _channel, _data_buf[0],_data_buf[2]);
_data_count = 0;
_running_status = 0;
}
break;
default: // shouldn't get here
cout << "Status = " << _running_status; << endl;
for (int i = 0; i < _data_count; ++i)
cout << " data[" << i << "] = " << _data_buf[i] << endl;
break;
}
}
}
}
Hope this helps.
Thomas
More information about the Synth-diy
mailing list