[sdiy] MIDI bytestream parser

Neil Johnson neil.johnson97 at ntlworld.com
Wed Nov 17 00:16:38 CET 2010


Hi Tom,

> The MIDI bytestream never shows you the channel values as displayed  
> to the user. Channel "One" is always '0x0'. In fact, aside from the  
> actual user display, there isn't anywhere that MIDI channel 16  
> actually exists, is there?

You're confusing a particular encoding of channel numbers, with the  
actual channel numbers.  MIDI has channels 1-16, while the encoding  
uses 0-15.  If anything, it would be more correct to say that MIDI  
channel 0 does not exist!

>> The HASH( ) is used to implement a lookup map from status byte to
>> handler function, by observing that there are no two status byte with
>> the same nibble checksum (they are either nx, with n between 8 and E
>> and x for channel messages, or Fn, with n below 8 for system  
>> messages.
>
> I'm not sure I get this. Ok, status bytes are unique, I get that.  
> And there are only certain values possible, I get that. And we have  
> a function to call for each type of message. So far so good.

Great!

> But what's the point of the hash? A lookup map, you say? So it maps  
> from status byte x to function y?

No, you don't seem to understand what a hash is.  A hash generates a  
value from a small set of values given a value from a large set.   
There are bound to be clashes (multiple input values hash to the same  
output value), but in this specific case the sparse input values do  
not cause clashes in the output values, so it all works out  
nicely :)  The end result is the values 0x80, 0x90, 0xA0, 0xB0, 0xC0,  
0xD0, 0xE0, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6 and 0xF7 are  
hashed, without clashing, onto the range 0-15.

> Why not use an array

Because for the set of input values, without any processing, you  
would need an array of size 0xF7 - 0x80 = 0x77, or 119, entries.

> a switch statement,

I could, but again given the sparse input values this would either be  
turned into a list of if--else or if the compiler is *really* smart  
it would work out the same hashing function in order to generate an  
index into a jump table.

> a long if/elseif,

Not very compact though is it?  And think of all those lines of source!

Also note that a long chain of if--else has different processing  
times depending on the order of tests - those early in the chain  
execute faster than those at the end of the chain.

> or any of the other possible constructions that would provide this  
> mapping?

You mean, like a hash function and a small function pointer table?   
Its a common idiom.

> If that is really what it's for, I still don't understand why you'd  
> do it like this.

It has many advantages, a few of which I've touched on here.

Cheers,
Neil
--
http://www.njohnson.co.uk






More information about the Synth-diy mailing list