Re: Stuck MIDI notes
Re: Stuck MIDI notes
- Subject: Re: Stuck MIDI notes
- From: Pete Yandell <email@hidden>
- Date: Fri, 1 Nov 2002 13:14:20 +1100
FYI, here's the code I use for MIDI filtering in MIDI Patchbay.
Despite the apparent simplicity of the MIDI protocol, it does get
tricky particularly when dealing with realtime bytes. Because I want
the option of deleting any given MIDI message as part of my filtering I
need to take out any realtime bytes that might be hiding in the midst
of that message.
BOOL isDataByte (Byte b) { return b < 0x80; }
BOOL isStatusByte (Byte b) { return b >= 0x80 && b < 0xF8; }
BOOL isRealtimeByte (Byte b) { return b >= 0xF8; }
unsigned int
findEndOfMessage (const MIDIPacket* packet, unsigned int startIndex)
{
unsigned int i;
// Look for the status byte of the next message, or the end of the
packet
for (i = startIndex + 1; i < packet->length && !isStatusByte
(packet->data[i]); i++);
// Skip backwords over any realtime data at the end of the packet
while (isRealtimeByte (packet->data[--i]));
return i;
}
- (void)processMIDIPacketList:(const MIDIPacketList*)inPacketList
sender:(id)sender
{
NSMutableData* data;
MIDIPacketList* outPacketList;
const MIDIPacket* inPacket;
MIDIPacket* outPacket;
int i, j;
int messageStart, messageEnd;
int outMessageStart;
int outMessageLength;
data = [NSMutableData dataWithLength:midiPacketListSize
(inPacketList)];
outPacketList = (MIDIPacketList*)[data mutableBytes];
outPacketList->numPackets = 0;
inPacket = &inPacketList->packet[0];
outPacket = &outPacketList->packet[0];
for (i = 0; i < inPacketList->numPackets; i++) {
outPacket->timeStamp = inPacket->timeStamp;
outPacket->length = 0;
// This is to skip over any SysEx continuation at the start of
the packet and simply
// copy it to the output packet without changing it.
for (j = 0; j < inPacket->length && !isStatusByte
(inPacket->data[j]); j++) {
if (shouldTransmitClock || !isRealtimeByte
(inPacket->data[j]))
outPacket->data[outPacket->length++] =
inPacket->data[j];
}
// Now we loop over the remaining MIDI messages in the packet
messageStart = j;
while (messageStart < inPacket->length) {
messageEnd = findEndOfMessage (inPacket, messageStart);
// Copy any realtime bytes in this message to the new packet
if (shouldTransmitClock) {
for (j = messageStart; j <= messageEnd; j++) {
if (isRealtimeByte (inPacket->data[j]))
outPacket->data[outPacket->length++] =
inPacket->data[j];
}
}
// Be sure to save our place in the output packet
outMessageStart = outPacket->length;
// Now copy everything else across
for (j = messageStart; j <= messageEnd; j++) {
if (!isRealtimeByte (inPacket->data[j]))
outPacket->data[outPacket->length++] =
inPacket->data[j];
}
// Process the packet with all our fabulous filters!
outMessageLength = outPacket->length - outMessageStart;
outMessageLength = [self
processMIDIMessage:&outPacket->data[outMessageStart]
ofLength:outMessageLength];
outPacket->length = outMessageStart + outMessageLength;
// Skip over any trailing realtime bytes
for (j = messageEnd + 1; j < inPacket->length &&
!isStatusByte (inPacket->data[j]); j++) {
if (shouldTransmitClock)
outPacket->data[outPacket->length++] =
inPacket->data[j];
}
// Set the start of the next message to be where we
finished up
messageStart = j;
}
// If we generated an output packet then add it to the list
if (outPacket->length > 0) {
outPacketList->numPackets++;
outPacket = MIDIPacketNext (outPacket);
}
inPacket = MIDIPacketNext (inPacket);
}
// Pass the new packet list out for processing
if (outPacketList->numPackets > 0) {
[output processMIDIPacketList:outPacketList sender:self];
}
}
_______________________________________________
coreaudio-api mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/coreaudio-api
Do not post admin requests to the list. They will be ignored.