On Sat, 2007-12-01 at 23:23 +0100, Krzysztof Foltman wrote:
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.
Agreed
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)
What is the point of having two separate event definitions when one will
do for both, though?
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.
As listed in my previous mail, any audio plugin situation I can conceive
of is covered. Specifically where and why will it fail? This logic
applies for things that try to be universal by being complex, not things
that do it by being simple.
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.
You can freely ignore this and just consider it a frame stamp for your
purposes.
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:
Why? The cons are obvious, what are the pros? A few bits?
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 need to traverse the actual event data anyway, there's no
difference. Noone will ever be skipping through an array of just
headers like this (flat buffer thing again..).
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.
A byte here and a byte there in the header makes no difference to any of
this. We should try to keep it small as possible, yes, but it doesn't
affect what the using code looks like at all.
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).
Well... good thing you don't have to use those stamps for the 'others'.
Again, I'm not proposing anyone use OSC style stamps in place of frame
stamps...
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.
I think being directly compatible with Jack, with higher resolution,
while also capable of being an absolute or tempo based time stamp is a
pretty clear winner when the only downside is 4 bytes. 16:16
fixed /decreases/ the stamp range compared to Jack's by a factor of 2^16
remember. That's a big decrease.
I've directly run into problems with the MIDI timestamp type in Ardour
(I was wrong, floating point stamps were stupid, didn't realise it
before this conversation though). 32:32 fixed stamps solve all the
problems. Ardour will be able to use the same event struct from Jack
through ringbuffers, to tempo based time, through plugins, right down to
the file writing (the tempo stuff is going to have to use stamps like
this anyway). It would be perfect...
Ingen could transparently read, schedule, process, and output absolute
stamped OSC messages with minimal jitter and latency compensation. It
would be perfect...
In short; I've hit a lot of actual, real, concrete problems in working
code, and 32:32 fixed stamps solve them all beautifully. 4 bytes
somewhere is not quite a convincing enough argument for me to be happy
dealing with 5 different event structs (and all the translation) instead
of 1 ;)
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.
Bit... odd. Sure, saves 2 bytes, but at the cost of throwing out that
OSC stamp compatibility (which I guarantee will be actually useful).
Plus... well, 2 bytes. Recentish chips can keep a few million of them
in cache. :)
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 :)
You don't always need to memcpy it. Arbitrary restrictions are neither
wise or necessary in the spec. uint32_t is a good limit for size (it's
used in both Jack MIDI and OSC, so everything matches)
-DR-