[LAD] "enhanced event port" LV2 extension proposal

Krzysztof Foltman wdev at foltman.com
Mon Nov 26 20:15:40 UTC 2007

Hello all,

A few weeks ago there was a discussion about proposed enhancements to 
Lars Luthman's LV2 MIDI port extension (lv2-midiport.h). I've read the 
suggestions that you gave, and tried to hack together a new version, 
that would enhance the initial standard that Lars designed, by:

- addressing alignment-related issues
- using fixed-point integers for time values
- adding optional sub-channel addressing (for per-note control changes 
and similar features)
- optionally allowing sending floating point automation events in the 
same stream as MIDI events (because mixing several event streams at the 
same time is inefficient)
- optionally allowing sending arbitrary data (similar to SysEx, but 
fully binary safe and without having to pay to register at MMA :) )
- trying to keep it simple, efficient and easy to implement

Finding the right compromise is often an impossible task, so it won't 
probably satisfy everyone. However, I think its advantages outweight 
those of its drawbacks and limitations that I can currently see. The 
basic MIDI-type events can be passed with minimal effort, however, the 
more advanced features require more effort if you want to make use of 
them (though they may be safely ignored).

Here we go - treat it as pseudocode sketch meant to get more feedback 
from you, not as the compilable C code (that's why there is no license 
or copyrights attached, in case anybody's wondering). In fact, there's 
no actual *code* (as in: anything that translates into CPU instructions) 
here, just data structures and declarations. Also, because it is not 
meant to be actually used at this stage, I'm not assigning it any URI.

// data structures for proposed "enhanced event port" extension of LV2 
audio plugin standard
// loosely based on Lars Luthman's lv2-midiport.h; most ideas come from 
people on
// linux-audio-developers mailing list (David Olofson, Lars Luthman, 
Stefan Westerfeld,
// Nedko Arnaudov and others)

// base event structure
// size: 8 octets
// if command < 0x80, one more 8-octet structure follows; the type of that
// structure is dependent on value of command
// the plugin that does not understand the given command can safely skip 
the next 8 bytes
  uint32_t timestamp; ///< fixed-point timestamp with 16 integer and 16 
fractional bits; use of fractional part is optional
  uint8_t command;    ///< command byte - >= 0x80 for MIDI commands, 
<0x80 for 16-octet extended commands
  uint8_t arg1;       ///< for MIDI commands that need it; should be 0 
  uint8_t arg2;       ///< for MIDI commands that need it; should be 0 
  uint8_t subchannel; ///< optional, allows for control changes for 
specific notes; writer must set to 0 if not used

// buffer of events, analogous to LV2_MIDI structure in Lars Luthman's 
  LV2_EVENT_HEADER *first; ///< pointer to the first event, the next 
ones (if any) follow it directly
  uint32_t event_count; ///< number of events in the buffer
  uint32_t block_count; ///< buffer size (current or max, depending on 
if it's input or output buffer) in 8-octet blocks

// the features below are optional and may be ignored by skipping the 
8-octet extension block

// optional command 0x70: set parameter
  uint32_t lv2_ctl_port;
  float new_value;

// feel _encouraged_ to ignore everything below this line ;)

// advanced optional command 0x71: set parameter delta
// specifies that until the next event the parameter
// is supposed to increase linearly by new_value_delta each sample
// this is for super-precise envelopes and other insane paranoid stuff :)
  uint32_t lv2_ctl_port;
  float new_value_delta;


  // increase reference count and return data pointer
  const char *(*ref_inc)(struct LV2_BINARY_BUFFER *self);
  // decrease reference count
  void (*ref_dec)(struct LV2_BINARY_BUFFER *self);
  // get event type URI or MIME type
  const char *(*get_type)(struct LV2_BINARY_BUFFER *self);
  // get string encoding (if applicable)
  const char *(*get_encoding)(struct LV2_BINARY_BUFFER *self);

  // pointer analogous to virtual method table pointer
  // length of data in octets
  uint32_t length;

// advanced optional command 0x72: data block
// in order to get to the data, ref_inc must be used before
// process function ends (and then use ref_dec to free the data)
// otherwise host will free or reuse it to avoid leaks
  union {
    uint64_t pad; // padding so that the structure is 64 bits long


Have fun :)

More information about the Linux-audio-dev mailing list