[gmpi] Re: MIDI: Common event coding

  • From: Tim Hockin <thockin@xxxxxxxxxx>
  • To: gmpi@xxxxxxxxxxxxx
  • Date: Wed, 23 Jun 2004 00:07:01 -0700

On Tue, Jun 22, 2004 at 05:27:28PM -0700, Chris Grigg wrote:
> PROPOSAL:
> GMPI as Addresses, Opcodes, and Operands
> 
> This proposal is intended to find a common coding for GMPI events 
> that neither privileges nor disadvantage either an OSC-style 
> paths/events approach or a MIDI message approach, permits the host to 
> fully manage plug message history, and also permits arbitrary routing 
> and processing of MIDI messages per se.

Chris, I'd like to start by thanking you for all these details (even
though we're in reqs, if we can't agree on a general model, we're doomed).

I'd also like to thank you for (essentially) changing teams.  You've more
or less proposed NMiG.  If this has just been miscommunication, for 800
emails, god help us all.

> Messages - In the general case, all GMPI event types (set parameter, 
> launch note, etc.) can be considered as messages.  Even if fields are 
> actually communicated to plug via separate function parameters. 
> Exact format unimportant now.  Each message to contain one opcode, 
> one address, and any number of operands.

Agree and always have.

> Opcodes as Integers - The set of event types will be small initially, 

I'm not sure why it is important that they be integers, but for the sake
of argument, ok.

> Addresses as Indexes - All GMPI plugs expose all commands & 

I dislike this simply because the plugin lists can be dynamic.  I'd much
rather see a fully qualified pathname.  What if, instead of assuming that
integer parameter IDs are indices, just take them as cookies.  The plugin
tells you that parameter /foo/bar/volume is number 12345.  Then you can
always address volume via 12345, and the plugin can even encode it's own
sematic meaning into the cookie.  As long as cookies are unique withing a
plugin, it's no different than (sparse) indexing.

> Operands - Depending on event type, zero or more operands are also in 
> the message.  Operand count and data type of each depends on the 
> event type.

Each message may also need an operand-length argument.  This starts to
break down when you consider operands that are not integral, though.  How
do you specify "the next operand is floating point" or "the next operand is
a string of X characters" (or NULL terminated) or "the next operand is a
blob of Y bytes" ?

>       Then the OSC-style-notated event "/sidechain/filterCutoffFreq 
> set 3500.9" is losslessly expressed in the form (assuming opcode for 
> 'set' is 2):
> 
>       { <address: index 6> <opcode: 2> <operand: float( 3500.9 )> }

how do you idicate that the operand is going to be a float?  Also, I'm
assuming that the value 3500.9 is guaranteed to be withing the bounds of
the parameter #6.  Right?

> So GMPI hosts route these binary messages to plugs, can parse them in 

I'm not sure why the emphasis on "binary".  <tin_foil_hat> It sounds
like the emphasis on binary is to cath the NMiG camp in some inconsistency
that you've seen </tin_foil_hat>

I don't like that plugins have to decode messages.  Adding cookies as
the paramter "name" helps some.

> All MIDI messages can also be losslessly encoded in the same form, as 
> <address> <opcode> [<operand> ...].  This requires un-binding 
> address, opcode, and operand parts from MIDI message, per the 
> unpacking required by each MIDI message type, and then re-assembling 
> the parts in the common GMPI message format.  Fortunately, the rules 

This is what NMiG people have been saying all along!  Welcome to our camp!
:)  The kool-aid is pretty yummy, have some!

> This re-packaging allows the host to track all MIDI messages equally 

instead of saying MIDI, say "external".  The goal is not to ghetto-ize
MIDI messgaes, but to make ANY external message become GMPI internally.
OSC, HID, MIDI, etc.

> 2.1.1. Whole-Unit Addressing - Many messages implicitly address the 
> receiver as a whole unit:
> - System Real Time group (Timing Clock, Start, Continue, Stop, Active 
> Sensing, System Reset)

To which GMPI might add operations...

> - System Common group (MTC QuarterFrame, Song Position Pointer, Song 
> Select, Tune Request, End of SysEx

Not clear how these MIDI-isms will map to GMPI.  How broken hearted would
we all be if some of these got dropped in favor of GMPI-isms?  Example:
plugs should not need MTC - they should be slaving to the host.  Could we
reaonably drop MTC support for plugins?

> - Manufacturer SysEx (may be internally addressed further, but in the 
> general case contents are opaque)

Fine, as always.

> 2.1.3. Channel Number Addressing - Some messages use only channel 
> number (0-15): Note On, Note Off, Channel Aftertouch, Program Change, 
> Pitch Bend Change

Req #57 says "There may be an arbitrary number of channels per plugin".
So this 0-15 assumption is right out.  Even for MIDI, it is reasonable
that the host would take incoming MIDI port 0 channel 12 and map it to a
GMPI plugin's channel 199.

I'd like to see this addressing mode go away.  Can channel-targetted
messages be handled as an extended case of control addressing?  Req 57
also says "channels need not be symmetric".  Rather than make these
MIDI-isms be first order opcodes, make them channelized parameters.

Then instead of a messgae "channelN aftertouch 123" you have a message 
"set channelN/aftertouch 123".  Less opcodes is more gooder.

> 2.1.4. Channel Plus Key Number Addressing - Poly Aftertouch has both 
> channel & key number
> 
> Channel number plus 'pressure' can be used as the address, key number 
> should be translated to a note-id operand.

Of course you mean that poly-aftertouch is an example of a parameter which
is addressed by channel and voice-id.  Please be careful to say voice-id
rather than note ID.  It is entirely possible to have 100 instances of the
same note playing and addressable all at the same time.

> 2.1.5. Channel Plus Control Number Addressing - Control Change has 
> both channel & control number
> 
> Channel number and control number can be combined into a slashed address.

Can we call this "Direct Addressing"?  All parameters are addressed by
some fully-qualified identifier (whether that is "/path/to/foo" or 12345).
That FQID can encode both the channel and the parameter, with arbitrarily
nested grouping).

> Assigments.  Gesture ID's are shown as optional operands where 
> appropriate.

Without getting any further into details, gesture ID probably needs to be
tightly integrated.

> 0x8n, 0x9n - Note On & Note Off - These are 'command' opcodes of some 
> kind -- that needs to be reconciled with 'pure GMPI' note concepts, 
> however those don't exist yet.  May be combined into one opcode, 

Fair enough.  I promise we'll talk about voice control soon :)

> operand(s) , and probably some note-id operand.  For an event that 
> originated as a MIDI message, the literal MIDI message could be 
> included as the last operand.

I *really* don't see the point in that, but if it makes you happy.  What
about other external protocols?  Do we paperclip the original OSC message,
or HID event?

>       strawman:
>       <address: /channel> <opcode: note> <operand1: note-id> 
> [<operand2: pitchSomething>] [<operand3: gateOnOrOff>] [<operand3: 
> gesture-id>] [<operand4: MIDI>]

This is confusing.  What you really mean is something like:
        <address> <opcode> [<operand...>*]

Examples:
        // standard MIDI-style note-on
        channel0 note-on voice=123 pitch=60.0 velocity=0.75

        // simple note-on, no velocity, no pitch
        channel0 note-on voice=123 

        // complex note-on, with extra parameters
        channel0 notr-on voice=123 pitch=60.0 velocity=0.75 cutoff=12000
                resonance=0.3

Whether or not this is actually one operation is irrelevant, it's one
logical operation.  It should be noted that the operands are totally
dependant on the plugin, and there can be any number of per-note
parameters which apply at note-on or note-off time.

It should also be noted that operands are formatted as the natural range
of their destination.

So a MIDI note-on with velocity of 64 which was sent to a plugin with
float(0-1) velocity would come across as velocity=0.5039...

> 0xAn, 0xDn - Polyphonic Aftertouch & Channel Aftertouch - These can 
> both use the 'set' opcode addressed to parameter 'pressure' in 
> channel n, but the operand set is different.  Poly aftertouch has an 
> extra operand for the target note-id. One pressure operand, either 

Good, so the existance of that 'pressure' parameter indicates that the
plugin cares to receive aftertouch.  I think it is wise to separate the
two, though.  Channel aftertouch is a per-channel parameter and
poly-aftertouch is a per-voice parameter.  Also good that you point out
that it is a "set".  This is just a case of a simple per-channel control
and a simple per-voice control.

> 0xBn- Control Change & Channel Mode - This can use the 'set' opcode 

Sorry, what is channel mode?  Otherwise, I agree.

> 0xCn - Program Change - This can use the 'set' opcode addressed to 
> parameter 'program' channel n.  One value operand.  For an event that 
> originated as a MIDI message, the literal MIDI message could be 
> included as the last operand.

This is fine, though we may actually want to expand on that.  Not sure,
exactly.  What is the operand?  A string (filesystem path? relative path?)
or an integer (index? code?) or other??

> 0xEn - Pitch Bend Change - This can use the 'set' opcode addressed to 
> parameter 'pitchBend' in channel n (subject to final design of GMPI 
> note & pitch model).  One value operand, either way.  For an event 

>       Note, we could also go beyond MIDI and introduce a 
> per-note-id pitch bend, by adding a note-id operand:

Beautiful.  Chris, we're largely on the same page.

> 0xF1 - MTC Quarter Frame - This is a 'command' opcode addressed to 
> 0xF2 - Song Position Pointer - This is a 'set' opcode addressed to 
> 0xF3 - Song Select - This is a 'command' opcode  addressed to the 
> 0xF6 - Tune Request - This is a 'command' opcode  addressed to the 
> 0xF7 - End of System Exclusive - This should not normally result in a 
> 0xF8 - Timing Clock - This is a 'command' opcode  addressed to the 
> 0xFA - Start - This is a 'command' opcode  addressed to the whole 
> 0xFB - Continue - This is a 'command' opcode  addressed to the whole 
> 0xFC - Stop - This is a 'command' opcode  addressed to the whole 
> 0xFE - Active Sensing - This is a 'command' opcode  addressed to the 
> 0xFF - System Reset - This is a 'command' opcode  addressed to the 

I'd need clarification on some of these, and some (I think) we really
don't want to send as far as the plugin.

> 3. Strawman Opcode Assignments

irrelevant for now :)

So, as wonderful as this tastes, I have to ask: What happened to "WE MUST
HAVE MIDI!"?  What happened to the lazy programmers who don't want to
handle GMPI, and just want to use their existing MIDI code?  What happened
to MIDI processors and "studio routing"?  What happenend to all the
arguments that MiG proposed.

What you have here is more-or-less what we've been proposing.  In fact,
some of it is startlingly close to XAP in concept.

I don't want to jinx the process, I like what you say, by and large.

*thank*you*

Tim

----------------------------------------------------------------------
Generalized Music Plugin Interface (GMPI) public discussion list
Participation in this list is contingent upon your abiding by the
following rules:  Please stay on topic.  You are responsible for your own
words.  Please respect your fellow subscribers.  Please do not
redistribute anyone else's words without their permission.

Archive: //www.freelists.org/archives/gmpi
Email gmpi-request@xxxxxxxxxxxxx w/ subject "unsubscribe" to unsubscribe

Other related posts: