[sdiy] Tips for writing a MIDI parser wanted

paul.maddox.mail-list at synth.net paul.maddox.mail-list at synth.net
Tue Mar 24 12:37:19 CET 2009


Tom,

I've read through Seb Francis' 4XD code (which is very useful since it
is in 16F PIC assembly, which is what I'm using) and looked at the
MIDIbox code too.

the code for the monowave, polydac and midi2sds are all up on my page
(www.vacoloco.net/synths) if you want to have a look, though they're in C.


[Hide Quoted Text]
Dealing just with MIDI reception for a moment, I think the general plan
is something like this:

* Every time a byte arrives, an interrupt is generated. The interrupt
routine checks whether this is a byte on our channel, and whether it is
a byte that we're expecting (the second byte of a 2-byte message for
example) or a new message. If it has a complete message, it puts either
1,2, or 3 bytes into a MIDI processing buffer.

close,
FIRST thing to do is check if it's a status byte (MSB set).

Secondly, if it's 0xF0 or above (midi start stop, clock, etc) you'll  
probably want to
ignore it. if it's one of these messages you need to handle them  
differently to status
bytes below 0xF0 as these tend to be single byte status bytes (midi  
clock, midi start are
perfect examples). For a synth, personally, I just *bin* everything  
that's 0xF0 and above.

Thirdly, be aware of running status which is a bugger if you don't  
know about it.

Quick explanation (sorry if I'm teaching you to suck eggs),

Any MIDI status byte (MSB set) can potentially be replaced by an  
assumed running status
byte, so if you had the following stream (some random three note chord)-

0x90, 0x3c, 0x7f, 0x90, 0x3e, 0x7f, 0x90, 0x37, 0x7f

more often than not, it'll be delivered to your midi input like this ;-

0x90, 0x3c, 0x7f, 0x3e, 0x7f, 0x37, 0x7f

notice the lack of note on status bytes?
This, is the nightmare that is running status.

it doesn't matter WHAT the timing is between the notes, if no other  
Status byte is sent,
*some* synths continue with this.

So when a byte comes in, you'd do somethingl ike this,

Test the MSB
if it's set, check the midi channel (and if it's below 0xF0), if it's  
a match, REMEBER
this status byte
everything you get there after will be data associated with this status byte

if the MSB is not set, then it's data, could be the "second" or  
"thruid" byte so you need
to remember which you've had, and what you're expecting next.
For the example above you'll be processing bytes like this
- 1,2,3,2,3,2,3

Also, again be aware that things like midi clock timing status message  
bytes can happen
in the middle of your note stream!

using the above example, you could get this horrible thing happening ;-

0x90, 0x3c, 0x7f, 0x3e, 0xF8, 0x7f, 0x37, 0x7f

and because it's midi clock, and it just "happens" there's no new  
status byte, hence you
have to treat messages 0xF0 and above, VERY differently to the rest of  
your midi stream.

When debugging, bare in mind apps like MIDI-OX, tend to tidy up the  
MIDI Stream, so you
don't see the lack status bytes.

The point of this two-stage scheme is that the serious work is only
done on relevant, correct messages. The interrupt will discard anything
on other channels, or anything badly formed. This should both limit the
amount of data that goes into the buffer, and also remove the need for
complex error checking from the interpreting code.

yep, FWIW, I usually use a buffer for midi notes, as a byte comes in I  
just throw the
entire stream into a buffer (an indexed array really).

I then have a routine in my main loop that checks to see if there  
array index point is
something other than zero (i.e. there's data there), if so it jumps to a
midi_process(getchar()) function, which checks MSB, channel, values  
over 0xF0, etc and
then sets a "byte counter" So that I know the next byte recieved is  
byte 2 of a 3 byte
stream.
Then byte 3, and UNLESS I have a new midi status, then byte 2.

What do you think? Am I on the right track? Anything I need to know?
Anything I'm forgetting?

the thing that catches you out will be running status and those  
"system realtime
messages" (anythong 0xF0 to 0xFF).
The other odd one is the two types of note off ;-

0x80, 0x3C, 0x7F
0x90, 0x3C, 0x00

Both are valid note off's for the same note, *most* things seem to use  
note (0x90) with
zero velocity, but some still use note off (0x80) status bytes.

I spent last night doing the internet research on this topic, but
couldn't find anything that gives an overview of the best strategy for
writing a MIDI parser. There are some examples, but no-one talks about
*why* they did it the way they did it, and that's the really
interesting bit.

I did a paper for AVRFreaks which had a quite in depth explanation of  
how to handle MIDI,
(http://www.avrfreaks.net/index.php?module=FreaksArticles&func=downloadArticle&id=19)  
but
the code that went with it (in assembler) seems to have been lost.

Hope that helps
Paul





More information about the Synth-diy mailing list