[LAD] "enhanced event port" LV2 extension proposal

Krzysztof Foltman wdev at foltman.com
Sat Dec 1 22:23:50 UTC 2007

Dave Robillard wrote:

> Taking a step back, it would be nice to have these events (being
> generic) able to use something other than frame timestamps, for future
> dispatching/scheduled type event systems.

I think there's certain advantage to using sample frames for events in 
the typical audio plugin situations. On the other hand, it doesn't cover 
all weird stuff people will want to do.

I could even think of two event ports - one for typical frame-based 
stuff, other for absolute nanosecond time or what not. Keep in mind that 
converting nanoseconds to frames in typical case would be very very slow 
(64-bit divisions, or at least multiplications)

So, if we need something else than sample-based timing, we should do it 
elsewhere (by defining another event type, or something). Trying to fit 
everything in - audio, video, networking, industrial equipment, car 
engine control etc - is highly likely to fail.

> OSC uses 64 big fixed point
> absolute time stamps, giving a resolution of about 200 picoseconds
> absolute time (epoch January 1, 1900).  This is equivalent to NTP time
> stamps apparently - ie huge precedent.

Also, huge overkill, in my opinion :) It might be needed in some cases, 
but demanding everyone to use this resolution is bad.

> Whether stamps are in frames or absolute time could be a property of the
> port.

You may not like it, but I would actually like two kinds of ports:

- one for experimental weird stuff (may be even 64-bit integer in 
200-picosecond units, why not); this could be nice for certain uses but 
overkill/inefficient in most situations

- one for bread-and-butter stuff, sample based; and here you could even 
use just 32-bit integers, not fixed point numbers, the certain events 
that would indeed require fractional part of the timestamp (grain 
start), would define it as a part of payload

The structures will probably be very similar, the event types carried 
inside might be the exactly same (including URI-to-number mapping 
scheme!). The experimental plugins and hosts would implement the 
extended event transport, most of the everyday stuff would just stick to 
the basic sample-based one.

That kind of fits the "do one thing and do it well" rule. Both ports 
wouldn't be directly compatible anyway (because they use different 
timing schemes) so why not keep them separate? :)

> Maybe we should up it to 64 bits fixed point?  The additional 32
> bits aside, doing that gives us all the range or precision in frames
> needed, and the ability to map to a widespread absolute timestamp
> format, and parity with OSC.  That's a lot of pros...

I'm more comfortable with 8-byte header, just because it lets us use 
headers as unit of data (payload is always padded to 8 bytes, think 
pointers on 64-bit machines). As in the code example I've posted (minus 
the bug).

With 12-byte headers, we get some ugly pointer arithmetic (and pointer 
alignment problems on 64-bit machines). With 16-byte headers, we either 
count in 16-byte units (just think of 1-byte MIDI messages here :) ), or 
align to 8 and get ugly pointer arithmetic.

You can't just write anything as brief as:

   i += (event[i].size + 7) >> 3;

when you have 12-byte headers. And losing 15 bytes for 1 byte messages 
in 16-byte solution without pointer arithmetic may be acceptable, but 
gives me certain discomfort :)

Yet another solution would be to keep header 12-byte + 4 bytes of 
data/padding (for short messages). But I think we've already been there, 
and you didn't like it much, right? :)

Everything that allows plugin loops to be simple and readable and 
doesn't waste CPU/bus cycles or (whether on misalignment penalties, long 
divisions, float-to-int, 32 bytes per average event) is going to be fine 
to me. It's just that... well, you can see for yourself, there are not 
many solutions that satisfy all of those criteria.

Those are my reasons for "bit paranoia" which annoys you so much :)

> (This may sound a bit esoteric, but to do something like Max right, you
> need absolute time stamps).

Absolute time stamps can still be done by keeping some sort of state 
between process calls, plus optionally some "set absolute time (resync)" 
kind of events.

> Currently in MIDI we have 64 bits in there anyway.. I never thought of
> using fixed point, but the OSC/NTP parity and potential for very precise
> absolute time stamps is very, very tasty to me.

Tastes like 64-bit division, which as far as I know involves a function 
call on average x86 platform ;) Good for some stuff (networking, audio 
plus video), absolutely horrible for others (think granular synthesis 
which has dense events).

> Also, the frame part would be a uint32_t - equivalent to Jack MIDI
> timestamps, another win (and cutting out more conversion overhead).

I like this - just don't like the consequences on header size :) Hard to 
find a clear winner here.

By the way, what about 48-bit timestamp as another candidate? (32 int, 
16 fract) Still leaves 2 bytes for other stuff (size, type) in 8-byte 
header. Restricting payload size to 255 bytes max doesn't sound like a 
total disaster. Larger data will be likely passed by reference anyway, 
doing otherwise in a realtime system usually smells like bad design :) 
Just think of memcpying those data back and forth when those 20 reverbs 
wait for their turn :)


More information about the Linux-audio-dev mailing list