Re: [LAD] enhanced event port LV2 extension proposal

2007-12-10 Thread Krzysztof Foltman
Dave Robillard wrote:

 Not valid in C++.
 Ah, that was it.  Back to char we go.

We have some choices:

1. your original uint8_t - good because you can still do
(event-data)[offset], bad because it breaks sizeof somewhat, making it
totally misleading (this particular clock doesn't show the right time
even once per 12 hours ;) )

2. uint8_t[1] - variant of solution 1, just *slightly* better because
you can write event-data[offset] instead of (event-data)[offset]

3. uint8_t[0] - gcc extension, possibly incompatible with non-gcc
compilers (I don't care, I bet someone else does)

4. uint8_t[4] - variant of solution 1 with somewhat better sizeof
behaviour (at least it returns the proper size for payload length = 4)

5. separate header structure and event-type specific event structure
(with header as first field), equivalent to what Nedko proposed. Not as
awkward as you probably imagine. You'll find examples in my previous
mails if you have any doubt about what I mean.

I'm fine with either choice. 4 and 5 look somewhat attractive, 3 is
probably out of the question.

Anyway, we're arguing about changing one or two lines of code in a
plugin here, so if you think a single uint8_t member is a way to go,
it's fine IMHO.

The URI passing thing is much more interesting, as it affects 5 lines of
plugin code, not 2, so it'd be better to concentrate on that one.

I'd still prefer to have new URI mappings delivered to plugins (which
you don't like), and URI-int mapping to be implemented in a host (which
you like, IIRC). No matter what calling convention is - C++-style
object or a structure with function pointer and instance pointer. At
least as long as it doesn't lead to GObject-style insanity :)

 this struct in that case would be handy), but I guess that could just be
 another event type?

Absolutely.

 char* does cause confusion though, as this thread made painfully clear
 earlier...

Yes, and how would you refer to in-place char data? ((char
*)(event-data))[0]? Do you like it?

Krzysztof
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-12-09 Thread Krzysztof Foltman
Dave Robillard wrote:
 Is this what we have for the event/buffer header, then?
 http://svn.drobilla.net/lad/lv2/extensions/events/lv2_events.h 
   
char data? why not char data[0]?

Krzysztof

___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-12-09 Thread Nedko Arnaudov
Krzysztof Foltman [EMAIL PROTECTED] writes:

 Dave Robillard wrote:
 Is this what we have for the event/buffer header, then?
 http://svn.drobilla.net/lad/lv2/extensions/events/lv2_events.h 
   
 char data? why not char data[0]?

just header please

-- 
Nedko Arnaudov GnuPG KeyID: DE1716B0


pgpV4XRXS0CZd.pgp
Description: PGP signature
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-12-09 Thread Dave Robillard
On Sun, 2007-12-09 at 15:06 +, Krzysztof Foltman wrote:
 Dave Robillard wrote:
  Is this what we have for the event/buffer header, then?
  http://svn.drobilla.net/lad/lv2/extensions/events/lv2_events.h 

 char data? why not char data[0]?

Not standard C AFAIK.

-DR-


___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-12-09 Thread Dave Robillard
On Sun, 2007-12-09 at 18:08 +0200, Nedko Arnaudov wrote:
 Krzysztof Foltman [EMAIL PROTECTED] writes:
 
  Dave Robillard wrote:
  Is this what we have for the event/buffer header, then?
  http://svn.drobilla.net/lad/lv2/extensions/events/lv2_events.h 

  char data? why not char data[0]?
 
 just header please

How would you access the data in code? (it'd be ugly/annoying)

-DR-


___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-12-09 Thread Dave Robillard
On Sun, 2007-12-09 at 17:09 +, Krzysztof Foltman wrote:
 Dave Robillard wrote:
  How would you access the data in code? (it'd be ugly/annoying)
 
 Control byte of MIDI - data[0]
 First argument of MIDI - data[1]
 Second argument of MIDI - data[2]

. duh.  Try to note what something is a reply to /before/
responding ;)

-DR-


___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-12-08 Thread Dave Robillard
Is this what we have for the event/buffer header, then?

http://svn.drobilla.net/lad/lv2/extensions/events/lv2_events.h 

(Ignoring the URIs, references to nonexistant symbol stuff, etc.)

Cheers,

-DR-

___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-12-06 Thread Krzysztof Foltman
Dave Robillard wrote:

 There are times when 'GoF Patterns in Java' style is appropriate for
 discussion solutions.
 This isn't one of them.

And that's because?

Krzysztof

___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-12-06 Thread Krzysztof Foltman
Lars Luthman wrote:

 That sounds OK. I suggest something like this:
 struct URI_Mapper {
   // call this with your URI and the host_data member - not RT safe
   uint16_t (map_function*)(const char* uri, void* host_data);
   // pass this as the second parameter to map_function()
   void* host_data;
 };
 It doesn't provide a way for the host to say I'm out of IDs! though.
 Will that be needed?

What about using int32_t and returning -1 as out of IDs? There's no
difference in CPU time spent anyway, because uint16_t is returned in the
same 32-bit register as int32_t is (eax, on x86).

Or you can use 0 (or 65535) for error. It doesn't look like something
that requires lots of thinking.

Also, a reverse mapping mechanism would be helpful at times (for
debugging/data monitors). I put it in my proposal for that specific
reason. It shouldn't be hard to implement, either (might be a waste of
memory, but of acceptable kind).

Or it might be a separate feature, so that certain people won't get too
confused ;)

Krzysztof

___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-12-05 Thread Krzysztof Foltman
Dave Robillard wrote:

 Not really 'nicely'... essentially implementing the exact same thing n
 times.  Why bother?

Huh???

Instantiating n times, not implementing.

I know there are certain bad programmers around who would implement it
multiple times or use copy-paste for code reuse, but I don't think
they make LV2 hosts.

 Also, I would be for a requirement that numbers are always assigned (by
 host) sequentially starting from 0, not by - for example - hashing,
 because then some plugins could use small arrays to store
 event-type-to-handler mapping (or
 something-id-to-whatever-data-structure). Is that OK?
 The interface for the dynamic part would have to be figured out before
 this can be decided.

??? Well, just proposed one. I don't know if it's the best one, as
nobody proposed any alternative, but it certainly works.

 ... did I stumble on to the Java 101 mailing list by mistake? ;)

Do you think interfaces are a Java thing?

Hint: IDL. Makes some explanations shorter. Also, allows us not to get
distracted by details like if user data should be passed as void * or
struct * or integer cookie or anything else.

If there are *really* people who don't get it (shouldn't have been
sleeping through OOP courses :P), let me translate it, say, to C:

/*** functions in IURIRegistryObserver_funcs are only implemented by
the plugin when it wants notifications about new types /

struct IURIRegistryObserver;

struct IURIRegistryObserver_funcs
{
  // function in a plugin called by host on new URI registration
  void (*mapping_added)(struct IURIRegistryObserver *observer, int id,
const char *uri);
};

struct IURIRegistryObserver
{
  struct IURIRegistryObserver_funcs *functions;
  // plugin may place it in a larger structure, and cast a pointer
};

/* functions implemented by host, used for mapping URIs and numbers */

struct IURIRegistry_funcs
{
  // returns -1 if new registrations are not supported
  int (*uri_to_id)(struct IURIRegistry *registry, const char *uri, bool
create_if_absent);

  // returns pointer to the URI (host-owned), or NULL
  const char *(*id_to_uri)(struct IURIRegistry *registry, int id);

  // might be a do-nothing if the host doesn't support registering uris
on the fly

  void (*add_observer)(struct IURIRegistryObserver *observer);

  // might be a do-nothing if the host doesn't support registering uris
on the fly
  void (*remove_observer)(struct IURIRegistryObserver *observer);
};

/* structure returned by get_registry */
struct IURIRegistry
{
  struct IURIRegistry_funcs *functions;
  // host may place it in a larger structure, and cast a pointer
};

// structure on host side
struct IURIRegistries_funcs
{
  struct IURIRegistry *get_registry(const char *uri);
};

// structure on host side
struct IURIRegistries
{
  IURIRegistries_funcs *functions;
  // host may place it in a larger structure, and cast a pointer
};

Or to C++:

class IURIRegistryObserver
{
  virtual void mapping_added(int id, const char *uri) = 0;
};

class IURIRegistry
{
  virtual int uri_to_id(const char *uri, bool create_if_absent) = 0;
  virtual const char *id_to_uri(int id) = 0;
  virtual void add_observer(IURIRegistryObserver *observer) {}
  virtual remove_observer(IURIRegistryObserver *observer) {}
};

class IURIRegistries
{
  virtual IURIRegistry *get_registry(const char *registry_uri) = 0;
};

In fact, instead of IURIRegistries* you may have separate feature per
registry. Doesn't matter much.

Perhaps you want reference implementation, too? :D

Krzysztof

___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-12-05 Thread Krzysztof Foltman
Lars Luthman wrote:

 I don't like having something this complicated in an extension that is
 going to be required if you just want to write a simple synth with a
 MIDI input.

Hey, it's simpler than it looks like. Especially when you're writing a
plugin. All you need to do is do this during activation (C++ code):

// assume you have the void* for the registries feature already
IURIRegistries *registries = (IURIRegistries *)feature_value;
IURIRegistry *registry =
registries-get_registry(http://example.com/event_types_registry;);
if (registry) {
  midi_event_id =
registry-uri_to_id(http://example.com/midi_event_type;, true);
}

And that's all. With C you'd have
registries-functions-get_registry(registries,
http://example.com/event_types_registry;) instead, but that's still 6
lines of code or less. Done on activation. Nothing truly bad.

 Is there really any need for adding and removing mappings dynamically?

I think it is (especially adding). For inter-plugin communication - even
when host doesn't support a specific plugin type, two connected plugins may.

And Dave will probably agree with me here.

The big question here is memory management when host doesn't support the
type of data which is passed between two plugins (ie. if one plugin
produces an event which is of a type which has a pointer inside, then
who does free the memory? receiver just after reception, or sender
during next process() call?)

 Just passing an array in the LV2_Feature data would be enough for me.

But then, how would you search the array if it had, say, 1000 items?
Linear search with strcmp on each item?

Exposing the uri-id in the host lets you reuse host's lookup
implementation, which may be more efficient (say, using a hash table or
a tree like std::map).

Not that expect that many items in an array, especially if it was
restricted to event types only, and not a general mapping.

Krzysztof

___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-12-05 Thread Lars Luthman
On Wed, 2007-12-05 at 09:45 +, Krzysztof Foltman wrote:
 Lars Luthman wrote:
 
  I don't like having something this complicated in an extension that is
  going to be required if you just want to write a simple synth with a
  MIDI input.
 
 Hey, it's simpler than it looks like. Especially when you're writing a
 plugin. All you need to do is do this during activation (C++ code):
 
 // assume you have the void* for the registries feature already
 IURIRegistries *registries = (IURIRegistries *)feature_value;
 IURIRegistry *registry =
 registries-get_registry(http://example.com/event_types_registry;);
 if (registry) {
   midi_event_id =
 registry-uri_to_id(http://example.com/midi_event_type;, true);
 }

And with an array you'd have

const char* const* uris = feature_data;
for (uint16_t i = 0; uris[i]; ++i) {
  if (!strcmp(uris[i], midi_type_uri)) {
midi_event_id = i;
break;
  }
}

The difference is not in the number of lines but in how many new
functions and types are used. The fewer the better. Sure, in practice
this will probably be done with a single function call to some plugin
support library, but the actual spec should still be as simple as
possible.


  Is there really any need for adding and removing mappings dynamically?
 
 I think it is (especially adding). For inter-plugin communication - even
 when host doesn't support a specific plugin type, two connected plugins may.

If a plugin supports an event type (I assume that's what you meant) it
can list it in its RDF file, and then the host can map it and that
plugin will get an ID for that event type URI, regardless of whether the
host or any other loaded plugin supports that event type or not. Though
I don't think it's such a great idea to load plugins that need event
types that the host doesn't know anything about, for the reasons you
list below. If you want some sort of generic event where the host
doesn't need to bother with the actual content you could define a single
event type for that - maybe something like the refcounted objects you
talked about earlier.


  Just passing an array in the LV2_Feature data would be enough for me.
 
 But then, how would you search the array if it had, say, 1000 items?
 Linear search with strcmp on each item?

Sure. It's just on instantiation. If you wanted to be smart you could
have the host sort the array and pass the size as well and let the
plugin do binary searches.


--ll


signature.asc
Description: This is a digitally signed message part
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-12-05 Thread Krzysztof Foltman
Lars Luthman wrote:

 The difference is not in the number of lines but in how many new
 functions and types are used.

I think the cost-benefit ratio is important here. The added complexity
may be worth it for me, but perhaps not for you.

I hope we're still at pretty low complexity level, but that is a very
subjective thing.

 If a plugin supports an event type (I assume that's what you meant) it
 can list it in its RDF file, and then the host can map it and that
 plugin will get an ID for that event type URI,

The point is, how a previously loaded plugin (a transparent bridge or
something) will be informed about the new type? In most cases it would
work, though. It's just that old loaded plugins will not know the
mapping for new types, which might be OK for many applications. Not
that I think it's a good solution, just an acceptable one.

We can ignore the issue for now, but maybe it should be picked up later
at some point, when deciding about runtime extensibility.

Question to Dave, do you see any way to invalidate a particular RDF
triplet, then announce another one? say: PluginX is no longer a
ReverbPlugin, PluginX is now a FilterPlugin. Or port 4 is no longer the
plugin X's port. It's unrelated to our current discussion, I know.
Perhaps some kind of rdf triplet event type, that would carry
information about knowledge update, if you know what I mean? Not
timestamped, perhaps :)

 Sure. It's just on instantiation. If you wanted to be smart you could
 have the host sort the array and pass the size as well and let the
 plugin do binary searches.

So it would have to be an array of pairs (uri, number), right? Because
otherwise adding any new number will mess up the numbering.

Krzysztof
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-12-05 Thread Lars Luthman
On Wed, 2007-12-05 at 16:34 +, Krzysztof Foltman wrote:
 Lars Luthman wrote:
 The point is, how a previously loaded plugin (a transparent bridge or
 something) will be informed about the new type? In most cases it would
 work, though. It's just that old loaded plugins will not know the
 mapping for new types.

My idea is that if the plugin knows how to handle an event type it
should list that type in its RDF data, and the host will assign it an
integer value. A plugin that doesn't care about the event types, e.g. a
generic quantizer, doesn't care about the event types, so any new
mappings wouldn't matter to it.


  Sure. It's just on instantiation. If you wanted to be smart you could
  have the host sort the array and pass the size as well and let the
  plugin do binary searches.
 
 So it would have to be an array of pairs (uri, number), right? Because
 otherwise adding any new number will mess up the numbering.

Yeah, if it's sorted. I don't really think it's needed though, iterating
through a couple of hundreds of strings (in extreme cases) isn't that
much work to do at instantiation time.


--ll


signature.asc
Description: This is a digitally signed message part
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-12-05 Thread Dave Robillard

On Wed, 2007-12-05 at 04:35 +0100, Lars Luthman wrote:
 On Tue, 2007-12-04 at 09:42 +, Krzysztof Foltman wrote:
  What about this (translate it to C in your heads :) ):
  
  interface IURIRegistryObserver
  {
// function in plugin etc. called by host whenever new URI is registered
void mapping_added(int id, const char *uri);
  };
  
  interface IURIRegistry
  {
int uri_to_id(const char *uri, bool create_if_absent);
const char *id_to_uri(int id);
void add_observer(IURIRegistryObserver *observer);
void remove_observer(IURIRegistryObserver *observer);
  };
  
  interface IURIRegistries
  {
IURIRegistry *get_registry(const char *registry_uri);
  };
 
 I don't like having something this complicated in an extension that is
 going to be required if you just want to write a simple synth with a
 MIDI input. Is there really any need for adding and removing mappings
 dynamically?

Definitely agreed.

 Just passing an array in the LV2_Feature data would be enough for me.

Simple is nice, but somewhat closed ended.

How about simply passing a function pointer which converts a string to
an int? (in a Feature struct so things can be added for a more advanced
symbol system in the future)

Easier on the plugin author to just call a function than have to
implement that search all over the place anyway.

-DR-


___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-12-05 Thread Lars Luthman
On Wed, 2007-12-05 at 22:50 -0500, Dave Robillard wrote:
 On Wed, 2007-12-05 at 04:35 +0100, Lars Luthman wrote:
  On Tue, 2007-12-04 at 09:42 +, Krzysztof Foltman wrote:
   What about this (translate it to C in your heads :) ):
   
   interface IURIRegistryObserver
   {
 // function in plugin etc. called by host whenever new URI is registered
 void mapping_added(int id, const char *uri);
   };
   
   interface IURIRegistry
   {
 int uri_to_id(const char *uri, bool create_if_absent);
 const char *id_to_uri(int id);
 void add_observer(IURIRegistryObserver *observer);
 void remove_observer(IURIRegistryObserver *observer);
   };
   
   interface IURIRegistries
   {
 IURIRegistry *get_registry(const char *registry_uri);
   };
  
  I don't like having something this complicated in an extension that is
  going to be required if you just want to write a simple synth with a
  MIDI input. Is there really any need for adding and removing mappings
  dynamically?
 
 Definitely agreed.
 
  Just passing an array in the LV2_Feature data would be enough for me.
 
 Simple is nice, but somewhat closed ended.
 
 How about simply passing a function pointer which converts a string to
 an int? (in a Feature struct so things can be added for a more advanced
 symbol system in the future)
 
 Easier on the plugin author to just call a function than have to
 implement that search all over the place anyway.

That sounds OK. I suggest something like this:

struct URI_Mapper {
  // call this with your URI and the host_data member - not RT safe
  uint16_t (map_function*)(const char* uri, void* host_data);
  // pass this as the second parameter to map_function()
  void* host_data;
};

It doesn't provide a way for the host to say I'm out of IDs! though.
Will that be needed?


--ll


signature.asc
Description: This is a digitally signed message part
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-12-04 Thread Krzysztof Foltman
Dave Robillard wrote:

 Using a uint32_t (which is a reasonable limit for number of symbols in
 pretty much any system) and just not using out of range numbers for the
 event ones doesn't seem so bad, just in case.  It's one line in a
 comment somewhere, BFD.

I'm thinking of something else - like having different domains for
mappings. Like http://whatever/parameter-value gets number 10 in
URI-to-event-type mapping, and number 16777216 in URI-to-global-numbers
mapping. Basically, same class (URI-to-int mapper), different objects
(event type URI registry, plugin port URI registry, plugin URI registry,
 and so on). Different dictionaries, same dictionary interface.

I'm not insisting this is a good idea - just that it could solve the
max 65536 types thing nicely while preserving some (not all)
generality. It could also lead to a mess if somebody used wrong type ID
(when the same URI is in two registries).

Also, I would be for a requirement that numbers are always assigned (by
host) sequentially starting from 0, not by - for example - hashing,
because then some plugins could use small arrays to store
event-type-to-handler mapping (or
something-id-to-whatever-data-structure). Is that OK?

Seems that we don't have as many ideas for design of URI-int mapping as
we had for binary layout ;)

What about this (translate it to C in your heads :) ):

interface IURIRegistryObserver
{
  // function in plugin etc. called by host whenever new URI is registered
  void mapping_added(int id, const char *uri);
};

interface IURIRegistry
{
  int uri_to_id(const char *uri, bool create_if_absent);
  const char *id_to_uri(int id);
  void add_observer(IURIRegistryObserver *observer);
  void remove_observer(IURIRegistryObserver *observer);
};

interface IURIRegistries
{
  IURIRegistry *get_registry(const char *registry_uri);
};

Where IURIRegistries pointer is passed as a feature to a plugin.

Either that, or expose individual IURIRegistry objects as separate
features (perhaps deriving from http://something/uri-registry, RDF
allows that, right?).

Note that there is no delete function, as is doesn't seem very useful
for our purposes. Otherwise, it should be fine.

Thoughts?

Krzysztof
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-12-04 Thread Lars Luthman
On Tue, 2007-12-04 at 09:42 +, Krzysztof Foltman wrote:
 What about this (translate it to C in your heads :) ):
 
 interface IURIRegistryObserver
 {
   // function in plugin etc. called by host whenever new URI is registered
   void mapping_added(int id, const char *uri);
 };
 
 interface IURIRegistry
 {
   int uri_to_id(const char *uri, bool create_if_absent);
   const char *id_to_uri(int id);
   void add_observer(IURIRegistryObserver *observer);
   void remove_observer(IURIRegistryObserver *observer);
 };
 
 interface IURIRegistries
 {
   IURIRegistry *get_registry(const char *registry_uri);
 };

I don't like having something this complicated in an extension that is
going to be required if you just want to write a simple synth with a
MIDI input. Is there really any need for adding and removing mappings
dynamically?

Just passing an array in the LV2_Feature data would be enough for me.


--ll

PS. Who keeps breaking the list headers? About 50% of the time Reply to
list doesn't work on mails in this thread.


signature.asc
Description: This is a digitally signed message part
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-12-03 Thread Dave Robillard
On Mon, 2007-12-03 at 03:32 +0100, Lars Luthman wrote:
 On Sun, 2007-12-02 at 21:08 -0500, Dave Robillard wrote:
  On Mon, 2007-12-03 at 02:29 +0100, Lars Luthman wrote:
   For the URI-int mapping, I've changed my mind and vote for a separate
   Feature that you have to explicitly list in the RDF file. It may be
   useful for other extensions where you need to have arbitrarily
   extendable stuff that you want to match to your known data reasonably
   fast. The actual mapping would be done by the host by passing a
   NULL-terminated URI array as the data for that Feature, where the index
   of an URI in the array is the associated integer value. Or maybe we
   should pass the size of the array as well and require that it's sorted
   in lexicographical order, so a clever plugin can do a binary search? Not
   really important, it will only happen at instantiation time anyway.
  
  Fully agreed.  int-URI mapping is generic and widely useful.  This
  does have me thinking about range though.. you can have an awful lot of
  URIs in a system.  I guess the generic extension can map to, say,
  uint32_t, but the event extension can specifically say the event type
  URIs need to fit in uint16_t?  Maybe doesn't matter but I think allowing
  a huge number of URIs is a good idea if it's just a single (or half)
  word, just in case.
 
 I doubt anyone is ever going to use more than a couple of tens of URIs
 with this.

What if, say, symbols are used as identifiers to shared data structures?
If you've got a symbol per sample or something, it could get high fast.

OSC has a specific symbol type we could use to get super fast
comparison/lookup of things keyed by symbol.  Parameters in each message
being a symbol?  That can definitely get high fast...

Using a uint32_t (which is a reasonable limit for number of symbols in
pretty much any system) and just not using out of range numbers for the
event ones doesn't seem so bad, just in case.  It's one line in a
comment somewhere, BFD.

 It's really only for things that will be compared and
 processed in a realtime thread, non-time-critical code might as well use
 strings directly. I'm fine with limiting the total number of URIs (or
 symbols or names or whatever) to 2^16 in the URI mapping extension
 itself to avoid annoying and inelegant constraints in the event port
 extension.
 
 
  If it is just for URIs, we could maybe take advantage of prefixes and
  save some space in that table?  lv2:Plugin is a lot nicer to deal with
  in all cases than http://lv2plug.in/ns/spec/lv2core#Plugin
 
 Hm. Feels a bit hacky. Memory isn't really an issue unless you use tens
 of thousands of these which seems a bit unlikely, and if it's just for
 code prettification you might as well use a macro.
 
   #define LV2(sfx) http://lv2plug.in/ns/spec/lv2core#; sfx
 
   const char* my_uri_map[] = { LV2(Plugin), LV2(Baaah), NULL };

Yeah, this extension probably shouldn't be concerned with the actual
contents of the strings/symbols anyway (they can still be prefixed names
in some cases).  Just a thought..

-DR-


___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-12-02 Thread Krzysztof Foltman
I think the version you (probably) proposed is:

struct LV2_EVENT_HDR
{
  uint32_t frame, subframe;
  unsigned int size:24;
  unsigned int type:8;
  // put data here, but header size+data size must be a multiple of 8
};

plus 8-byte alignment requirement (ie. header size+payload size must be 
an integer multiple of 8), is going to work.

Either that, or 16 bits for both size and type. Or 16 bits for size and 
8 bits for type, and the remaining byte may be used for char field in 
payload (5 byte payload for free). All three are more or less equally 
good/bad.

MIDI would look like this: 12 bytes header, (up to) 3 bytes content, 1 
byte padding - which is fine.

Same for pointer-only data on 32-bit architecture, for 64-bit, there 
would be a padding of 4 bytes followed by 8-byte pointer. Not very 
elegant, but perfectly acceptable. Plus, the compiler takes care of 
generating padding.

Krzysztof

___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-12-02 Thread Dave Robillard
On Mon, 2007-12-03 at 02:29 +0100, Lars Luthman wrote:
 On Sun, 2007-12-02 at 19:39 -0500, Dave Robillard wrote:
  On Sun, 2007-12-02 at 22:25 +, Krzysztof Foltman wrote:
   Lars Luthman wrote:
with data padded to 4+N*16 bytes
   4 + N*8. 16 is excessive, while 4 is not enough (to be able to store 
   aligned doubles or 64-bit pointers).
   
   But, yes, I think header is ready. Right, Dave?
  
  Works for me, I get my timestamp :)
  
  On to the buffer header (same as MIDI?  more clever?) and the URI-int
  mechanism..
 
 Aligned to 8 bytes sounds good to me too. Done.
 
 I'm happy with a port buffer header that has the same layout as the
 current MIDI one (I should be...).
 
 For the URI-int mapping, I've changed my mind and vote for a separate
 Feature that you have to explicitly list in the RDF file. It may be
 useful for other extensions where you need to have arbitrarily
 extendable stuff that you want to match to your known data reasonably
 fast. The actual mapping would be done by the host by passing a
 NULL-terminated URI array as the data for that Feature, where the index
 of an URI in the array is the associated integer value. Or maybe we
 should pass the size of the array as well and require that it's sorted
 in lexicographical order, so a clever plugin can do a binary search? Not
 really important, it will only happen at instantiation time anyway.

Fully agreed.  int-URI mapping is generic and widely useful.  This
does have me thinking about range though.. you can have an awful lot of
URIs in a system.  I guess the generic extension can map to, say,
uint32_t, but the event extension can specifically say the event type
URIs need to fit in uint16_t?  Maybe doesn't matter but I think allowing
a huge number of URIs is a good idea if it's just a single (or half)
word, just in case.

Though that's starting to sound like we're implementing a symbol
system... probably going to be wanting one of those at some point
regardless.  Is that what this really is? (probably doesn't affect
implementation much, just a hypothetical question).

If it is just for URIs, we could maybe take advantage of prefixes and
save some space in that table?  lv2:Plugin is a lot nicer to deal with
in all cases than http://lv2plug.in/ns/spec/lv2core#Plugin

-DR-


___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-12-02 Thread Lars Luthman
On Sun, 2007-12-02 at 21:08 -0500, Dave Robillard wrote:
 On Mon, 2007-12-03 at 02:29 +0100, Lars Luthman wrote:
  For the URI-int mapping, I've changed my mind and vote for a separate
  Feature that you have to explicitly list in the RDF file. It may be
  useful for other extensions where you need to have arbitrarily
  extendable stuff that you want to match to your known data reasonably
  fast. The actual mapping would be done by the host by passing a
  NULL-terminated URI array as the data for that Feature, where the index
  of an URI in the array is the associated integer value. Or maybe we
  should pass the size of the array as well and require that it's sorted
  in lexicographical order, so a clever plugin can do a binary search? Not
  really important, it will only happen at instantiation time anyway.
 
 Fully agreed.  int-URI mapping is generic and widely useful.  This
 does have me thinking about range though.. you can have an awful lot of
 URIs in a system.  I guess the generic extension can map to, say,
 uint32_t, but the event extension can specifically say the event type
 URIs need to fit in uint16_t?  Maybe doesn't matter but I think allowing
 a huge number of URIs is a good idea if it's just a single (or half)
 word, just in case.

I doubt anyone is ever going to use more than a couple of tens of URIs
with this. It's really only for things that will be compared and
processed in a realtime thread, non-time-critical code might as well use
strings directly. I'm fine with limiting the total number of URIs (or
symbols or names or whatever) to 2^16 in the URI mapping extension
itself to avoid annoying and inelegant constraints in the event port
extension.


 If it is just for URIs, we could maybe take advantage of prefixes and
 save some space in that table?  lv2:Plugin is a lot nicer to deal with
 in all cases than http://lv2plug.in/ns/spec/lv2core#Plugin

Hm. Feels a bit hacky. Memory isn't really an issue unless you use tens
of thousands of these which seems a bit unlikely, and if it's just for
code prettification you might as well use a macro.

  #define LV2(sfx) http://lv2plug.in/ns/spec/lv2core#; sfx

  const char* my_uri_map[] = { LV2(Plugin), LV2(Baaah), NULL };


--ll


signature.asc
Description: This is a digitally signed message part
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-12-01 Thread Dave Robillard
On Fri, 2007-11-30 at 09:45 +, Krzysztof Foltman wrote:
 Dave Robillard wrote:
 
  We could use float I guess to save a bit of space, but I definitely
  prefer floating point.  Fixed point is just a PITA, modern CPUs are much
  faster at FP anyway, why bother?
 
 1. The modern CPUs are much faster at FP thing is a myth that shows up
 here and there and is usually taken as a gospel by people who don't know
 what they're doing (or what their CPU is doing).

The Fixed point is faster than FP thing is a myth that shows up here
and there and is usually taken as gospel by people who don't know what
they're doing (or what their CPU is doing) ;)

Fixed point is a PITA.  Time based effects and whatnot do math on time
stamps, and doing math on fixed point is a massive nuisance compared to
floating.  With floating, if you want to time stretch by a factor of
2 multiply by 2.  Fixed?  Well, first write your fixed point
arithmetic library, then.

Unless there's very /significant/ advantages to bothering with it,
well.. why bother with it.  I've advocated high precision floating point
in the past because 'groove' effects and such are obviously much better
off with such a representation.

At the end of the day, for basic synths etc. timestamp things aren't
going to be a remotely significant part of the CPU time spent by a
plugin; I doubt the fixed point nuisance is worth it.

Premature optimisation is the root of all evil...
 
-DR-


___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-12-01 Thread Dave Robillard
On Fri, 2007-11-30 at 11:23 +0100, David Olofson wrote:
 On Friday 30 November 2007, Krzysztof Foltman wrote:
 [...several points that I totally agree with...]
  If you use integers, perhaps the timestamps should be stored as
  delta values. 
 
 That would seem to add complexity with little gain, though I haven't 
 really thought hard about that...

It does have the significant advantage of eliminating the hard upper
bound on the range of time that can be present in a buffer (and with
'null' events, eliminates any such limit entirely, ala SMF).  More
annoying to work with though..

-DR-


___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-12-01 Thread Dave Robillard
On Fri, 2007-11-30 at 10:42 +, Krzysztof Foltman wrote:
 Dave Robillard wrote:
 
  Sigh.  In /this case/ they are the same, because the data directly
  follows
 
 Sort it out with gcc, not with me :)

The struct does not actually exist, its sizeof is irrelevant.

 And if you meant that event-buf is still a pointer, buf the value of
 event-buf will always be (buf)+1
[snip]

The data is at buf.  That's all.  The sole significance of that struct
member is that the data is at buf.  It doesn't matter in any way
whatsoever what that struct member is.  Honest.  ;)

Read the comment... the buffer format couldn't be more clear.

-DR-


___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-12-01 Thread Dave Robillard
On Fri, 2007-11-30 at 11:10 +, Krzysztof Foltman wrote:
 Dave Robillard wrote:
 
  MIDI.  In short: don't rock the boat; all this Jack/LV2 MIDI stuff is
  still getting off the ground...
 
 Well, I see your point. Again, I'll start worrying (or defining
 extensions) when it'll be necessary.
 
 Don't you think that there should be a sort of extension TODO list? As
 you see, I already have certain things in mind, and so do others.

If you really think it would make a difference to compile a list of what
people have in mind, go nuts.

 That's right. On the other hand, sometimes extension designed by some
 guy and then adopted because there was nothing better available, limits
 growth of the scene/market (there's enough resistance to a change to
 prevent better standards from being adopted).

True, but these things are generally discussed on the list anyway (as
they are right now).  If that does happen, you can just make something
better.

Generally, host authors won't support things they think are
stupid/short-sighted/whatever, so the problem takes care of itself for
the most part.

 Maybe all it lacks is a set of well-thought-out well-defined extensions
 to start things up?
 
 Or maybe the invisible hand of the scene will sort things out by itself.

You speak as if these two things are different, somehow? :)  The
invisible hand of the scene created all this...

Quite a bit of thought has gone into hypothetical extensions to make
sure the core spec is sound, but the complete independence of extensions
from the core spec is a fundamentally good thing.  Everything LV2 should
be tackled in terms of the smallest sub-problems possible (hence e.g. my
oppositing to cramming event definitions into the generic event
transport stuff).

Read the archives of this list (or, even better, the GMPI one..) enough
and it's pretty clear that's the only way we can actually get things
done 'round here... and, hey, because of it we're getting things done
around here right now.  We have working plugins, MIDI, dynamic
parameters, OSC, toolkit agnostic embeddable GUIs; we're soon getting
generic extensible events, control ramps, message-based stuff GMPI
has a few years worth of pointless bickering and arguing on a mailing
list archive somewhere.  QED.  Love or hate all this extensible talk
and RDF stuff, the proof is in the pudding.

I love it when things work out. :)
 
-DR-


___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-12-01 Thread Lars Luthman
On Sat, 2007-12-01 at 14:03 -0500, Dave Robillard wrote:
 We have working plugins, MIDI, dynamic
 parameters, OSC, toolkit agnostic embeddable GUIs;

Clarification: The GUI extension is toolkit agnostic, the GUIs are not.
Not that it matters to me.


--ll


signature.asc
Description: This is a digitally signed message part
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-12-01 Thread Krzysztof Foltman
Dave Robillard wrote:
 Read the comment... the buffer format couldn't be more clear.
   
That was the problem - the comment contradicted the code, but - as human 
language is usually more ambiguous than C code -  I assumed that the 
true intention is in the code, not in the comment.

Just to clear it up.

And as for fixed point timestamps - yes, I admit(ted) the fixed point is 
*usually* more PITA than floating point. But it all depends on context. 
I can't say fixed point is always bad, because for some things it's 
really good :) Say, wavetable oscillators - you can't really get good 
performance when you store sample position as floating point. Just try it :)

However, I'm not advocating for using fixed point numbers everywhere. 
Let me give a concrete example, so that you know *why* I'm so stubborn 
about this issue. Perhaps I'm making a wrong assumption here.

uint32_t optr = 0;
while(icount) {
  uint32_t timestamp = events[i].timestamp; // just saving on typing 
here :)
  uint32_t nsamples = (timestamp  16) - optr; // fixed point case
  uint32_t nsamples = fast_f2i(timestamp) - optr; // floating point case
  if (nsamples) {
process_samples(optr, nsamples); // buffer offset, nsamples
optr += nsamples;
  }
  float frac_pos = (timestamp  0x) * (1.0 / 65536.0); // fixed 
point case
  float frac_pos = timestamp - floor(timestamp); // floating point case
  process_event(events[i], frac_pos);
  i += (events[i].size + 7)~7;
}
process_samples(optr, output_size - optr);

This is how I imagine an event processing loop (main process function) 
in an average plugin. Note that there's not a lot of difference between 
fixed point and floating point (assuming we want fractional position as 
float number, which is a fair assumption, IMHO). However, floor is slow 
(though you need it only if you need fractional position). Float-to-int 
is slow, even if implemented via bit-manipulation trickery. Shift is 
fast. AND is fast. float*int is fast, at least faster than floor() :)

As you see, I'm not pushing on fixed point use everywhere. Just in that 
particular case, because - in my opinion - it's worth it. The loss of 
precision is pretty acceptable (1/65536th of a sample? that's 0,34 
nanosecond resolution with sr = 44100, pretty impressive in my opinion, 
I think DRAM access times are more than 0,34 nanoseconds, just to give 
you some point of reference :) ). The code is very similar, only a bit 
faster.

Come on, we're arguing about changing two lines of code here (with the 
rest - process_samples, process_event etc - being exactly the same!). 
Don't present it as if I wanted everyone to code thousands of lines of 
fixed point handling libraries. THAT would be both stupid and evil. I 
obviously don't want that.

I'd gladly sacrifice very large runs to not have to use the horribly 
inefficient things like float-to-int - and you don't really have to 
sacrifice them (just add a 65536 sample time period have pased event 
type). I think it's not premature optimization, it's more of not 
forcing everyone waste CPU cycles.

Krzysztof

___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-12-01 Thread Lars Luthman
On Sat, 2007-12-01 at 14:09 -0500, Dave Robillard wrote:
 On Fri, 2007-11-30 at 16:21 +0200, Nedko Arnaudov wrote:
  Krzysztof Foltman [EMAIL PROTECTED] writes:
  
   Lars Luthman wrote:
  
   non-standard hacks in a specification. But with the current event header
   proposal we don't have a pointer _or_ a flexible array member in it, so
   this discussion is sort of pointless.
  
   So, basically, we have a choice between:
  
   struct LV2_EVENT_HEADER_LLKF
   {
 uint32_t timestamp; // 16:16
 uint16_t payload_size;
 uint16_t event_type;
   };
 
 Might as well break the time stamp into two separate uint16_t's and make
 life easy.

Agreed. Most plugins won't care about the fractional part. The only
drawback I can think of is that on a platform that aligns struct members
to 32 bits you won't be able to load the complete timestamp as a
uint32_t without some shifting and |ing, but that will probably be a
special case anyway. Having the timestamp as two separate members makes
everything completely self-documented.


 Please, please let this silly 'type of the data member' angle of
 conversation die... :)
 
 Hereby humbly requesting that:
 
 // data follows here
 
 be the last thing in the event struct for the purposes of this
 conversation, since it's irrelevant and not a point of debate

Agreed.


--ll


signature.asc
Description: This is a digitally signed message part
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-12-01 Thread Dave Robillard
On Sat, 2007-12-01 at 20:13 +0100, Lars Luthman wrote:
 On Sat, 2007-12-01 at 14:03 -0500, Dave Robillard wrote:
  We have working plugins, MIDI, dynamic
  parameters, OSC, toolkit agnostic embeddable GUIs;
 
 Clarification: The GUI extension is toolkit agnostic, the GUIs are not.
 Not that it matters to me.

Ah, right.  I was debating even mentioning that bit :)

Has the world beyond IRC seen your videos?  You should post one for the
list maybe..

-DR-


___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-12-01 Thread Krzysztof Foltman
Krzysztof Foltman wrote:
   i += (events[i].size + 7)~7;
   
Oops, that should be:

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

:)

Krzysztof

___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-12-01 Thread Dave Robillard
On Sat, 2007-12-01 at 21:49 +0100, David Olofson wrote:
 On Saturday 01 December 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'm not sure about the scope of this LV2 event system, but the idea of 
 using timestamps related to anything other than audio time (ie 
 buffers, sample frames etc) seems to be a violation of the idea that 
 events are essentially structured control data or similar - ie 
 anything that's locked to the audio stream.

Obviously MIDI-like events to be handled in-band in the audio stream
would use frame time stamps, yes.

You can't do everything with in-band realtime events though... say,
firing around video frames in events for processing (not at all unheard
of in pd etc).  You can't be doing complex image processing in the audio
thread, that's idiotic.  ie yes this is a wider scope for events, but
it's necessary.

I'd rather not go on this digression to be honest, multi-context
plugins/patcher environments with events crossing contexts is not a
trivial subject.  The time stamps being up to the task would sure be
nice though...

All I ask for is a few measley bits :)  That I can point to widely
accepted standards (one of which is very, very close in domain to this
event stuff) that use timestamps of this sort is telling..

Anyway, making the frames part 16 bits screws up parity with Jack MIDI.
We already have a uint32_t frame timestamp.  We want fractional, so
stick a fractional part in there, voila.  The host just sets the
fractional part to 0 from Jack, things can use the fractional bit (or
not) as they please.

Simple.

-DR-


___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-12-01 Thread Dave Robillard
On Sat, 2007-12-01 at 22:19 +0100, David Olofson wrote:
 On Saturday 01 December 2007, Dave Robillard wrote:
 [...non audio time timestamps...]
  All I ask for is a few measley bits :)  That I can point to widely
  accepted standards (one of which is very, very close in domain to
  this event stuff) that use timestamps of this sort is telling..
 
 Sure, I have no problem with that. I just don't want to make sure 
 we're not confusing this with types of event communication that just 
 doesn't fit in the model of this particular event system. I mean, 
 it's kind of pointless to pollute *this* event system with features 
 that you need a completely separate LV2 extension to actually 
 use. :-) (Well, unless that other LV2 extension can use this one as a 
 transport layer in some sensible way, maybe.)

Understandable.  I'm thinking the events themselves can be the same
(they're so open-ended, why not..) but the transport mechanism would
just be different.  Some kind of one-event-at-a-time thing instead of a
big flat buffer.

There's also the sharing of transport layer and 'crossing' contexts,
yes.  The way I see it in both cases the generic event is just a time
stamp, size, and some data, so might as well make this one good enough.
Precise timing resolution never hurt anyone anyway.

  Anyway, making the frames part 16 bits screws up parity with Jack
  MIDI. We already have a uint32_t frame timestamp.  We want
  fractional, so stick a fractional part in there, voila.  The host
  just sets the fractional part to 0 from Jack, things can use the
  fractional bit (or not) as they please.
  
  Simple.
 
 Yes, that makes sense to me. It seems like the general case (even when 
 making use of sub-sample timing) favors separate integer and 
 fractional parts, and then, why not just use an int for each?

Yep.  Something ala:

struct LV2Event {
uint32_t frames;
uint32_t subframes;
foo_ttype;
uint32_t size;
// data follows here
};

Best choice for order and foo_t for alignment?  Making it smaller than
32 makes size's (and data) alignment suck, but 2^32 types of events at
one time is pretty nuts.

Cheers,

-DR-


___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-12-01 Thread Dave Robillard
On Sat, 2007-12-01 at 14:56 -0500, Dave Robillard wrote:
 No argument that it's faster.  With separate int fractional parts it's
 even probably cleaner.  I may be convinced...
 
 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.  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.
 
 Whether stamps are in frames or absolute time could be a property of the
 port.  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...
 
 (This may sound a bit esoteric, but to do something like Max right, you
 need absolute time stamps).
 
 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.
 
 Also, the frame part would be a uint32_t - equivalent to Jack MIDI
 timestamps, another win (and cutting out more conversion overhead).

Another thought on 32:32 fixed point with a 'timestamp type' concept:
tempo time.

You could use these stamps at beats:ticks time stamps with excellent
range/resolution.  Actually now that I think of it I've run into exactly
this problem in Ardour MIDI with floating point tempo-time-stamps.
32:32 stamps like this would be excellent in a sequencer, I would
definitely use them in Ardour.

With the same event struct we can get:

- Sub-sample accurate frame timestamps (Jack MIDI stamps + resolution)

- Absolute timestamps with sub-nanosecond resolution (OSC equivalent)

- Tempo relative timestamps with much higher resolution than any
existing MIDI/sequencer/etc gear I know of 

++

-DR-


___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-12-01 Thread Dave Robillard

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 

Re: [LAD] enhanced event port LV2 extension proposal

2007-12-01 Thread Dave Robillard

On Sun, 2007-12-02 at 00:15 +, Krzysztof Foltman wrote:
 Dave Robillard wrote:
  What is the point of having two separate event definitions when one will
  do for both, though?
 Perhaps, if we go 64-bit (although I still think it's overkill!) it 
 might make sense to make a timestamp a sort of an union, so some event 
 types will use one int64_t member (say, 200 picosecond units) instead of 
 integer+fractional? Just cosmetics.
 
 So we'd have something like:
 
 struct LV2_EVENT_HEADER {
   union {
 int64_t timestamp64; // for event streams that use one large number 
 as timestamp, like OSC???
 struct {
   int32_t timestamp;
   int32_t timestamp_fract;
 };
   };
   uint32_t type; // don't see any other choice but int, opaque pointer 
 won't fit on x86-64, plus, index is all we need, given a good URI 
 mapping mechanism
   uint32_t size;
 };

Guess we could.  I don't really want to mess up the struct, but
whatever.  The number of bytes is all that actually matters, some URI
somewhere will define what they are.  union can make things nicer, so
why not... not really relevant.

 With 16-byte granularity for payload (ie. size is rounded up to nearest 
 multiple of 16 to determine next header address). Or perhaps 8-byte, 
 winning some memory at cost of messier code.

I still don't see where you're getting all this messy code stuff.
Adding 8 to a pointer isn't any more or less messy than adding 16 to a
pointer.  Or 4, or 2, or 3, or 17, or whatever.  pointer + number. There
will surely be a macro to round any value up to whatever that number
should be.  Alignment is purely a performance issue.

  Why?  The cons are obvious, what are the pros?  A few bits?

 Using a small structure when a small structure is just fine.

Ignoring my 'extended' uses, halving the stamp size vs. Jack MIDI isn't
really fine.  Dealing with that properly would be a PITA (a real one,
not a 'adding a different number' one ;) )

 When you 
 have lots of events, this may be very important. In other situations, no 
 clear advantages of 8-byte struct over 16-byte.
  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.

 Well, let me try to rephrase it, because I sense a huge miscommunication 
 here.
 
 When payload is always aligned to header size (8 bytes in my case), the 
 loop can look just like this:
 
 for (size_t i = 0; i  count; i += (events[i].size+7)  3) {
// use events[i] here, cast to event type struct if needed
 }
 
 or (events[i].size+15)4 with 16 byte header

Yeah, because everyone is going to write the loop with (events[i].size
+7)  3 in it.  Geeze. :P

A bitshift versus an addition is hardly significant. 

 Short, simple, efficient.

, weird looking, insignificant anyway.

  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...

 So we end up with two-three event stream types, each using different 
 timing scheme. Not as bad as it sounds, certainly, because each of these 
 types will be used for different things.
 
 What I proposed was to use different event structure layout for those 
 event streams. As I said above, the differences between those streams 
 are so huge, that translation between 8-byte and 16-byte headers will be 
 the least of the problems :)

3 separate and incompatible extensions and event structs everyone has to
deal with so you can have a bit shift in a for loop and save a tiny
fraction of a nanosecond processing time per event...

  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 ;)

 2 structs, not 5. And the translation will have to be there anyway, 
 unless you expect sample-based plugins to read OSC-style timestamps.

Frankly if anyone knows this would be a PITA, it's me, and it would be a
PITA.  It would make the overall thing more complicated for no good
reason.  Ringbuffering events around and changing the time base and such
would be extremely annoying (not to mention significantly more expensive
due to all the copying from struct type A to struct type B) versus just
using the same struct everywhere.  Then you just change the time stamp
in place.  Easy, fast.

In apps that do have to do things like this the performance hit of
copying structs around is way, way more significant than a shift here vs
an add there - in both space and time.

  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. :)

 By saving 2 bytes, it saves 8-16 bytes. Magic, isn't it? :)

Only because of your excessive padding and irrational desire to apply
the  operator 

Re: [LAD] enhanced event port LV2 extension proposal

2007-12-01 Thread Krzysztof Foltman
Dave Robillard wrote:
 I still don't see where you're getting all this messy code stuff.
 Adding 8 to a pointer isn't any more or less messy than adding 16 to a
 pointer.
uint32_t *p = some_int_array[0];
p += 7;

Q: Where does p point now?
A: 28 bytes ahead of its previous value.

That's where the elegance-related problem lies (IMO).

If the struct size is 16, and you want to increase the pointer by 8 
bytes, you need to cast to char*, increase by 8, and cast back to 
LV2_EVENT_HEADER. That's what was (and is) bugging me.

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

is a bit nicer than:

  p = (LV2_EVENT_HDR *)((char *)p + ((p-size + 7) ~7));

to me. Still, it's just one line of code, and can be put inside of a 
macro or something, so the messiness might be perfectly bearable. I 
might also keep the current pointer as char * for easy incrementing, and 
cast to LV2_EVENT_HEADER * (or whatever) when needed.

Putting things in perspective, it's not even nearly as ugly as what goes 
on inside plugins' inner loops, so it might be perfectly acceptable ;)

Krzysztof

___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-12-01 Thread Dave Robillard
On Sun, 2007-12-02 at 01:26 +, Krzysztof Foltman wrote:
 Dave Robillard wrote:
  I still don't see where you're getting all this messy code stuff.
  Adding 8 to a pointer isn't any more or less messy than adding 16 to a
  pointer.
 uint32_t *p = some_int_array[0];
 p += 7;
 
 Q: Where does p point now?
 A: 28 bytes ahead of its previous value.

Congratulations, you can add and multiply. ?

 That's where the elegance-related problem lies (IMO).

heh.

 If the struct size is 16, and you want to increase the pointer by 8 
 bytes, you need to cast to char*, increase by 8, and cast back to 
 LV2_EVENT_HEADER. That's what was (and is) bugging me.
 
   i += (events[i].size+7)  3;
 
 is a bit nicer than:
 
   p = (LV2_EVENT_HDR *)((char *)p + ((p-size + 7) ~7));

Yeah, that or

p = (LV2_EVENT*)(p.data + PAD(p.size))

you have an unhealthy bit manipulation fetish or something :P

Anyway, I agree the alignment sucks.  Not for these... colourful
reasons, but because accessing things that aren't aligned is slow.

The real problem (relative to the old original events) is the type
field.  It doesn't need to be very large, so it takes up a little bit of
space and throws everything out of alignment regardless of whether we
choose 32 or 64 bit stamps.

struct LV2EventA {
uintn_t  frames; // good alignment
uintn_t  subframes; // good alignment
uint32_t size; // good alignment
uint8_t type; // bad alignment
// data // bad alignment
} // 9 or 13 bytes (ick) 

How do we fix that?  The only solution is to cram type into the space
taken up by size or subframes.  If I had to pick, I'd choose doing it to
size, but OSC blobs (among other things) have a 32 bit length so that
sucks a bit.  The max length if we use uint16_t is not even a meg

Taking over subframes space means tempo time wouldn't be sample
accurate, which is a show-stopper.  It's a big chunk for time, sure, but
time is the most important information, the rest is framework.

struct LV2EventB {
uintn_t frames;
uintn_t subframes;
uint16_t size;
uint16_t type;
// data (32-bit aligned)
} // 8 or 12 bytes

is the best so far IMO, but that's an awful lot of space wasted on type
which isn't even likely to be  10.

Is doing something really weird like 24 bytes for size and 8 bytes for
type worth it for the much nicer payload size limit (16 megs)?

Then again, UDP packet size (which OSC typically travels in) is
typically well within uint16_t's range, and if messages are actually
getting that big, they should probably be pointing at some shared
resource to avoid the potential copying.

All things considered LV2EventB with n=32 seems best to me..
 
-DR-

___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-30 Thread Lars Luthman
On Fri, 2007-11-30 at 10:42 +, Krzysztof Foltman wrote:
 In other words - just remove the pointer from the generic header, or
 replace it with buf[], a zero-length in-place array, as opposed to 4- or
 8-byte pointer - and nobody's hurt ;)

If you have a flexible array member in a struct that struct is an
incomplete type and you can not put it in an array, according to the C99
standard. Not to mention that flexible array members aren't even allowed
in C++. Yes, GCC allows it anyway unless you compile with -std=c99 (or
c++98) -pedantic-errors, but it still wouldn't be very nice to use
non-standard hacks in a specification. But with the current event header
proposal we don't have a pointer _or_ a flexible array member in it, so
this discussion is sort of pointless.


--ll


signature.asc
Description: This is a digitally signed message part
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-30 Thread Krzysztof Foltman
Dave Robillard wrote:

 Sigh.  In /this case/ they are the same, because the data directly
 follows

Sort it out with gcc, not with me :)

And if you meant that event-buf is still a pointer, buf the value of
event-buf will always be (buf)+1, then we will always have a pointer
dereference. Which is (slightly) less efficient and usually unnecessary.
If you define a type that passes large data, put the pointer in payload,
it will only have to be dereferenced for that particular event type.

And if you meant that it's usually (buf)+1 but not if data is large
then we also need to check if we need to skip the (possibly
non-existent) data block or not.

As in:

if (event-buf == (char *)(1 + event-buf))
{
  // data are in-place, skip then
  event += some_function_of(event-size);
}
else
{
  // data are somewhere else
  event += some_function_of(header_size);
}

In other words - just remove the pointer from the generic header, or
replace it with buf[], a zero-length in-place array, as opposed to 4- or
8-byte pointer - and nobody's hurt ;)

And by the way - maybe it would make sense to use some sort of
performance testing framework to check which event headers are faster
and how much impact does it really have?

If the difference on a gain plugin (or say, wave playback - to test
cache-intensive stuff) is within, say, 10%, with 256-sample buffers and
event density of 8 samples/event, then there's not much to argue about.

Krzysztof

___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-30 Thread Krzysztof Foltman
Nedko Arnaudov wrote:

 And supplying things to plugins that they should not (and do not) care
 about is not confusing? And we assume that plugins would be more than
 hosts after all...

Honestly, I prefer to have unnecessary information which I need to
ignore, than fields with context-dependent meaning. Context-dependent
meaning is usually more evil. Buffer header is not the place to
squeeze bits.

Krzysztof
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-30 Thread David Olofson
On Friday 30 November 2007, Krzysztof Foltman wrote:
[...several points that I totally agree with...]
 If you use integers, perhaps the timestamps should be stored as
 delta values. 

That would seem to add complexity with little gain, though I haven't 
really thought hard about that...

It seems more straightforward to just use sample frame offsets when 
sending; you just grab the loop counter/sample index. However, in the 
specific case of my instant dispath architechture, you'd need to 
look at the last event in the queue to calculate the delta - but then 
again, you need to touch that event anyway, to set the 'next' 
field... (Linked lists.) No showstopper issues either way, I think.

When receiving, OTOH, deltas would be brilliant! You'd just process 
events until you get one with a non-zero delta - and then you process 
the number of sample frames indicated by that delta. (Obviously, 
end-of-buffer stop condition must be dealt with somewhere. Adding a 
dummy stop event scheduled for right after the buffer would 
eliminate the per-audio-fragment check for fragment_frames  
remaining_buffer_frames.)


 Perhaps fractional parts could be just stored in events that demand
 fractional timing (ie. grain start event), removing that part from
 generic protocol.

That's another idea I might steal! ;-)

I'm not sure, but it seems that you'd normally not want to drive a 
sub-sample timestamped input from an integer timestamped output or 
vice versa. An output intended for generating grain timing would be 
concerned about generating events at the exact right times, whereas a 
normal control output would be value oriented.

This may not seem to matter much at first, but it makes all the 
difference in the world if you consider event processors. With pure 
values, you might want to add extra events or even regenerate the 
signal completely, but this would break down when controlling 
something that relies on event timing. Might be worth considering 
even in non modular synth environments, as you might want to edit 
these events with in sequencer. This is starting to sound like highly 
experimental stuff, though. :-)


 Perhaps we're still overlooking something.

I'd want to try actually implementing some different, sensible plugins 
using this before I really decide what makes sense and what doesn't. 
Granular synthesis is about the only application I can think of right 
now that *really* needs sub-sample accurate timing, so that's the 
scenario I'm considering, obviously - along with all the normal code 
that doesn't need or want to mess with anything below sample frames.


//David Olofson - Programmer, Composer, Open Source Advocate

.---  http://olofson.net - Games, SDL examples  ---.
|http://zeespace.net - 2.5D rendering engine   |
|   http://audiality.org - Music/audio engine  |
| http://eel.olofson.net - Real time scripting |
'--  http://www.reologica.se - Rheology instrumentation  --'
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-30 Thread Nedko Arnaudov
Lars Luthman [EMAIL PROTECTED] writes:

 According to the core spec, hosts are only required to pass the features
 to a plugin that the plugin lists as required in its RDF data. In
 practice many hosts will probably keep one static feature array with all
 the features they supports that they pass to every plugin instance but
 it's not necessary.

This is what zynjacku does, allocate list of all available host features
and then supply them to all plugins.

-- 
Nedko Arnaudov GnuPG KeyID: DE1716B0


pgpUmftcrlGj9.pgp
Description: PGP signature
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-30 Thread Krzysztof Foltman
Dave Robillard wrote:

 We could use float I guess to save a bit of space, but I definitely
 prefer floating point.  Fixed point is just a PITA, modern CPUs are much
 faster at FP anyway, why bother?

1. The modern CPUs are much faster at FP thing is a myth that shows up
here and there and is usually taken as a gospel by people who don't know
what they're doing (or what their CPU is doing). It depends. Sure,
implementing an IIR filter with 4:28 fixed point is not going to be
efficient, or even easy. That's one of many tasks where floating point
just works better.

But we were talking about comparing numbers or calculating an integer
difference (with fixed point, it's basically shift and subtract, with
floating point you have float-to-int conversion which is slow and
unelegant unless you use SSE-based conversion or tricks on IEEE
representation, which are not portable).

One could compare an integer loop index to a floating point event
timestamp instead of converting the timestamp to integer, but that would
mean that perhaps every inner loop would have to be written this way.
Bad idea, IMO.

2. With floating point, the precision of the fractional part decreases
with log2(sample_number). This is not going to be a practical problem,
but you're either wasting bits or losing precision here.

3. See: page C-24 in Intel® 64 and IA-32 Architectures Optimization
Reference Manual (keep in mind that the tables show latency/throughput
numbers for different CPUs, so compare apples with apples!),
instructions ADD/SUB vs FADD/FSUB. Intel doesn't seem to support your
claim that modern CPUs are much faster at floating point than at fixed
point (assuming same bit allocation) - certainly not for that particular
operation pair :)

And they will probably never be, because the complexity of adding two
floats is simply higher than of adding two integers (because one of the
mantissa values needs to be shifted and exponent has to be set properly).

Of course, it's not just ADD vs FADD. In the reality it's ADD+SHR vs
FADD+float to int conversion (or SUBSS+CVTSS2SI). Still, fixed point
seems to win.

4. I would agree that floating point numbers are usually much better for
representing rational numbers than fixed point numbers are. But
usually doesn't mean always. This particular situation is a textbook
example of where a fixed point values should be used!

Anyway, keep thinking. You already have three solutions to pick from
(floats, 16:16 fixed point, or an integer). If you use integers, perhaps
the timestamps should be stored as delta values. Perhaps fractional
parts could be just stored in events that demand fractional timing (ie.
grain start event), removing that part from generic protocol. Perhaps
we're still overlooking something.

Krzysztof

___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-29 Thread Krzysztof Foltman
Lars Luthman wrote:

 _Any_ structure that isn't just a dumb array of bytes will be unsafe to
 move between machines because of endianness.

A bridge can compare the architectures of the bridged machines, and
refuse to continue if they're different.

That kind of bridge could be written by a well trained chimpanzee and
work for (perhaps) majority of cases. Of course, to work for *all*
cases, the serialization would be needed.

Also, if the buffer is simple (as in: no pointers or handles
whatsoever), the serialization doesn't need to be implemented or invoked! :)


 struct Event_Port_Buffer {
   uint32_t capacity;// number of elements in the array
   uint32_t used_size;   // number of _used_ elements
   uint32_t event_count; // number of events (different from
 // used_size if there are large events -
 // would this really be needed?)
   struct Event* events; // an array allocated by the host
 };

I would argue for additional Event_Port_Buffer pointer, as in next.
This way, the host could allocate event buffers in (say) fixed-size
chunks, and the buffer is too full, another is allocated and linked to
previous one. What do you think?

 struct Event {
   uint32_t timestamp;
   uint16_t size;
   uint16_t event_type;
   uint8_t data[8];  // or a union or whatever, as long
 // as it's 8 bytes
 };

So we agree on that one.

 The host won't instantiate the plugin unless it knows how to handle
 event ports and MIDI events, and the plugin will fail to instantiate
 unless the host passes a URI - integer map to instantiate using a
 LV2_Feature with the URI http://lv2.example.com/uri-map and a
 NULL-terminated array of event type URIs as data.

How will it fail? (how will the host be notified about failure?) Is
there any way to communicate the reason for the failure to the user?

Just asking.

 The integer associated
 to each URI is simply the array index (my earlier suggestion was just a
 brain dump from a thought-in-progress, a simple array seems a lot
 cleaner).

A NULL-terminated array is good.

 Assuming that the host only supports MIDI events the data passed for
 this feature will be { http://lv2.example.com/midi-event-type;, NULL },
 the plugin will store the index 0 as the MIDI event identifier somewhere
 in its state, and everything is good to go. A basic loop for processing
 input events in a plugin could look something like this:

Looks good!

 handle_event(events[index]);
 index += 1 + (events[index].size - 8) / 16;

index += (events[index].size + 15)  4;

right?

 Should plugins have to list http://lv2.example.com/uri-map as a
 required feature, or should that be implicit whenever a plugin has an
 event port?

I guess, sometimes the event port isn't *required* to be connected?
Depends on a plugin, I guess. MIDI arpeggiator will need event support,
so will a synthesizer, but a reverb with MIDI support might do without
the event port support.

Krzysztof
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-29 Thread Krzysztof Foltman
Dave Robillard wrote:

 IP doesn't dictate packet contents whatsoever.  It does what it needs to
 do quite well, I don't think it's crufy at all.  It would be crufty if
 it tried to define, say HTTP error codes...

That's right. Lars addressed that criticism pretty well, I think. The
evolved proposal is both keeping headers and data in the same place
and keeping event semantics on separate layer from event transport.

 Please look at the definition of the LV2_MIDI struct in lv2-midiport.h.
 Note the char* parameter, and read it's comment.  The buffer is flat,
 there is no cache thrashing or any such issues here whatsoever.

Here it comes:

char*  buf;  /// raw event  data

Maybe you meant to write this?

char   buf[];   /// raw event data directly follow here

Because char* usually means, you know, a pointer, not a variable length
array :)

Take this, and solve alignment and URI numbering issues, and both
proposals (LarsLKF and yours) are actually the same one. Which is a
good thing.

 The only problem that needs to be handled is how to get the type in
 there.  I would like to find a good solution to this problem that's as
 extensible as URIs but doesn't actually stick a URI in the event struct
 (there are a few other future extensions that have the same problem.

Lars solved that one pretty well.

 strcmp of URIs in the audio thread is, as you say, completely out of the
 question, but so is handing out a flat numeric space.

Unless the handing out is done on the fly, based on URIs. Like, say,
file descriptors :) We still have central authority, but this time
it's the host loading the plugins, not a person. Should give a much
better roundtrip and less authority abuse ;)

Krzysztof

___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-29 Thread Lars Luthman
On Thu, 2007-11-29 at 05:59 +0200, Nedko Arnaudov wrote:
 Also, i doubt we need three count members in Event_Port_Buffer
 structure. used_size - number of used events is perfectly fine by
 itself. I dont see why plugin should know whether buffer is actually
 larger.

It needs to know that for an output buffer.


 Is midi event type semantics a broad or narrow one? I'd prefer narrow
 one, i.e. one type for note on/offs, one for pitch bend, and for midi
 cc, etc. Reasoning behind this is to indicate to user (informational) or
 maybe to host for runtime optimizations too, that only certain types of
 midi events will be actually processed. Read this as lv2zynadd does not
 respond to MIDI CC events (zynjacku however maps (will) those to actual
 parameter changes, through separate ports).

I'd prefer to just have one MIDI event type and pass the status bytes as
part of the event data. That way you can have generic MIDI processors or
channel filters or whatever without having to list every event type in
the RDF file.


--ll


signature.asc
Description: This is a digitally signed message part
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-29 Thread Lars Luthman
On Thu, 2007-11-29 at 09:19 +, Krzysztof Foltman wrote:
 Lars Luthman wrote:
  _Any_ structure that isn't just a dumb array of bytes will be unsafe to
  move between machines because of endianness.
 
 A bridge can compare the architectures of the bridged machines, and
 refuse to continue if they're different.
 
 That kind of bridge could be written by a well trained chimpanzee and
 work for (perhaps) majority of cases. Of course, to work for *all*
 cases, the serialization would be needed.

OK, maybe. It's trivial to add a safe RDF indicator in a separate
extension and just assume that an event type is not safe if it doesn't
have it.


  struct Event_Port_Buffer {
uint32_t capacity;// number of elements in the array
uint32_t used_size;   // number of _used_ elements
uint32_t event_count; // number of events (different from
  // used_size if there are large events -
  // would this really be needed?)
struct Event* events; // an array allocated by the host
  };
 
 I would argue for additional Event_Port_Buffer pointer, as in next.
 This way, the host could allocate event buffers in (say) fixed-size
 chunks, and the buffer is too full, another is allocated and linked to
 previous one. What do you think?

For that case I think it would be cleaner if the host just splits the
processing period in smaller parts if it needs to fit in more events per
time unit. The plugin doesn't need to worry about it.


  The host won't instantiate the plugin unless it knows how to handle
  event ports and MIDI events, and the plugin will fail to instantiate
  unless the host passes a URI - integer map to instantiate using a
  LV2_Feature with the URI http://lv2.example.com/uri-map and a
  NULL-terminated array of event type URIs as data.
 
 How will it fail? (how will the host be notified about failure?) Is
 there any way to communicate the reason for the failure to the user?

The same way the core spec says that a plugin should always fail to
instantiate when a required feature is missing - by returning NULL from
the instantiate() callback. There is no error message passing.


  handle_event(events[index]);
  index += 1 + (events[index].size - 8) / 16;
 
 index += (events[index].size + 15)  4;
 
 right?

No, that doesn't work. If the event size is 16 it will need to use the 8
free bytes in this event header and 8 bytes in the next one, so the
index needs to be increased by 2, but (16 + 15)  4 == 1.

And mine is wrong too. Embarassing. This works:

  index += (events[index].size + 23) / 16;


  Should plugins have to list http://lv2.example.com/uri-map as a
  required feature, or should that be implicit whenever a plugin has an
  event port?
 
 I guess, sometimes the event port isn't *required* to be connected?
 Depends on a plugin, I guess. MIDI arpeggiator will need event support,
 so will a synthesizer, but a reverb with MIDI support might do without
 the event port support.

Right, if the event port has the lv2:connectionOptional hint (from the
core spec) the host doesn't need to know about the event extension at
all. So I guess the cleanest way would be to not list the uri-map thing
as a separate lv2:Feature in the RDF data but require that a host that
handles events passes that LV2_Feature to the plugin's instantiate
callback if it is going to connect a non-NULL buffer to any event ports.


--ll


signature.asc
Description: This is a digitally signed message part
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-29 Thread Lars Luthman
On Thu, 2007-11-29 at 14:55 +0200, Nedko Arnaudov wrote:
 Lars Luthman [EMAIL PROTECTED] writes:
 
  On Thu, 2007-11-29 at 05:59 +0200, Nedko Arnaudov wrote:
  Also, i doubt we need three count members in Event_Port_Buffer
  structure. used_size - number of used events is perfectly fine by
  itself. I dont see why plugin should know whether buffer is actually
  larger.
 
  It needs to know that for an output buffer.
 
 Well, port is either input or output, why not use same variable/member
 (with appropriate naming)?

You could, but there isn't really much to gain from it. The host will
want to keep track of the buffer capacity in some way so those 4 bytes
have to go somewhere, and I think having the same variable mean
different things for input and output buffers makes things more
confusing.


--ll


signature.asc
Description: This is a digitally signed message part
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-29 Thread Lars Luthman
On Thu, 2007-11-29 at 13:56 +0100, Lars Luthman wrote:
 On Thu, 2007-11-29 at 09:19 +, Krzysztof Foltman wrote:
  Lars Luthman wrote:
   The host won't instantiate the plugin unless it knows how to handle
   event ports and MIDI events, and the plugin will fail to instantiate
   unless the host passes a URI - integer map to instantiate using a
   LV2_Feature with the URI http://lv2.example.com/uri-map and a
   NULL-terminated array of event type URIs as data.
  
  How will it fail? (how will the host be notified about failure?) Is
  there any way to communicate the reason for the failure to the user?
 
 The same way the core spec says that a plugin should always fail to
 instantiate when a required feature is missing - by returning NULL from
 the instantiate() callback. There is no error message passing.

...except that if all event ports are lv2:connectionOptional the plugin
should _not_ fail to instantiate.


--ll


signature.asc
Description: This is a digitally signed message part
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-29 Thread Krzysztof Foltman
Lars Luthman wrote:

 OK, maybe. It's trivial to add a safe RDF indicator in a separate
 extension and just assume that an event type is not safe if it doesn't
 have it.

Fair enough.

 For that case I think it would be cleaner if the host just splits the
 processing period in smaller parts if it needs to fit in more events per
 time unit. The plugin doesn't need to worry about it.

Yes. But that makes it impossible to use a fixed size buffer. If we
already have a fixed size buffer extension, why break it this way?

(note: I'm not saying that fixed size buffers are always a nice thing,
but let's think about it before it's too late)

 And mine is wrong too. Embarassing. This works:
   index += (events[index].size + 23) / 16;

Yes, that's the correct one. Mine would only be correct if 'size' meant
size of the whole event including 8-byte header, not the size of the
payload.

 all. So I guess the cleanest way would be to not list the uri-map thing
 as a separate lv2:Feature in the RDF data but require that a host that
 handles events passes that LV2_Feature to the plugin's instantiate
 callback if it is going to connect a non-NULL buffer to any event ports.

Why not use lv2:optionalFeature?

Krzysztof

___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-29 Thread Krzysztof Foltman
Lars Luthman wrote:

 Yes. But that makes it impossible to use a fixed size buffer. If we
 already have a fixed size buffer extension, why break it this way?
 I just don't like to add complexity to the port buffer struct. Sure,
 worrying about one extra pointer may seem silly, but it's yet another
 thing that the plugin needs to check. The simpler the better.

It's not just extra pointer, it's also extra outer loop in every plugin,
so the complexity is definitely there.

 A host doesn't necessarily have to allocate one fixed-size memory block
 for every plugin event port, it can use one large shared buffer and dole
 out portions of it to each input port in each period,

What about plugin-to-host communication, then? Before getting the events
from the host we set the capacity to maximum, and after the plugin
returns, we just reuse the part that wasn't used by the plugin for other
events?

 Why not use lv2:optionalFeature?
 Because it isn't really a separate optional feature, it depends on
 whether 1) all event ports have the lv2:connectionOptional hint and 2)
 the host doesn't plan to connect to any of those ports.

Are hosts forced to reveal all features that they implement for
instantiate call, or just the ones mentioned by the particular plugin in
RDF?

In theory, passing some features to a plugin despite if they use the
features or not, might require the host to create additional objects,
often unnecessarily.  That's not a huge problem though.

Krzysztof
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-29 Thread Krzysztof Foltman
Krzysztof Foltman wrote:

 What about plugin-to-host communication, then? Before getting the events
 from the host we set the capacity to maximum, and after the plugin

From the plugin, of course, not the host :)

In other words, the host sets capacity to max, calls the plugin, and
resets the capacity to size of data received.

Krzysztof

___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-29 Thread Lars Luthman
On Thu, 2007-11-29 at 14:03 +, Krzysztof Foltman wrote:
 Lars Luthman wrote:
  A host doesn't necessarily have to allocate one fixed-size memory block
  for every plugin event port, it can use one large shared buffer and dole
  out portions of it to each input port in each period,
 
 What about plugin-to-host communication, then? Before getting the events
 from the host we set the capacity to maximum, and after the plugin
 returns, we just reuse the part that wasn't used by the plugin for other
 events?

It's up to the host I suppose. If you pass the maximum capacity you get
maximum flexibility, but also risk that a greedy plugin fills your
entire buffer with 12412 MIDI CC's per audio frame. But at some point I
guess you just have to assume that plugin writers aren't going to be
maliciously stupid. =)


  Why not use lv2:optionalFeature?
  Because it isn't really a separate optional feature, it depends on
  whether 1) all event ports have the lv2:connectionOptional hint and 2)
  the host doesn't plan to connect to any of those ports.
 
 Are hosts forced to reveal all features that they implement for
 instantiate call, or just the ones mentioned by the particular plugin in
 RDF?

According to the core spec, hosts are only required to pass the features
to a plugin that the plugin lists as required in its RDF data. In
practice many hosts will probably keep one static feature array with all
the features they supports that they pass to every plugin instance but
it's not necessary.

If we decide that plugins with event ports do _not_ have to list the URI
map thing as an optional or required feature but still pass the
LV2_Feature struct to the plugin at instantiation that's OK too - that's
what extensions are for, extending and modifying the core spec.


--ll


signature.asc
Description: This is a digitally signed message part
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-29 Thread Krzysztof Foltman
Lars Luthman wrote:
 It's up to the host I suppose. If you pass the maximum capacity you get
 maximum flexibility, but also risk that a greedy plugin fills your
 entire buffer with 12412 MIDI CC's per audio frame. But at some point I
 guess you just have to assume that plugin writers aren't going to be
 maliciously stupid. =)
   
Judging from my Buzz experience, I *have* to assume that plugin writers 
aren't going to know what they're doing - like a certain plugin 
developer who couldn't get the basic pitch-to-Hz formula right for 
several years, and many others (myself included).

But, unfortunately, there's little one can do to remedy that. You could 
draft the specs in such a way that nobody with IQ under 170 could write 
plugins (DirectShow, I'm looking at you ;) ), but then you'd end up with 
no plugins.
 According to the core spec, hosts are only required to pass the features
 to a plugin that the plugin lists as required in its RDF data. 
Unless certain features will need passing personalized pointers to 
plugins (separate host's objects per plugin).

And by the way - seems that the char array/union part creates more 
controversies than necessary. So we may get back to Dave's idea of 
payload being a zero-length array (no minimum length), and to 8 bytes of 
alignment instead of 16. If LV2_EVENT_HEADER is defined this way:

struct LV2_EVENT_HEADER
{
  uint32_t timestamp; // still wondering if fractional addresses should 
be a part of generic even transport spec, by the way
  uint16_t event_type;
  uint16_t size; // of payload, with space occupied rounded up to nearest 8
};

it's practically as convenient to use as the previous version, and may 
be preferable in some cases (when bit 3 in payload size is 0).

Then we may define (as another extension, perhaps) a MIDI event like this:

struct LV2_MIDI_EVENT
{
  LV2_EVENT_HEADER hdr; // or use as a base class in C++
  uint8_t command, arg1, arg2, subchannel;
  uint8_t padding[4];
};

Or maybe instead of dedicating one byte to subchannel we might allow 
dynamic arbitrary assignment of extra fields (host passes an 
offset-and-length-to-struct-uri mapping). Well, maybe not.

Or other possibility (WARNING: bit squeezing paranoia ahead):

struct LV2_EVENT_HEADER // 4 bytes :)
{
  uint16_t timestamp; // no fractional timestamps here
  uint8_t event_type; // 256 events are enough for everybody
  uint8_t size; // 256 bytes are enough for everybody
};

struct LV2_MIDI_EVENT
{
  LV2_EVENT_HEADER hdr; // or use as a base class in C++
  uint8_t command, arg1, arg2, padding;
};

// separate event type for those 3 instruments with per-note control changes
struct LV2_MIDI_EVENT_SUBCHANNEL
{
  LV2_EVENT_HEADER hdr; // or use as a base class in C++
  uint8_t command, arg1, arg2, subchannel;
};

// separate event type for those 3 specific granular synthesis hosts and 
plugins
struct LV2_MIDI_EVENT_FRACTIONAL
{
  LV2_EVENT_HEADER hdr; // or use as a base class in C++
  uint8_t command, arg1, arg2, subsample;
};

(1/256 of a sample should be good enough for everybody, too!)

Krzysztof

___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-29 Thread Lars Luthman
On Thu, 2007-11-29 at 19:43 +, Krzysztof Foltman wrote:
 Lars Luthman wrote:
 And by the way - seems that the char array/union part creates more 
 controversies than necessary. So we may get back to Dave's idea of 
 payload being a zero-length array (no minimum length), and to 8 bytes of 
 alignment instead of 16. If LV2_EVENT_HEADER is defined this way:
 
 struct LV2_EVENT_HEADER
 {
   uint32_t timestamp; // still wondering if fractional addresses should 
 be a part of generic even transport spec, by the way
   uint16_t event_type;
   uint16_t size; // of payload, with space occupied rounded up to nearest 8
 };

Sure, that's fine by me. It has the added benefit that you can have 0
byte events where only the event type carries any meaning (though that
may not be much of a benefit).


 Then we may define (as another extension, perhaps) a MIDI event like this:

Another extension, yes. =)


--ll


signature.asc
Description: This is a digitally signed message part
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-29 Thread Dave Robillard
On Wed, 2007-11-28 at 17:19 +0100, Lars Luthman wrote:
 On Wed, 2007-11-28 at 15:56 +, Krzysztof Foltman wrote:
  Serialization is necessary because large events can potentially refer
  to some foreign objects, like handles to OpenGL textures in video
  memory and what not :) You cannot assume that all of your large event
  data will be conveniently placed in a single contiguous buffer in RAM,
  because it might not be the most practical way of dealing with them.
 
 No argument with any of this. Passing around reference counted opaque
 objects can certainly be useful and I can imagine lots of sexy
 applications, I just don't think it needs to be in the event transport
 specification when it works just as well outside it.

++

Extensions should be kept as small and limited in scope as possible.
Do one thing, and do it well...

-DR-


___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-29 Thread Dave Robillard

On Thu, 2007-11-29 at 12:55 +, Krzysztof Foltman wrote:
 Lars Luthman wrote:
 
  I'd prefer to just have one MIDI event type and pass the status bytes as
  part of the event data. That way you can have generic MIDI processors or
  channel filters or whatever without having to list every event type in
  the RDF file.
 
 Yes. MIDI Implementation Chart LV2 extension, anyone? ;)
 
 In fact, MIDI Map extension serves exactly that purpose - however, it
 only deals with CC, not other messages.
 
 A totally unrelated note: static RDF files in LV2 might be fine for now,
 but sometimes I'd like to generate the same kind of metadata on the fly.
 Think dynamic parameters, dynamic event types, editable CC maps...
 
 Nedko has tried to solve the first problem by his dynamic parameters
 extension, but I guess that a general solution could be better, because
 the same problem he had with params, is practically guaranteed to appear
 everywhere else.
 
 Think of plugin standard adapters (VST-to-LV2) and the like. Or any
 adapters, bridges and what not. Or plugin-side MIDI learn which sends
 controller information via dynamic CC map.
 
 Any thoughts how to attack that problem? A function to send an updated
 RDF to the host? A function to send incremental information?

We will want that eventually, but it's officially Hard(TM) :)

 Oh, and by the way - Nedko has mentioned that a *host* may want to send
 updates of URI number allocations - how are we going to solve that?
 
 I suppose a host object with a function to subscribe/unsubscribe
 URI-number allocation update information could be a way to go - a
 classic Observer pattern. A plugin that doesn't make use of it would
 just ignore unknown event types in the event buffer, which is fine, as
 long as the only URIs that may appear in updates are new URIs (there are
 no reassignments or deletions).

Dynamic URI-int mapping is probably a good thing.  Raises issues
though - maybe an acceptable compromise is that the existing ones never
change, but ones can be added?  Really no reason an already designated
number needs to change URIs that I can think of, just tack new ones on
the end.

-DR-


___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-29 Thread Dave Robillard

On Thu, 2007-11-29 at 05:59 +0200, Nedko Arnaudov wrote:
 Lars Luthman [EMAIL PROTECTED] writes:
 
  struct Event_Port_Buffer {
uint32_t capacity;// number of elements in the array
uint32_t used_size;   // number of _used_ elements
uint32_t event_count; // number of events (different from
  // used_size if there are large events -
  // would this really be needed?)
struct Event* events; // an array allocated by the host
  };
 
  struct Event {
uint32_t timestamp;
uint16_t size;
uint16_t event_type;
uint8_t data[8];  // or a union or whatever, as long
  // as it's 8 bytes
  };
 
 snip
 
  Should plugins have to list http://lv2.example.com/uri-map as a
  required feature, or should that be implicit whenever a plugin has an
  event port? Both methods have some drawbacks - if plugins are required
  to list it there is some redundancy, if they are not we have a required
  feature that isn't listed as one which can be a bit confusing.
 
 I think uri-map feature should be part of event extension itself. what
 would be use without it?

Shared data structures?  Maybe even things inside events themselves (ie
the type of various message arguments).

I think a URI-int mapping mechanism will probably be very useful in
several places, since it's  the only way of getting URI extensibility
with DSP appropriate performance.  Doesn't hurt to keep it separate
anyway, it's not really event specific at all.

-DR-


___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-29 Thread Dave Robillard

On Thu, 2007-11-29 at 13:25 +0100, Lars Luthman wrote:
 On Thu, 2007-11-29 at 05:59 +0200, Nedko Arnaudov wrote:
  Also, i doubt we need three count members in Event_Port_Buffer
  structure. used_size - number of used events is perfectly fine by
  itself. I dont see why plugin should know whether buffer is actually
  larger.
 
 It needs to know that for an output buffer.
 
 
  Is midi event type semantics a broad or narrow one? I'd prefer narrow
  one, i.e. one type for note on/offs, one for pitch bend, and for midi
  cc, etc. Reasoning behind this is to indicate to user (informational) or
  maybe to host for runtime optimizations too, that only certain types of
  midi events will be actually processed. Read this as lv2zynadd does not
  respond to MIDI CC events (zynjacku however maps (will) those to actual
  parameter changes, through separate ports).
 
 I'd prefer to just have one MIDI event type and pass the status bytes as
 part of the event data. That way you can have generic MIDI processors or
 channel filters or whatever without having to list every event type in
 the RDF file.

++

Event extension should keep it hands out of event contents entirely.
MIDI is already well-defined.

-DR-



___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-29 Thread Krzysztof Foltman
Dave Robillard wrote:
 We will want that eventually, but it's officially Hard(TM) :)
   
No doubt it is. But it's the result of your own choice, so better don't 
complain too much ;)
 Dynamic URI-int mapping is probably a good thing.  Raises issues
 though - maybe an acceptable compromise is that the existing ones never
 change, but ones can be added?
Look at the part you've just quoted (or see below)

 as long as the only URIs that may appear in updates are new URIs (there are
 no reassignments or deletions).


No reassignments or deletions. Just add, no change/remove.

But, actually, I can see some purpose for deletion - when a host stops 
supporting some event type coming out of a plugin. Which tells me we've 
concentrated too much on host-to-plugin direction, and not enough on 
plugin-to-host or plugin-to-plugin (basically: communicating what event 
types are actually *wanted* on an event output port!)

But, worst case is that host would have to ignore the event types that 
are not valid anymore. It would be inefficient for the plugins, sure. 
But somehow, I don't see anyone will care. Not with current temperatures 
in hell.

Krzysztof

___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-29 Thread Krzysztof Foltman
Dave Robillard wrote:
 I /really/ don't like screwing around with MIDI.  Just make the events
 pure, raw MIDI.  Jack MIDI events are 'just n bytes of MIDI', Alsa has
 functions to get at 'just n bytes of MIDI', and... well, it's just MIDI.
   
However, it also has its own age. And limitations. In particular, the 
amount of per-note control is pitiful.

I can always use hacks to get around the limitations, or introduce a 
per-note control via separate set note parameter event type. But hacks 
are ... hacky, and the extended extension of extension for every single 
feature is a bit inelegant too.

Anyway - so far, I have no code that would make use of this, so we might 
keep it as plain MIDI. And then we have next 5 years to decide the 
details of the feature. In the meantime, maybe the MIDI guys will decide 
for us :D

Krzysztof

___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-29 Thread Dave Robillard
On Fri, 2007-11-30 at 00:23 +, Krzysztof Foltman wrote:
 Dave Robillard wrote:
  Because char* usually means, you know, a pointer, not a variable length
  array :)
  
   char buf[] is, you know, equivalent to char* buf.  You do know C,
  yes? ;)

 You *do* know C, yes? Well enough to judge others?
 
 Hint: try this little proggy (gcc should compile it fine):
 
 #include stdio.h
 int main(int argc, char *argv[])
 {
   struct X
   {
 int a;
 char buf[];
   };
   struct Y
   {
 int a;
 char *buf;
   };
 
   printf(%d %d\n, sizeof(struct X), sizeof(struct Y));
 }

Sigh.  In /this case/ they are the same, because the data directly
follows (the char* member doesn't even really have to be there, it's
just convenient. It could literally be just 'char', for example).  The
data always did directly follow, and this has all been working just fine
for ages now.  You just didn't bother to understand the existing LV2
MIDI before trying to extend it, and an awful lot of pointless ranting
about cache and optimisation or whatever was the result.   

Touche, smartass :P

-DR-

___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-29 Thread Dave Robillard

On Thu, 2007-11-29 at 19:43 +, Krzysztof Foltman wrote:
 Lars Luthman wrote:
  It's up to the host I suppose. If you pass the maximum capacity you get
  maximum flexibility, but also risk that a greedy plugin fills your
  entire buffer with 12412 MIDI CC's per audio frame. But at some point I
  guess you just have to assume that plugin writers aren't going to be
  maliciously stupid. =)

 Judging from my Buzz experience, I *have* to assume that plugin writers 
 aren't going to know what they're doing - like a certain plugin 
 developer who couldn't get the basic pitch-to-Hz formula right for 
 several years, and many others (myself included).
 
 But, unfortunately, there's little one can do to remedy that. You could 
 draft the specs in such a way that nobody with IQ under 170 could write 
 plugins (DirectShow, I'm looking at you ;) ), but then you'd end up with 
 no plugins.
  According to the core spec, hosts are only required to pass the features
  to a plugin that the plugin lists as required in its RDF data. 
 Unless certain features will need passing personalized pointers to 
 plugins (separate host's objects per plugin).
 
 And by the way - seems that the char array/union part creates more 
 controversies than necessary. So we may get back to Dave's idea of 
 payload being a zero-length array (no minimum length), and to 8 bytes of 
 alignment instead of 16. If LV2_EVENT_HEADER is defined this way:
 
 struct LV2_EVENT_HEADER
 {
   uint32_t timestamp; // still wondering if fractional addresses should 
 be a part of generic even transport spec, by the way
   uint16_t event_type;
   uint16_t size; // of payload, with space occupied rounded up to nearest 8
 };

++

FWIW OSC  (and by extension, my LV2 OSC stuff) does this too, except
with 4 bytes instead of 8.

 Then we may define (as another extension, perhaps) a MIDI event like this:
 
 struct LV2_MIDI_EVENT
 {
   LV2_EVENT_HEADER hdr; // or use as a base class in C++
   uint8_t command, arg1, arg2, subchannel;
   uint8_t padding[4];
 };

I /really/ don't like screwing around with MIDI.  Just make the events
pure, raw MIDI.  Jack MIDI events are 'just n bytes of MIDI', Alsa has
functions to get at 'just n bytes of MIDI', and... well, it's just MIDI.

Everyone knows MIDI, it's probably the most ubiquitous audio standard in
existence.  Keeping our hands  out of it means trivial interoperability
with everything: past, present, and  future.   We should just leave it
be.

It's working this way in Jack right now, it's working this way in LV2
right now.  If it ain't broke

-DR-


___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-29 Thread Dave Robillard
On Thu, 2007-11-29 at 01:49 +0100, David Olofson wrote:
 On Thursday 29 November 2007, Dave Robillard wrote:
 [...]
  Well, sure, but big data is big data. In the typical case plugin
  buffers are much smaller than the cache
 [...]
 
 Of course, but that's exactly what I'm talking about - large buffers, 
 and why it doesn't make sense to support them. :-)

It makes a lot less sense to explicitly deny them for no particular
reason.

You can't use events larger than x bytes

Why?  Because some Dave or another said it could possibly be slow in
certain cases?  Sure, there's a performance hit running on really
massive buffers.  There's a performance hit running on tiny buffers too.
So what?

There are times when running on single sample buffers is  what you want
to do, even though it's slow.  There are other times when running on
massive buffers is what you want to do, even though it's slow.  If you
don't want to do that, well... don't do that.  Currently the only limit
on sizes of things in LV2 is the range of uint32_t, and this is a Good
Thing.

Not explicitly making things verboten != supporting

I do agree we should not be adding crufty features to support massive
buffers, if that's what you mean.  It's easier to just split the cycle
anyway.

 Last time I looked into this, a reasonably optimized resampler with 
 cubic interpolation and some ramped parameters was memory bound even 
 on a lowly P-III CPU, at least with integer processing. (Haven't 
 actually tested this on my AMD64...)
 
 I think floating point should be as fast or faster in most cases, at 
 least on P-III CPUs and better - and with SIMD, you may get another 
 2x-4x higher throughput at that.

A clever host can just use the same, say, 2 buffers (stereo audio), so
running a bunch of plugins on it will be in the cache the entire time.
Ardour, for example, (usually) runs the entire route's chain of plugins
on the same buffers in-place.  For any reasonable Jack buffer size on
any reasonable modern CPU, those buffers are going to be in the cache
for the duration of that entire chain's processing.  For non-in-place
chains, add a factor of 2 (and it's still going to all fit in cache in
many cases).

In other places, that's not the case.  Point being this is the host
author's - not the plugin specification's - business.

-DR-


___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-29 Thread Dave Robillard

On Fri, 2007-11-30 at 00:30 +, Krzysztof Foltman wrote:
 Dave Robillard wrote:
  I /really/ don't like screwing around with MIDI.  Just make the events
  pure, raw MIDI.  Jack MIDI events are 'just n bytes of MIDI', Alsa has
  functions to get at 'just n bytes of MIDI', and... well, it's just MIDI.

 However, it also has its own age. And limitations. In particular, the 
 amount of per-note control is pitiful.

Definitely.  This is why event type agnostic event ports are a good
thing.  You're free to make a better MIDI if you want (I'd say use OSC
and leave MIDI on the trash pile of computing history where it belongs,
but that's just me), but the normal MIDI events need to be plain old
MIDI.  In short: don't rock the boat; all this Jack/LV2 MIDI stuff is
still getting off the ground...

 I can always use hacks to get around the limitations, or introduce a 
 per-note control via separate set note parameter event type. But hacks 
 are ... hacky, and the extended extension of extension for every single 
 feature is a bit inelegant too.

No it isn't, it's extremely elegant.  What's inelegant is cramming too
much garbage into an extension when that garbage is a separate problem.

You want to define a new event type?  Define it!  No consensus, no
debates, no fuss, no muss.  You can get the whole thing working and
implement it in a host and plugins both before even telling anyone about
it at all (if you want), and /nothing breaks/.  Your plugins can even be
run in another host that doesn't even know what the heck these
events/ports even are, and everything will work fine (except, of
course, those ports/events).

If that's not elegant, I don't know what is ;)

-DR-

___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-29 Thread Dave Robillard

On Fri, 2007-11-30 at 03:15 +0100, David Olofson wrote:
 On Friday 30 November 2007, Dave Robillard wrote:
 [...]
  I do agree we should not be adding crufty features to support
  massive buffers, if that's what you mean.  It's easier to just split
  the cycle anyway.
 
 Yes, that's exactly what I mean. Sure, one *could* have a use for 
 really huge buffers (say, running large FFTs without intermediate 
 buffering), but to me, that seems too far out that one should have 
 everyone deal with 32:32 event timestamps for that reason alone.

The current version of LV2 MIDI just uses double.  All the precision you
could ask for, or an insane range if you'd prefer.  It's a bit big
maybe, but hey, why not?

We could use float I guess to save a bit of space, but I definitely
prefer floating point.  Fixed point is just a PITA, modern CPUs are much
faster at FP anyway, why bother?

-DR-


___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-29 Thread Dave Robillard

On Fri, 2007-11-30 at 02:39 +0100, David Olofson wrote:
 On Friday 30 November 2007, Dave Robillard wrote:
   That's why I'm using a Port as the smallest connection unit,
   much like LADSPA ports, so there is no need for an event type
   field of any kind at all, let alone a URI.
  
  Ports /are/ the smallest connection unit.  But ports can /contain/
  events, and if we want multiple kinds of events in a single port,
  then the events themselves need a type field.
 
 Sounds like there's a fundamental difference there, then. I'm using a 
 model where a port is nothing more than something that deals with a 
 value of some sort. There are no channels, voices, different events 
 or anything inside a port - just a value. An output port 
 can operate that value of a compatible input port.

LV2 ports can contain /anything/.  It's a void*, completely 100% opaque
in every way.  There might be 'channels' or 'voices' or a 'value' or
whatever in there, it's just data.

   The data in the events *could* be MIDI or whatever (the host
   doesn't even have to understand any of it), but normally, in the
   case of Audiality 2, it'll be modular synth style ramped control
   events. That is, one port controls exactly one value - just like
   in LADSPA, only using timestamped events with ramping info instead
   of one value per buffer.
  
  The host might not have to (though in practise it usually does), but 
  other plugins certainly do.  You can't process events if you don't
  even know what they are.
 
 Yes, obviously. I don't quite see what you think I'm trying to say 
 here. :-)
[snip]

Me neither :)

There are of course infinite ways to do 'events' for plugins (and an
infinite number of interpretations of what 'events' means).  Nice thing
about LV2 is you can do them all.  Something like your non-flat event
stuff (with queueing and linked lists and dispatching and such, rather
than plain old directly connected buffers) may find a place in LV2 as
well - may have to for certain message-based (ahem) programming
modular stuff ala Max.  What we have now is the sample accurate hard
realtime sort of 'events' (ala Jack MIDI).

Havn't quite figured out the bridging of those two worlds yet

-DR-


___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-28 Thread Steve Harris

On 28 Nov 2007, at 00:05, Marc-Olivier Barre wrote:

 On Nov 27, 2007 11:24 PM, Dave Robillard  
 [EMAIL PROTECTED] wrote:
 I have said this a lot, and I will continue saying it more until  
 the end
 of time because it's important: the fact that ports can
 contain /anything/ is the fundamental core idea behind LV2, and  
 it's a
 good one.  A good generic event extension must do this as well.

 Dave, I love it when you go crazy over a piece of spec. Just don't
 change anything :-)

 And for what it's worth, I agree with you on most parts...

Yeah, right - no big steps backwards please.

- Steve
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-28 Thread Lars Luthman
On Wed, 2007-11-28 at 10:47 +, Krzysztof Foltman wrote:
 I already gave you one example how it can be handled beyond what SysEx
 offers (by using interfaces). And another (by binding command numbers to
 URIs, preferably on plugin load). Read my previous mail more carefully.

Using a number - URI mapping host feature is a good idea. With one byte
for the event type in each event header you get 256 different types per
plugin instance which is probably more than enough. With two bytes you
get 65536 different types per plugin instance which is certainly more
than enough. It's not really an argument against having a completely
generic event transport though.


 As I said, you didn't even provide any way to transfer the ownership of
 the buffer to the plugin, so that it doesn't have to copy it.

Actually he did. Just pass a pointer and a byte size in the buffer and
type it with the URI http://this.buffer.is.yours.dude/ .


 Anyway... Let's try to LV2ize my proposal, just as some starting point:
 
 struct LV2_EVENT_HEADER
 {
   uint32_t timestamp; // timestamp
   uint8_t event_type; // event type number
   uint8_t args[3];// short-form arguments or padding
 };
 
 Event types are defined by the plugin like this:
 
 @prefix ep: http://foltman.com/lv2/ep .
 http://someevent ep:eventType [
   ep:eventNumber 128 ;
   ep:eventName CH1:Note off ;
   ep:eventData ep:shortData ;
   ep:eventContent
 http://www.midi.org/about-midi/specshome.shtml#ch1-noteoff; ;
 ].

I'd prefer to have the host define the URI - number mappings itself so
it doesn't have to remap them for every different plugin it has loaded,
e.g. the plugin requires a host feature for every event type it uses
(http://lv2.example.com/midi-event, http://lv2.example.com/osc-event
etc) so the host knows which events it needs to be able to handle (and
can refuse to load the plugin if it doesn't recognise an event type),
and then passes a pointer to something like this to instantiate() for
the host feature http://lv2.example.com/event-uri-map :

struct {
  uint32_t num_mappings;
  struct uri2num* mappings;
};

where uri2num is defined as

struct uri2num {
  const char* event_type_uri;
  uint16_t event_type_number;
};

I'd also prefer to have a single event type for MIDI and have the status
byte as part of the event data instead of having one event type for each
MIDI message type (note on, note off, aftertouch, what have you).

Also, in your proposal a single event type always has to have the same
size and there is no way to say that an event is smaller than 3 bytes
without possibly using the longData thing. I'd really prefer to have the
event size explicitly in the event header. Something like this:

struct LV2_EVENT_HEADER {
  uint32_t timestamp; // timestamp
  uint32_t size;  // event size
  uint8_t event_type; // event type number
  uint8_t data[7];// event data
};

The port buffer could contain a pointer to an array of these, and if
size  7 the subsequent array element is used to store data, if it's
larger then 7 + 16 the one after that is also used to store data etc.

This means that each event will need at least 16 bytes instead of 8, but
I don't think that's a huge loss. If we really wanted to we could make
the data array 3 bytes instead - would a 12 byte alignment be OK on all
platforms?

Another thing I've thought about since your earlier mails is the
timestamp. I think I agree that fixed point is better than floating
point (assuming that we want subsample precision) but I'd prefer 32.32
to 16.16. 16.16 would effectively limit the audio buffer size to 65536
samples since you can't address events in buffers larger than that. It's
not a huge practical problem to have to break your processing up in 1/3
second blocks at 192kHz, but it is a bit inelegant when the core spec
allows for 2^32 samples per buffer (~6 hour blocks at 192kHz). With a
32.32 fixed point timestamp the event struct could look like this:

struct LV2_EVENT_HEADER {
  uint32_t timestamp_int; // timestamp, integer part
  uint32_t timestamp_frc; // timestamp, fractional part (probably 
  // ignored by almost everyone)
  uint32_t size;  // event size
  uint8_t event_type; // event type number
  uint8_t data[3];// event data
};

which would be 16 bytes per event with size = 3.


--ll


signature.asc
Description: This is a digitally signed message part
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-28 Thread Krzysztof Foltman
Lars Luthman wrote:

 Using a number - URI mapping host feature is a good idea. With one byte
 for the event type in each event header you get 256 different types per
 plugin instance which is probably more than enough. With two bytes you
 get 65536 different types per plugin instance which is certainly more
 than enough. It's not really an argument against having a completely
 generic event transport though.

256 types is more than enough, in my opinion. Especially if MIDI takes
just 1 type, not 128 :)

 As I said, you didn't even provide any way to transfer the ownership of
 the buffer to the plugin, so that it doesn't have to copy it.
 Actually he did. Just pass a pointer and a byte size in the buffer and
 type it with the URI http://this.buffer.is.yours.dude/ .

How does the host know if the buffer has or has not been acquired
(owned) by the plugin? With my approach, a plugin can either ignore data
completely, or copy it into safe place, or increase reference count so
that host doesn't free it until plugin has finished with it.

 I'd prefer to have the host define the URI - number mappings itself so
 it doesn't have to remap them for every different plugin it has loaded,

It surely is a potential problem. While remapping can be really trivial,
it's not efficient and perhaps should be avoided.

On the other hand, how often do we send exactly the *same* event buffer
to different plugins (think Set Parameter messages!)? Is that a typical
or untypical case? What are example scenarios where that problem might
arise?

But, if we put whole MIDI stuff into a single event type, I'm fine with
host-assigned numbers (which would be given to plugin on instantiation).

 etc) so the host knows which events it needs to be able to handle (and
 can refuse to load the plugin if it doesn't recognise an event type),

Actually, a correct behaviour for the host would be to ignore the fact
that plugin handles some events that host doesn't. The fact that plugin
supports - say - video, doesn't mean that host must have anything to do
with that video.

It's a bit different if we're talking abot plugin's _output_ buffer
here, but I guess there can be a way to make a plugin not send unwanted
event types. Or to skip unrecognized event types.

 I'd also prefer to have a single event type for MIDI and have the status
 byte as part of the event data instead of having one event type for each
 MIDI message type (note on, note off, aftertouch, what have you).

We might. But then we lose generality and reserve a huge block of event
identifiers for an outdated crappy standard ;) Who uses polyphonic
aftertouch these days, anyway? :)

I thought of, at least, type ranges (like, 0x80-0x8F is note off
ch1..ch16). That might reduce RDF bloat, but don't know what others will
think about it.

Anyway, single event type for MIDI is OK for me.

 Also, in your proposal a single event type always has to have the same
 size and there is no way to say that an event is smaller than 3 bytes
 without possibly using the longData thing.

Losing those 2 bytes on 1-byte events is really acceptable to me :) We
need padding anyway, don't we?

To clarify the issue: shortData means that the event data may be up to 3
bytes long, not that it must be 3 bytes. In case it's less than 3 bytes,
the remaining bytes are used for padding/alignment.

But, anyway, the shortData/mediumData thing in my proposal could have
been done in a much better way (see below!).

 I'd really prefer to have the
 event size explicitly in the event header. Something like this:
 
 struct LV2_EVENT_HEADER {
   uint32_t timestamp; // timestamp
   uint32_t size;  // event size
   uint8_t event_type; // event type number
   uint8_t data[7];// event data
 };

A small modification: what about

struct LV2_EVENT_HEADER {
  uint32_t timestamp;
  uint16_t size;
  uint16_t event_type;
  union {
uint8_t data[8];
float dataf[2];
int32_t datai[2];
IDataBuffer *ptr;
  }
};

We don't need 65535 bytes for size, because copying THAT large blocks
in processing thread (no matter if host or plugin does it) is a bad
idea, just pass a pointer/object! 8 bytes of data is better than 7
bytes, because you can fit a 64-bit pointer there (on 64-bit machines).
Or an int32_t and a float (set parameter event).

I'm *slightly* against the size field, because it is another value that
must be inspected in event processing loop, even with trivial events
like MIDI.

But it's not worth arguing, I'm fine with keeping size there. 12 bytes
to inspect+4 to skip for average MIDI event is already slightly better
than Dave's 16 bytes + 3 bytes on the side. And memory management gets
easier. Everybody wins :)

 The port buffer could contain a pointer to an array of these, and if
 size  7 the subsequent array element is used to store data, if it's
 larger then 7 + 16 the one after that is also used to store data etc.

So you've basically improved the mediumData thing and merged it with
smallData, by introducing size 

Re: [LAD] enhanced event port LV2 extension proposal

2007-11-28 Thread David Olofson
On Wednesday 28 November 2007, Krzysztof Foltman wrote:
[...]
 I don't think it's a serious problem. Huge processing buffers are
 not very useful in practice.
[...]

Actually, they're directly harmful most of the time!

For any graph with more than one plugin, and with plugins that use 
internal buffers of the I/O buffer size, large buffers means you'll 
get a gigantic cache footprint. It gets worse in high latency real 
time situations (games, media players etc), where you have other 
threads fighting for the cache as well.

Obviously, this effect is less visible with non-trivial plugins - but 
even how many plugins in a normal graph are actually CPU bound? In 
my experience, the effect is very pronounced (several times higher 
CPU load with 512 samples/buffer than with 32) when using a bunch of 
sampleplayer voices (cubic interpolation + oversampling) and some 
simple effects. You have to do some pretty serious processing to go 
CPU bound on a modern PC...


//David Olofson - Programmer, Composer, Open Source Advocate

.---  http://olofson.net - Games, SDL examples  ---.
|http://zeespace.net - 2.5D rendering engine   |
|   http://audiality.org - Music/audio engine  |
| http://eel.olofson.net - Real time scripting |
'--  http://www.reologica.se - Rheology instrumentation  --'
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-28 Thread David Olofson
On Wednesday 28 November 2007, Krzysztof Foltman wrote:
[...]
 - or introducing a 65536 samples milestone kind of event similar
 to clear message in LZ compression format, separating events from
 different 65536-sample eras :)

Why would you need to do this? Timestamps in Audiality 0.1.x are 16 
bit and based on a continuously running, wrapping timer. Audiality 2, 
VST, DSSI and others use offsets from the first sample in the current 
buffer. Either way works just fine as long as the timestamps cover 
the buffers safely.

Now, this is assuming that we consider events real time data, just 
like audio. That is, plugins are not allowed to send events for 
future buffers, and they'll only ever see events for the current 
buffer.

I don't see the point in supporting anything else, unless you go all 
the way and provide a random access sequencer API, where plugins can 
just browse around as they wish.


 If the plugin does not implement this extension, it cannot handle
 buffers of more than 65536 samples - and that should be perfectly
 fine in most cases.

Well, it's kind of nasty that the base API supports larger buffers if 
the events don't, but IMNSHO, the mistake is in supporting 65536 
sample buffers *at all*...


 Hell, max buffer size in Buzz was 256 samples, pitiful by
 today's standards, and it was still quite efficient. 

I'd say it's efficient *because* of this. It may not matter much on a 
quiescent system with a CPU with megabytes of cache, but if you have 
serious GUI stuff going on - or a game engine - your audio thread 
will wake up and find 100% cold memory every time it fires! In that 
situation, every byte of the graph's footprint will have to be 
fetched from cold memory at least once per engine cycle.

Of course, if your graph footprint is larger than the cache, things 
get even worse, as you'll have cache misses over and over until the 
audio thread is done with the buffer.


//David Olofson - Programmer, Composer, Open Source Advocate

.---  http://olofson.net - Games, SDL examples  ---.
|http://zeespace.net - 2.5D rendering engine   |
|   http://audiality.org - Music/audio engine  |
| http://eel.olofson.net - Real time scripting |
'--  http://www.reologica.se - Rheology instrumentation  --'
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-28 Thread David Olofson
On Wednesday 28 November 2007, Dave Robillard wrote:
[...]
 The only problem that needs to be handled is how to get the type in
 there.  I would like to find a good solution to this problem that's
 as extensible as URIs but doesn't actually stick a URI in the event
 struct (there are a few other future extensions that have the same
 problem. strcmp of URIs in the audio thread is, as you say,
 completely out of the question, but so is handing out a flat numeric
 space.  This is /the/ problem that needs solving here, and I'm
 desperately trying to guide the conversation in a direction that
 will get it solved nicely ;)

I don't know if this is applicable here, but for Audiality 2 I'm 
dealing with this on the connection level. Each control is a port 
like any other, meaning it has a name, a protocol URI and a few other 
parameters that the host needs to know what can and cannot be 
connected. If two ports have the same URI, they can be connected, and 
that's it, basically. Event semantics (structured 
stream, commands etc) and data fields are left to the plugins that 
implement the ports, so the host doesn't even need to know what the 
plugins are talking about. (This is a direct connection model; data 
is not normally piped through the host.)

On the physical level, I still have ports share event buffers (or 
rather, queues in this case) so plugins don't have to sort/merge or 
poll umpteen queues all the time. What event goes where is decided 
by means of filling an address field with an opaque cookie value that 
the plugin generates upon connection. The cookie can be ignored if 
there's one queue per port, or it can be a fully specified 
plugin-wide port index if the plugin uses a single event queue, or 
anything in between.

Multiple queues...? Yes, A2 plugins can use multiple queues when that 
suits the implementation better. (Multiple inner loops, rather than 
running the whole synth, all voices, or whatever, one sample at a 
time.) Thus, a plugin doesn't have to mess around with the events to 
get them to the right places in the right order. It just creates one 
queue per voice/strip/section/whatever loop and hands the right 
queues out when connections are made. This means an event target 
also needs to contain a queue pointer.

Of course, one could just use one queue per plugin and use only cookie 
addressing, but I decided to allow multiple queues to eliminate most 
of the event dispatching complexity you'll otherwise have in any 
non-trivial plugin.

It seems to be a simple and efficient solution, but I could be missing 
something, of course. Remains to see when I have some more serious 
code running. :-)


//David Olofson - Programmer, Composer, Open Source Advocate

.---  http://olofson.net - Games, SDL examples  ---.
|http://zeespace.net - 2.5D rendering engine   |
|   http://audiality.org - Music/audio engine  |
| http://eel.olofson.net - Real time scripting |
'--  http://www.reologica.se - Rheology instrumentation  --'
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-28 Thread Lars Luthman
On Wed, 2007-11-28 at 16:45 +, Krzysztof Foltman wrote:
 There is also a possible middle ground - an event type declaration in
 rdf would say not just what URI it corresponds to, but also if it
 contains any unsafe data (like pointers, handles etc).
 
 Just to possibly prevent a hypothetical transparent network/interprocess
 bridge from trying to smuggle pointers between process boundaries, which
 could lead to unexplained crashes :)

_Any_ structure that isn't just a dumb array of bytes will be unsafe to
move between machines because of endianness. If the host doesn't know
exactly what the internal structure of the event buffer is it can't do
anything like that (unless it has a serialisation callback like in your
object event proposal) and if it does it can, so having a separate flag
for that is probably redundant.


  No argument with any of this. Passing around reference counted opaque
  objects can certainly be useful and I can imagine lots of sexy
  applications, I just don't think it needs to be in the event transport
  specification when it works just as well outside it.
 
 Good. So let's postpone that part for now, it will go into different
 extension(s).

OK, so what we have now is something like this:


struct Event_Port_Buffer {
  uint32_t capacity;// number of elements in the array
  uint32_t used_size;   // number of _used_ elements
  uint32_t event_count; // number of events (different from
// used_size if there are large events -
// would this really be needed?)
  struct Event* events; // an array allocated by the host
};

struct Event {
  uint32_t timestamp;
  uint16_t size;
  uint16_t event_type;
  uint8_t data[8];  // or a union or whatever, as long
// as it's 8 bytes
};


A pointer to an Event_Port_Buffer is passed to connect_port() for every
event port etc. And in the RDF file for the plugin there would be
something like this:


http://myplugin.example.com a lv2:Plugin;
  lv2:requiredFeature http://lv2.example.com/midi-event-type;
  lv2:port [
a lv2:InputPort, http://lv2.example.com/event-port;
...
  ];
  ...


The host won't instantiate the plugin unless it knows how to handle
event ports and MIDI events, and the plugin will fail to instantiate
unless the host passes a URI - integer map to instantiate using a
LV2_Feature with the URI http://lv2.example.com/uri-map and a
NULL-terminated array of event type URIs as data. The integer associated
to each URI is simply the array index (my earlier suggestion was just a
brain dump from a thought-in-progress, a simple array seems a lot
cleaner).

Assuming that the host only supports MIDI events the data passed for
this feature will be { http://lv2.example.com/midi-event-type;, NULL },
the plugin will store the index 0 as the MIDI event identifier somewhere
in its state, and everything is good to go. A basic loop for processing
input events in a plugin could look something like this:


  Event_Port_Buffer* buf = ports[EVENT_PORT];
  uint32_t index;
  uint32_t next_frame;
  uint32_t frames_done = 0
  while (index  buf-used_size) {
next_frame = events[index].timestamp  16;
render_audio(frames_done, next_frame);
frames_done = next_frame;
handle_event(events[index]);
index += 1 + (events[index].size - 8) / 16;
  }
  render_audio(frames_done, nframes);


Should plugins have to list http://lv2.example.com/uri-map as a
required feature, or should that be implicit whenever a plugin has an
event port? Both methods have some drawbacks - if plugins are required
to list it there is some redundancy, if they are not we have a required
feature that isn't listed as one which can be a bit confusing.

Does anyone else see any other problems with this type of event port?
Steve, Dave, Nedko?


--ll


signature.asc
Description: This is a digitally signed message part
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-28 Thread Dave Robillard

On Wed, 2007-11-28 at 23:39 +0100, David Olofson wrote:
 On Wednesday 28 November 2007, Dave Robillard wrote:
 [...]
  The only problem that needs to be handled is how to get the type in
  there.  I would like to find a good solution to this problem that's
  as extensible as URIs but doesn't actually stick a URI in the event
  struct (there are a few other future extensions that have the same
  problem. strcmp of URIs in the audio thread is, as you say,
  completely out of the question, but so is handing out a flat numeric
  space.  This is /the/ problem that needs solving here, and I'm
  desperately trying to guide the conversation in a direction that
  will get it solved nicely ;)
 
 I don't know if this is applicable here, but for Audiality 2 I'm 
 dealing with this on the connection level. Each control is a port 
 like any other, meaning it has a name, a protocol URI and a few other 
 parameters that the host needs to know what can and cannot be 
 connected. If two ports have the same URI, they can be connected, and 
 that's it, basically. Event semantics (structured 
 stream, commands etc) and data fields are left to the plugins that 
 implement the ports, so the host doesn't even need to know what the 
 plugins are talking about. (This is a direct connection model; data 
 is not normally piped through the host.)

Same with LV2 ports; works perfectly for port types.  Problem is,
sticking a URI in each /event/ is far too bloated/slow.

-DR-


___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-28 Thread Dan Mills
On Wed, 2007-11-28 at 19:07 -0500, Dave Robillard wrote:


 
 Same with LV2 ports; works perfectly for port types.  Problem is,
 sticking a URI in each /event/ is far too bloated/slow.
 

I am coming horribly late to this discussion, so I might be being thick,
but what happens if each event contains a pointer to a C style string
being the URI... Bloated and slow right?

Now here is the trick, we convert that to a unique identifier at run
time by registering each unique event URI as a string in some data
structure (Map, linked list of parameters, whatever), then at event
creation time we set the pointer to point to our single common instance
of the URI. Now all events of a given type have the same value stored in
that pointer which will serve as a unique ID for this event for run of
the programme. If saving event data to disk, we just replace the pointer
with the string it pointed to. 

struct event_t {
char * uri;
size_t data_length;
char data[1]
};

On loading a set of events build a list of every unique uri and patch
each events uri pointer to point to it. 

struct known_events {
char *uri;
int (*handler)(struct event_t * ev, void *param);
struct known_events *next;
}

Or something like that. 

Now using the fact that the address of a struct is the address of the
first element of the struct, running an event is simply 
((struct known_events *) event.uri)-handler (event,whatever);

Or something like that, I didn't try to compile it. 

If we wish to check if two events are of the same type then 
if ((char*) event1.uri == (char*) event2.uri){
is sufficient and is a single 32 or 64 bit integer comparison. 

Just a thought.

Regards, Dan.



___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-28 Thread David Olofson
On Thursday 29 November 2007, Dave Robillard wrote:
[...]
 Same with LV2 ports; works perfectly for port types.  Problem is,
 sticking a URI in each /event/ is far too bloated/slow.

That's why I'm using a Port as the smallest connection unit, much 
like LADSPA ports, so there is no need for an event type field of any 
kind at all, let alone a URI.

The data in the events *could* be MIDI or whatever (the host doesn't 
even have to understand any of it), but normally, in the case of 
Audiality 2, it'll be modular synth style ramped control events. That 
is, one port controls exactly one value - just like in LADSPA, only 
using timestamped events with ramping info instead of one value per 
buffer.

Extensibility is a non-issue on this level. What you do if you want 
more stuff is just grab another URI for a new event based protocol, 
and you get to start over with a fresh event struct to use in 
whatever way you like. (In fact, as it is, the host doesn't even have 
to know you'll be using events. It just provides a LIFO pool of 
events for any plugins that might need it.)


//David Olofson - Programmer, Composer, Open Source Advocate

.---  http://olofson.net - Games, SDL examples  ---.
|http://zeespace.net - 2.5D rendering engine   |
|   http://audiality.org - Music/audio engine  |
| http://eel.olofson.net - Real time scripting |
'--  http://www.reologica.se - Rheology instrumentation  --'
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-28 Thread David Olofson
On Thursday 29 November 2007, Dave Robillard wrote:
[...]
 Well, sure, but big data is big data. In the typical case plugin
 buffers are much smaller than the cache
[...]

Of course, but that's exactly what I'm talking about - large buffers, 
and why it doesn't make sense to support them. :-)

If you're using 65536 samples per buffer, it just takes a plugin with 
four audio inputs and you're up to 1 MB of intermediate buffers. Even 
if that does fit in the cache, in a real life situation, with other 
threads working, most of it will be cold again every time the audio 
thread starts. So, your processing speed is potentially capped at the 
memory bandwidth throughout the buffer cycle, or at least until you 
start reusing buffers in the graph. And what is supposed to be gained 
by this...?

I don't see why a plugin API of this type should support nonsense like 
that at all, and thus, it shouldn't affect event timestamps either - 
but well, now it's there, and there isn't really any Right Thing(TM) 
to do here, I guess.


 crunching away on plain old audio here is definitely CPU bound (with
 properly written RT safe host+plugins anyway).

Last time I looked into this, a reasonably optimized resampler with 
cubic interpolation and some ramped parameters was memory bound even 
on a lowly P-III CPU, at least with integer processing. (Haven't 
actually tested this on my AMD64...)

I think floating point should be as fast or faster in most cases, at 
least on P-III CPUs and better - and with SIMD, you may get another 
2x-4x higher throughput at that.

Could be way off here, though. Do you have benchmark figures?


//David Olofson - Programmer, Composer, Open Source Advocate

.---  http://olofson.net - Games, SDL examples  ---.
|http://zeespace.net - 2.5D rendering engine   |
|   http://audiality.org - Music/audio engine  |
| http://eel.olofson.net - Real time scripting |
'--  http://www.reologica.se - Rheology instrumentation  --'
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-28 Thread Nedko Arnaudov
Lars Luthman [EMAIL PROTECTED] writes:

 struct Event_Port_Buffer {
   uint32_t capacity;// number of elements in the array
   uint32_t used_size;   // number of _used_ elements
   uint32_t event_count; // number of events (different from
 // used_size if there are large events -
 // would this really be needed?)
   struct Event* events; // an array allocated by the host
 };

 struct Event {
   uint32_t timestamp;
   uint16_t size;
   uint16_t event_type;
   uint8_t data[8];  // or a union or whatever, as long
 // as it's 8 bytes
 };

snip

 Should plugins have to list http://lv2.example.com/uri-map as a
 required feature, or should that be implicit whenever a plugin has an
 event port? Both methods have some drawbacks - if plugins are required
 to list it there is some redundancy, if they are not we have a required
 feature that isn't listed as one which can be a bit confusing.

I think uri-map feature should be part of event extension itself. what
would be use without it?

I think using untyped 8 byte array instead of union is more appropriate,
we can map those 8 bytes to whethever is needed based on type
uri. However, the needs additional marshaling flag is good thing
imho. this can include endian swaping, and dereferencing external
objects. It would be appropriate to have marshaling feature lv2
extension in future (for cross machine events). Since value of this
flag is known at compile/deploy stage, there is no need it to be
runtime variable. Having it specified in RDF is the way to go.

Also, i doubt we need three count members in Event_Port_Buffer
structure. used_size - number of used events is perfectly fine by
itself. I dont see why plugin should know whether buffer is actually
larger.

Is midi event type semantics a broad or narrow one? I'd prefer narrow
one, i.e. one type for note on/offs, one for pitch bend, and for midi
cc, etc. Reasoning behind this is to indicate to user (informational) or
maybe to host for runtime optimizations too, that only certain types of
midi events will be actually processed. Read this as lv2zynadd does not
respond to MIDI CC events (zynjacku however maps (will) those to actual
parameter changes, through separate ports).

-- 
Nedko Arnaudov GnuPG KeyID: DE1716B0


pgpoyJHUMAEGa.pgp
Description: PGP signature
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-28 Thread Nedko Arnaudov
Dan Mills [EMAIL PROTECTED] writes:
 Now here is the trick, we convert that to a unique identifier at run
 time by registering each unique event URI as a string in some data
 structure (Map, linked list of parameters, whatever), then at event
 creation time we set the pointer to point to our single common instance
 of the URI. Now all events of a given type have the same value stored in
 that pointer which will serve as a unique ID for this event for run of
 the programme. If saving event data to disk, we just replace the pointer
 with the string it pointed to. 

 struct event_t {
   char * uri;
   size_t data_length;
   char data[1]
 };

 On loading a set of events build a list of every unique uri and patch
 each events uri pointer to point to it. 

I somewhat like the idea, but how would this work for a host dispatching
opaque/unknown events? Maybe such host would load plugin event type uris
From RDF and just use them in opaque way. However, I dont see benefits
over the uri-map approach proposed in the other subthread. using uri map
indexes looks quite more cleaner and intuitive to me than assuming uri
pointers are constant. IMHO later can be quite confisung for not that
experienced plugin writters.

 struct known_events {
   char *uri;
   int (*handler)(struct event_t * ev, void *param);
   struct known_events *next;
 }

I don't get why this handler callback is needed at all. In LV2 such
events are supposed to be processed during run().

It is worth to discuss how host dispatching opaque events will notify
already instantiated plugins about new event type introduced by loading
new plugin.

-- 
Nedko Arnaudov GnuPG KeyID: DE1716B0


pgpHv0aKEGCkw.pgp
Description: PGP signature
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-27 Thread Krzysztof Foltman
Dave Robillard wrote:

 Why not make it satisfy most everyone by being extensible?

It *is* extensible. Note that commands 0x00-0x6F and 0x73-0x7F are
unused, so further extensions are free to define them (perhaps we need a
scheme for binding extension URIs to command numbers, to make it more
LV2-ey). And 0x72 command can be used for pretty much any data larger
than 8+2 octets.

While it's efficient first and not generic first, so to speak, it
should be fine for the intended uses.

 The idea of a generic event port is not a bad one, 

I think it's not just not a bad one. The other possibility (multiple
event ports) is less efficient, and speed is crucial here. It's also
more complex, looking from plugin author's perspective. So I had little
choice.

 idea at all (no matter what, someone is going to want to put something
 in there you didn't think of.

Please don't jump to conclusions, and take more time to read and analyse
the proposal.

Of course, it is possible to add new event types with arbitrary length
data, and the limitation of 8 octets per extended block is not that bad,
because you can always fit an interface pointer (32-bit or 64-bit) there.

Just look how binary data extension is implemented.

Notice that I just took the approach of optimizing for most common case
(MIDI events), and tried to maximize functionality while keeping block
size small and constant (to avoid pointer arithmetic that was
complicating Lars' proposal a bit).

  Trying to pre-define things from the top down like this is un-lv2-ey).

Well, sometimes you need to find the right tradeoff between being
efficient (memory- and speed-wise) and generic. I think I've found an
acceptable tradeoff (definitely favouring speed, but not losing
generality and not very memory-hungry).

However, I had to make some assumptions about how it will be used
(mostly implemented by inexperienced people, mostly used for MIDI and
float parameters, seldom used for advanced stuff). Oh well, I'm
repeating myself here :)

I think those are correct assumptions, but you seem to have a different
angle for looking at those things. Well, it took me years (and
failed/inadequate designs) to grow out of the everything should be as
generic as possible approach, so I understand why you're doing that,
but I still prefer the priority-based optimization approach that I've used.

I still think my proposal could be improved, and I don't like some
decisions that I made (basically, I made them because the alternatives
looked even more nasty), but stripping off optimizations is not the way
to go, IMO.

 Something more appropriate (IMO) might be like:
 struct LV2_EVENT
 {
   ev_stamp_t time; /// (ignoring the timestamp type issue)
   ev_type_t  type; /// (again ignoring type issue)
   size_t buf_size; /// size of buf in bytes
   char*  buf;  /// raw event  data
 }

You're suggesting a classic textbook chunked data approach, which
works, no doubt. However, it has some problems with it, which might not
be considered very major, but seem to make my approach slightly more
favourable:

- too much data to be accessed in the most common use case (in 32-bit
environment, 16 bytes of header plus event data possibly in distant
memory); we don't need to save every byte of RAM, but when you need to
read and write twice as much RAM as you could, then maybe it's worth
rethinking it

- separation of event header and event data in the most common case;  it
would be better not to cause cache thrashing too much

- it encourages memory fragmentation (experienced people will allocate
event data for all events in the same buffer, wonder about inexperienced
ones, one malloc per event data? :) )

- it doesn't deal with large data properly (because the plugin cannot
start owning the raw event data instead of copying it from the buffer
provided); imagine copying a video buffer in the process() function of a
plugin!

I'm not saying that approach is Really Bad - just that it's kind of a
pre-optimization version of my proposal (I made MIDI data very
efficient, float parameter data slightly less efficient, float parameter
data with deltas even less efficient, and binary data are pretty
inefficient :) ).

The fact that event has to be handled is annoying enough on its own :) -
I have to end the inner loop, store state information somewhere etc. - I
don't want some additional, unnecessary memory accesses which may throw
sample data and buffers out of the cache.

 (Obviously just a quick generic knock-off to get the idea across).  In
 networkey terms, this is separating transport from contents, which is
 pretty firmly established as a Good Idea. 

In network context, yes. However, _optimizing_ for uncommon case is not
a preferable approach to me.

The arbitrary binary data command (0x72) mentioned in my proposal can
give you practically everything you need, and can be used in a
network-transparent way, as long as data in the binary data chunks are
self-contained (don't 

Re: [LAD] enhanced event port LV2 extension proposal

2007-11-27 Thread Jens M Andreasen
On Tue, 2007-11-27 at 10:46 +, Krzysztof Foltman wrote:


 Well, sometimes you need to find the right tradeoff between being
 efficient (memory- and speed-wise) and generic. 

++ KzF

 I think I've found an
 acceptable tradeoff (definitely favouring speed, but not losing
 generality and not very memory-hungry).


___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-27 Thread Dave Robillard
On Tue, 2007-11-27 at 10:46 +, Krzysztof Foltman wrote:
 Dave Robillard wrote:
 
  Why not make it satisfy most everyone by being extensible?
 
 It *is* extensible. Note that commands 0x00-0x6F and 0x73-0x7F are
 unused, so further extensions are free to define them (perhaps we need a
 scheme for binding extension URIs to command numbers, to make it more
 LV2-ey). And 0x72 command can be used for pretty much any data larger
 than 8+2 octets.

extensible like SYSEX.  It isn't 1980 anymore...

 I think it's not just not a bad one. The other possibility (multiple
 event ports) is less efficient, and speed is crucial here. It's also
 more complex, looking from plugin author's perspective. So I had little
 choice.

Your extension is too complex, this is primarily why I don't like it.
Why are there two uint8_t's in the header that are probably completely
useless for essentially everything but MIDI?  It's crufty.

A stamped chunk of some sort of event is simple to understand,
guaranteed 100% extensible and generic without any weird sysexey
1980'sness, and is very, very similar to how LV2 ports themselves work
(and therefore obvious and easy to understand for anyone who knows LV2).

 Notice that I just took the approach of optimizing for most common case
 (MIDI events), and tried to maximize functionality while keeping block
 size small and constant (to avoid pointer arithmetic that was
 complicating Lars' proposal a bit).
 
   Trying to pre-define things from the top down like this is un-lv2-ey).
 
 Well, sometimes you need to find the right tradeoff between being
 efficient (memory- and speed-wise) and generic. I think I've found an
 acceptable tradeoff (definitely favouring speed, but not losing
 generality and not very memory-hungry).

Your efficiency claims make no sense, frankly.  Put everything in a flat
buffer and voila, it's exactly how MIDI events work right now.  Your
proposal has no inherent performance advantage over a more obvious and
cleaner one.

 However, I had to make some assumptions about how it will be used
 (mostly implemented by inexperienced people, mostly used for MIDI and
 float parameters, seldom used for advanced stuff). Oh well, I'm
 repeating myself here :)

Exactly.  You are making assumptions about what people want to put in
there.  This is a Bad Thing(TM).  If it can be avoided, it should be
(and it can definitely be avoided).

I have said this a lot, and I will continue saying it more until the end
of time because it's important: the fact that ports can
contain /anything/ is the fundamental core idea behind LV2, and it's a
good one.  A good generic event extension must do this as well.

Event transport and event contents are orthogonal problems and they
should be solved separately, otherwise they won't be solved well because
too much is on the table to be figured out at one time (how far would
the Internet have come if every high level protocol was defined in the
IP specification?)

Your optimisation comments (the bulk of your email) are based on a
misunderstanding.  I don't mean the data pointer to point somewhere else
in memory, it's a flat buffer (ie almost identical to how MIDI works
right now).  For large data, that flat buffer can contain a pointer or
whatever (again, see LV2 port extensions that can e.g. contain structs
with whatever you feel like cramming in there).

In short:  if generic events is the goal, then lets make the events
generic!

I'm adamant about this for pragmatic reasons:  There are some more
difficult problems here if we really want to crank up the performance of
this, especially random event access and constant time buffer traversal
which needs an lookup table to be around somewhere.  I want to make the
event contents part of this discussion go away so we can focus on the
real problem at hand and ignore the (completely orthogonal) details of
event types.  The transport part alone is a problem that needs
solving /first/.

Don't get me wrong, I think it's great someone is tackling this one, and
would implement it in a heartbeat, but it needs to be done more in the
spirit of LV2.  Note that commands 0x00-0x6F and 0x73-0x7F are unused
is more the spirit of MIDI circa 30 years ago.  It might be kinda sorta
extensible for some limited definition of extensible, but we can do
better.. having to appeal to some (nonexistant) central authority for
doling out a numeric range for features is completely out of the
question (we learned that one with LADSPA IDs).

Cheers,

-DR-

P.S. I tried to see this (generic events) happen with Jack MIDI too but
it was shot down for silly reasons.  Real extensibility means we're
free to hack without having to convince a bunch of sticks in the mud on
mailing lists that we're right (or tell them anything at all for that
matter), which IMO has held back LAD progress in several areas for
years.  I absolutely guarantee that people will do new and interesting
things with events if we /completely/ eliminate the diplomatic overhead
of 

Re: [LAD] enhanced event port LV2 extension proposal

2007-11-27 Thread Marc-Olivier Barre
On Nov 27, 2007 11:24 PM, Dave Robillard [EMAIL PROTECTED] wrote:
 I have said this a lot, and I will continue saying it more until the end
 of time because it's important: the fact that ports can
 contain /anything/ is the fundamental core idea behind LV2, and it's a
 good one.  A good generic event extension must do this as well.

Dave, I love it when you go crazy over a piece of spec. Just don't
change anything :-)

And for what it's worth, I agree with you on most parts...

Cheers,
__
Marc-Olivier Barre,
MarcO'Chapeau.
___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev


Re: [LAD] enhanced event port LV2 extension proposal

2007-11-27 Thread Dave Robillard

On Wed, 2007-11-28 at 01:05 +0100, Marc-Olivier Barre wrote:
 On Nov 27, 2007 11:24 PM, Dave Robillard [EMAIL PROTECTED] wrote:
  I have said this a lot, and I will continue saying it more until the end
  of time because it's important: the fact that ports can
  contain /anything/ is the fundamental core idea behind LV2, and it's a
  good one.  A good generic event extension must do this as well.
 
 Dave, I love it when you go crazy over a piece of spec. Just don't
 change anything :-)

I try :)

-DR-


___
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/mailman/listinfo/linux-audio-dev