Jack MIDI revised API

classic Classic list List threaded Threaded
25 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Jack MIDI revised API

Dave Robillard
I've done some work on the Jack "midi" header.  The most obvious of
which being it's no longer the "midi" header but the "event" header.

Header and doxygen generated pages here:
http://www.scs.carleton.ca/~drobilla/jack_event_api/

(Please read everything below before commenting)

Changes:

* The obvious documentation and cosmetic changes.  I've tried to specify
expected use/behaviour in all places that require it.

* Addition of event type field in port info struct

* Attempt to chose saner names for all functions.

* Typedefs for types that probably should be typedef'd (port buffer and
raw event data)

* Removal of running status (see below)

Important:  This is intended to represent the _client visible_ API.
Most of the things that were 'removed' just moved into the
implementation file.  Functionally speaking, nothing has changed (both
example clients are functioning after some trivial search/replacing).
In other words, these changes are nowhere near as dramatic as they
cosmetically seem.

The intent here is to make sure this transport is ready for whatever
future event types we want to add (hence the type field), and to work
towards polishing things up for eventual CVS inclusion (hence the
renaming and documentation).

I am aware this is a bit heavy handed, which is why it's a header file
and documentation, and not a complete patch.  Discuss. :)

-DR-



-------------------------------------------------------
SF.Net email is sponsored by:
Tame your development challenges with Apache's Geronimo App Server. Download
it for free - -and be entered to win a 42" plasma tv or your very own
Sony(tm)PSP.  Click here to play: http://sourceforge.net/geronimo.php
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: Jack MIDI revised API

Dave Robillard
On Wed, 2005-09-11 at 17:31 +1100, Dave Robillard wrote:
> I've done some work on the Jack "midi" header.  The most obvious of
> which being it's no longer the "midi" header but the "event" header.
>
> Header and doxygen generated pages here:
> http://www.scs.carleton.ca/~drobilla/jack_event_api/
>
> (Please read everything below before commenting)
[snip]

I would like to continue this work with people's approval, but I don't
want to waste my time.  Anyone?  The silence is deafening here. :)

-DR-  (Replies to himself without shame)



-------------------------------------------------------
SF.Net email is sponsored by:
Tame your development challenges with Apache's Geronimo App Server. Download
it for free - -and be entered to win a 42" plasma tv or your very own
Sony(tm)PSP.  Click here to play: http://sourceforge.net/geronimo.php
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: Jack MIDI revised API

Jack O'Quin-2
In reply to this post by Dave Robillard
Dave Robillard <[hidden email]> writes:

> I've done some work on the Jack "midi" header.  The most obvious of
> which being it's no longer the "midi" header but the "event" header.
>
> Header and doxygen generated pages here:
> http://www.scs.carleton.ca/~drobilla/jack_event_api/

Some initial thoughts...

After that long discussion, I'm surprised you chose not to implement
some form of sub-sample timing.

For future binary compatibility, I dislike returning a struct from
jack_event_port_get_info().  It is generally more flexible to define
separate accessor functions for each field (there are currently only
two).

Why is port_buffer sometimes (void *) and sometimes (jack_event_buffer_t)?

The jack_event_reserve_next_event() interface encourages clients to
write directly into the port buffer.  That could be dangerous, is it
necessary?  Would jack_event_write() be sufficient?

As a matter of style, I prefer names like jack_event_get() instead of
jack_event_get_event(), which seems redundant.  Here is a possible
alternative list of names (including accessors)...

  jack_event_clear()
  jack_event_count()            # was jack_event_port_get_info()
  jack_event_get()
  jack_event_lost_count()
  jack_event_reserve()
  jack_event_type()             # was jack_event_port_get_info()
  jack_event_write()

(The documentation is easier to use when sorted alphabetically.)

I have not had time to look carefully at the return codes, yet.
Generally, they seem to be zero (good) or nonzero (bad).  Sometimes it
returns a negative value for bad, somewhat inconsistent.  

It is generally helpful to return more informative error status.  I
like to use <errno.h> values.  They are easy to work with, somewhat
descriptive, and easily printed in human-readable form.  So,
jack_event_write() could return ENOSPC, for example, if there is no
more room in the buffer.

Should an event count really be returned as a jack_nframes_t?  That
seems wrong somehow.  How about a jack_nevents_t?

The buffer pointer in the event header should be a shared memory
offset, not a pointer.  We hope someday to allow mixed 32 and 64-bit
clients (on x86_64) to share access to a single server.  That requires
avoiding pointer types in shared memory.  (They don't really work
properly on most platforms, anyway.)  We probably want to use
something similar to the jack_shmsize_t in <jack/types.h> for this.
Perhaps call it jack_shmoffset_t, or just use the same type for both.
--
  joq


-------------------------------------------------------
SF.Net email is sponsored by:
Tame your development challenges with Apache's Geronimo App Server. Download
it for free - -and be entered to win a 42" plasma tv or your very own
Sony(tm)PSP.  Click here to play: http://sourceforge.net/geronimo.php
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: Jack MIDI revised API

Dave Robillard
On Fri, 2005-11-11 at 23:33 -0600, Jack O'Quin wrote:

> Dave Robillard <[hidden email]> writes:
>
> > I've done some work on the Jack "midi" header.  The most obvious of
> > which being it's no longer the "midi" header but the "event" header.
> >
> > Header and doxygen generated pages here:
> > http://www.scs.carleton.ca/~drobilla/jack_event_api/
>
> Some initial thoughts...
>
> After that long discussion, I'm surprised you chose not to implement
> some form of sub-sample timing.

I did it before that discussion got going, and I'm waiting to see what
the agreement is before putting whatever in there.  I'm just cleaning
things up...

> For future binary compatibility, I dislike returning a struct from
> jack_event_port_get_info().  It is generally more flexible to define
> separate accessor functions for each field (there are currently only
> two).

Fair enough (this was in the original patch, not a change of mine).
That would be more consistent with the other jack port stuff as well.  I
guess that struct should become private.

> Why is port_buffer sometimes (void *) and sometimes (jack_event_buffer_t)?

I havn't finished typedeffing yet.  Thought I got all the ones that were
visible in that upload.. :)

> The jack_event_reserve_next_event() interface encourages clients to
> write directly into the port buffer.  That could be dangerous, is it
> necessary?  Would jack_event_write() be sufficient?

I thought it was strange as well.  I assume there's some reason for it
being there - Ian?

> As a matter of style, I prefer names like jack_event_get() instead of
> jack_event_get_event(), which seems redundant.  Here is a possible
> alternative list of names (including accessors)...
>
>   jack_event_clear()
>   jack_event_count()            # was jack_event_port_get_info()
>   jack_event_get()
>   jack_event_lost_count()
>   jack_event_reserve()
>   jack_event_type()             # was jack_event_port_get_info()
>   jack_event_write()
>
> (The documentation is easier to use when sorted alphabetically.)

Yeah, some do look a bit silly.  I just replaced "midi" with "event"
trying to rock the boat as little as possible.  Those names look good to
me.

> I have not had time to look carefully at the return codes, yet.
> Generally, they seem to be zero (good) or nonzero (bad).  Sometimes it
> returns a negative value for bad, somewhat inconsistent.  
>
> It is generally helpful to return more informative error status.  I
> like to use <errno.h> values.  They are easy to work with, somewhat
> descriptive, and easily printed in human-readable form.  So,
> jack_event_write() could return ENOSPC, for example, if there is no
> more room in the buffer.

I took a quick look at the other Jack functions, and they seemed to just
return 0 or nonzero, so that's what I did.  I'll try to throw in
appropriate errno codes where they make sense.

> Should an event count really be returned as a jack_nframes_t?  That
> seems wrong somehow.  How about a jack_nevents_t?

Ah, good point.  I've gotten a little too used to using nframes_t as
'generic count-stuff type'

> The buffer pointer in the event header should be a shared memory
> offset, not a pointer.  We hope someday to allow mixed 32 and 64-bit
> clients (on x86_64) to share access to a single server.  That requires
> avoiding pointer types in shared memory.  (They don't really work
> properly on most platforms, anyway.)  We probably want to use
> something similar to the jack_shmsize_t in <jack/types.h> for this.
> Perhaps call it jack_shmoffset_t, or just use the same type for both.

I'll freely admit to being a bit shared memory retarded.  I'll look into
it.

I'll fix this stuff up and upload another version soon.

-DR-



-------------------------------------------------------
SF.Net email is sponsored by:
Tame your development challenges with Apache's Geronimo App Server. Download
it for free - -and be entered to win a 42" plasma tv or your very own
Sony(tm)PSP.  Click here to play: http://sourceforge.net/geronimo.php
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: Jack MIDI revised API

deviant
In reply to this post by Dave Robillard
On Wed, 2005-11-09 at 17:31 +1100, Dave Robillard wrote:

> I've done some work on the Jack "midi" header.  The most obvious of
> which being it's no longer the "midi" header but the "event" header.
>
> Header and doxygen generated pages here:
> http://www.scs.carleton.ca/~drobilla/jack_event_api/
>
> (Please read everything below before commenting)
>
> Changes:
>
> * The obvious documentation and cosmetic changes.  I've tried to specify
> expected use/behaviour in all places that require it.
>
> * Addition of event type field in port info struct

i've been thinking about this. i think that providing such types this
way is wrong because it is introducing inconsistencies in the way jack
data types are being handled - it is introducing a subtype to the port
type. this is not consistent (the audio type has no subtype) and also
very cumbersome to parse for clients (each event would now have to be
checked for it's type, whereas before no check was needed). a stream of
events of different types mixed together is confusing and much less
efficient.

jack currently has a model in which one port will only have one data
type. i think this is very sensible, and the correct way to do things.

it seems to me that part of the motivation for the change to generic
events is that jack midi provides a mechanism for variable sized data
buffers, which could be useful for other data types too. i think that a
better way to implement this is to preserve jacks current model of one
type per port, and register new types. a large part of the functionality
of the jack midi interface (i.e. all the code that deals with writing a
variable sized event to a port buffer) would then be turned into a set
of functions internal to jack that the different api's for different
event types would use to write data to ports. another reason to do this
is to keep the mixdown function simple.

ian




-------------------------------------------------------
SF.Net email is sponsored by:
Tame your development challenges with Apache's Geronimo App Server. Download
it for free - -and be entered to win a 42" plasma tv or your very own
Sony(tm)PSP.  Click here to play: http://sourceforge.net/geronimo.php
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: Jack MIDI revised API

Dave Robillard
On Sun, 2005-13-11 at 18:00 -0800, ian esten wrote:

> On Wed, 2005-11-09 at 17:31 +1100, Dave Robillard wrote:
> > I've done some work on the Jack "midi" header.  The most obvious of
> > which being it's no longer the "midi" header but the "event" header.
> >
> > Header and doxygen generated pages here:
> > http://www.scs.carleton.ca/~drobilla/jack_event_api/
> >
> > (Please read everything below before commenting)
> >
> > Changes:
> >
> > * The obvious documentation and cosmetic changes.  I've tried to specify
> > expected use/behaviour in all places that require it.
> >
> > * Addition of event type field in port info struct
>
> i've been thinking about this. i think that providing such types this
> way is wrong because it is introducing inconsistencies in the way jack
> data types are being handled - it is introducing a subtype to the port
> type. this is not consistent (the audio type has no subtype) and also
> very cumbersome to parse for clients (each event would now have to be
> checked for it's type, whereas before no check was needed). a stream of
> events of different types mixed together is confusing and much less
> efficient.
>
> jack currently has a model in which one port will only have one data
> type. i think this is very sensible, and the correct way to do things.

Yes, I ran into this problem trying to do the port creation stuff.  This
is largely where my "passing the actual port" questions came from.

> it seems to me that part of the motivation for the change to generic
> events is that jack midi provides a mechanism for variable sized data
> buffers, which could be useful for other data types too. i think that a
> better way to implement this is to preserve jacks current model of one
> type per port, and register new types. a large part of the functionality
> of the jack midi interface (i.e. all the code that deals with writing a
> variable sized event to a port buffer) would then be turned into a set
> of functions internal to jack that the different api's for different
> event types would use to write data to ports. another reason to do this
> is to keep the mixdown function simple.

Essentially all the code will be exactly the same.  There's not really
anything in the patch as I have it that's MIDI specific at all.

I fully agree with the one-type-per-port thing, but the implementation
of all 'event ports' is nearly identical.  There's really no point in
crufting everything up with a different API for every port time - it
would literally be exactly the same, except the functions would have
different names.

-DR-



-------------------------------------------------------
SF.Net email is sponsored by:
Tame your development challenges with Apache's Geronimo App Server. Download
it for free - -and be entered to win a 42" plasma tv or your very own
Sony(tm)PSP.  Click here to play: http://sourceforge.net/geronimo.php
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: Jack MIDI revised API

deviant
On Mon, 2005-11-14 at 13:47 +1100, Dave Robillard wrote:

> I fully agree with the one-type-per-port thing, but the implementation
> of all 'event ports' is nearly identical.  There's really no point in
> crufting everything up with a different API for every port time - it
> would literally be exactly the same, except the functions would have
> different names.

like i said, i disagree. i think it is reasonable and desirable to
expect a different set of functions to deal with a different data type.
an excellent example of this is the recent discussion of OSC. OSC has a
floating point timestamp. jack midi does not. this is just a trivial
difference. i find it easy to imagine a case where some data massaging
would have to be done before writing to a buffer. the current model does
not allow for this.

what you are proposing exposes clients to a lot of potential dangers.
jack can no longer enforce a single type per port, so clients can no
longer assume a single data type per port and must check each event for
it's type. it also makes the merging of data streams far more complex,
and potentially impossible. for instance, there may well be a data type
which can't support stream merging. sharing an api would not allow for
this.

different data types will have slightly different needs, and while it is
very desirable to share functionality, i think this is the wrong way to
go about it. much better would be to provide an api for midi, and an api
for OSC (as an example). now it may be that they share a lot of
functionality, but it does not make sense to combine the data types just
for this reason. as i said before, this functionality must be something
that jack provides under the hood, to support the different api's, and
should not be exposed to clients.

ian





-------------------------------------------------------
SF.Net email is sponsored by:
Tame your development challenges with Apache's Geronimo App Server. Download
it for free - -and be entered to win a 42" plasma tv or your very own
Sony(tm)PSP.  Click here to play: http://sourceforge.net/geronimo.php
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: Jack MIDI revised API

Dave Robillard
On Sun, 2005-13-11 at 19:24 -0800, ian esten wrote:

> On Mon, 2005-11-14 at 13:47 +1100, Dave Robillard wrote:
>
> > I fully agree with the one-type-per-port thing, but the implementation
> > of all 'event ports' is nearly identical.  There's really no point in
> > crufting everything up with a different API for every port time - it
> > would literally be exactly the same, except the functions would have
> > different names.
>
> like i said, i disagree. i think it is reasonable and desirable to
> expect a different set of functions to deal with a different data type.
> an excellent example of this is the recent discussion of OSC. OSC has a
> floating point timestamp. jack midi does not. this is just a trivial
> difference. i find it easy to imagine a case where some data massaging
> would have to be done before writing to a buffer. the current model does
> not allow for this.

OSC events will be contained in the event struct (like every other
event), and thus have the same time stamp, whatever that turns out to
be.

> what you are proposing exposes clients to a lot of potential dangers.
> jack can no longer enforce a single type per port, so clients can no
> longer assume a single data type per port and must check each event for
> it's type. it also makes the merging of data streams far more complex,
> and potentially impossible. for instance, there may well be a data type
> which can't support stream merging. sharing an api would not allow for
> this.

You seem to think I've put multiple event types in one port?  Good god
no. :)

Anyway, I stripped out that type field entirely.  I admit it was
ill-advised on my part.  The type of the port is now how client's know
what event type is contained in it (ie exactly the same as audio).

As far as exposing clients, the version below exposes much, much less to
clients than the original (because of Jack O'Quin's binary compatibility
points, and the removal of running status from client land).

On mixing, it's very possible that some event types will not be able to
be mixed.  This doesn't affect the client API though, at least not in
any way I can see.  If a port is unmixable, Jack will not allow multiple
inbound connections to it, and the situation will never arise anyway.

> different data types will have slightly different needs, and while it is
> very desirable to share functionality, i think this is the wrong way to
> go about it. much better would be to provide an api for midi, and an api
> for OSC (as an example). now it may be that they share a lot of
> functionality, but it does not make sense to combine the data types just
> for this reason. as i said before, this functionality must be something
> that jack provides under the hood, to support the different api's, and
> should not be exposed to clients.

The implementation may need to be different (for something crazy like
video anyway, for OSC I don't think it will differ whatsoever) but do
you have a real example why the _API_ for OSC events or MIDI events or
whatever events should be different?

Updated version that fixes the type problem and addresses (most) of
Jack's points (except the shm offset vs pointer):

http://www.scs.carleton.ca/~drobilla/jack_event_api/


-DR-




-------------------------------------------------------
SF.Net email is sponsored by:
Tame your development challenges with Apache's Geronimo App Server. Download
it for free - -and be entered to win a 42" plasma tv or your very own
Sony(tm)PSP.  Click here to play: http://sourceforge.net/geronimo.php
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: Jack MIDI revised API

Fons Adriaensen
On Mon, Nov 14, 2005 at 03:24:59PM +1100, Dave Robillard wrote:

> You seem to think I've put multiple event types in one port?  Good god
> no. :)
>
> Anyway, I stripped out that type field entirely.  I admit it was
> ill-advised on my part.  The type of the port is now how client's know
> what event type is contained in it (ie exactly the same as audio).
>
> As far as exposing clients, the version below exposes much, much less to
> clients than the original (because of Jack O'Quin's binary compatibility
> points, and the removal of running status from client land).

One could wonder why, if the port/buffer is supposed to handle only
one type of event (in this case JACK_DEFAULT_MIDI_TYPE), the API
couln'd be a bit more MIDI-specific. All it does now is putting
events in/out of a buffer, and these don't have to be legal MIDI
at all.

Given the fact that the user knows that events are transported in
buffers, i.e. blocks of raw memory as for audio, and also knows the
buffer size, and the exact representation of the events, all the API
does is hide the exact format of the two extra items that come with
each event: timestamp and length.

In fact the API so 'thin' that one could wonder if it would not be
better to absorb its functionality into the user code that has to be
there anyway to decode the events themselves, and document the raw
buffer format instead. That's what we do for audio buffers anyway.
All that's required to read or write events is advancing a pointer.
Surely, calling a function to copy data between the buffer and an
event struct is as much as waste of cycles as would be e.g. casting
a float to an int (according to some).

--
FA












-------------------------------------------------------
SF.Net email is sponsored by:
Tame your development challenges with Apache's Geronimo App Server. Download
it for free - -and be entered to win a 42" plasma tv or your very own
Sony(tm)PSP.  Click here to play: http://sourceforge.net/geronimo.php
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: Jack MIDI revised API

Jesse Chappell
On 11/14/05, fons adriaensen <[hidden email]> wrote:

> On Mon, Nov 14, 2005 at 03:24:59PM +1100, Dave Robillard wrote:
>
> > You seem to think I've put multiple event types in one port?  Good god
> > no. :)
> >
> > Anyway, I stripped out that type field entirely.  I admit it was
> > ill-advised on my part.  The type of the port is now how client's know
> > what event type is contained in it (ie exactly the same as audio).
> >
> > As far as exposing clients, the version below exposes much, much less to
> > clients than the original (because of Jack O'Quin's binary compatibility
> > points, and the removal of running status from client land).
>
> One could wonder why, if the port/buffer is supposed to handle only
> one type of event (in this case JACK_DEFAULT_MIDI_TYPE), the API
> couln'd be a bit more MIDI-specific. All it does now is putting
> events in/out of a buffer, and these don't have to be legal MIDI
> at all.
>
> Given the fact that the user knows that events are transported in
> buffers, i.e. blocks of raw memory as for audio, and also knows the
> buffer size, and the exact representation of the events, all the API
> does is hide the exact format of the two extra items that come with
> each event: timestamp and length.
>
> In fact the API so 'thin' that one could wonder if it would not be
> better to absorb its functionality into the user code that has to be
> there anyway to decode the events themselves, and document the raw
> buffer format instead. That's what we do for audio buffers anyway.
> All that's required to read or write events is advancing a pointer.
> Surely, calling a function to copy data between the buffer and an
> event struct is as much as waste of cycles as would be e.g. casting
> a float to an int (according to some).

From what I gathered in earlier discussion the contents of the raw
port buffers are *not* transparent and are not simply an array of
event/data structs in the jackmidi implementation.  Hence the desire
for the functions to exist as a way of putting/getting them.  I'd need
to delve back into the archives or the code itself to tell you why
this is the case.

jlc


-------------------------------------------------------
SF.Net email is sponsored by:
Tame your development challenges with Apache's Geronimo App Server. Download
it for free - -and be entered to win a 42" plasma tv or your very own
Sony(tm)PSP.  Click here to play: http://sourceforge.net/geronimo.php
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: Jack MIDI revised API

Paul Davis
> >From what I gathered in earlier discussion the contents of the raw
> port buffers are *not* transparent and are not simply an array of
> event/data structs in the jackmidi implementation.  Hence the desire
> for the functions to exist as a way of putting/getting them.  I'd need
> to delve back into the archives or the code itself to tell you why
> this is the case.

another piece of history, since i know some people are wondering why
there is no jack_midi_event_t.

every other MIDI API defines its own foobar_midi_event_t. if JACK does
this, it forces this struct up into the app code, making the app
fundamentally harder to port between MIDI APIs.

so instead, JACK pretends yer actual MIDI h/w port as much as possible,
and doesn't offer a jack_midi_event_t or anything really similar.

--p




-------------------------------------------------------
SF.Net email is sponsored by:
Tame your development challenges with Apache's Geronimo App Server. Download
it for free - -and be entered to win a 42" plasma tv or your very own
Sony(tm)PSP.  Click here to play: http://sourceforge.net/geronimo.php
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: Jack MIDI revised API

Dave Robillard
In reply to this post by Fons Adriaensen
On Mon, 2005-14-11 at 20:13 +0100, fons adriaensen wrote:

> On Mon, Nov 14, 2005 at 03:24:59PM +1100, Dave Robillard wrote:
>
> > You seem to think I've put multiple event types in one port?  Good god
> > no. :)
> >
> > Anyway, I stripped out that type field entirely.  I admit it was
> > ill-advised on my part.  The type of the port is now how client's know
> > what event type is contained in it (ie exactly the same as audio).
> >
> > As far as exposing clients, the version below exposes much, much less to
> > clients than the original (because of Jack O'Quin's binary compatibility
> > points, and the removal of running status from client land).
>
> One could wonder why, if the port/buffer is supposed to handle only
> one type of event (in this case JACK_DEFAULT_MIDI_TYPE), the API
> couln'd be a bit more MIDI-specific. All it does now is putting
> events in/out of a buffer, and these don't have to be legal MIDI
> at all.
>
> Given the fact that the user knows that events are transported in
> buffers, i.e. blocks of raw memory as for audio, and also knows the
> buffer size, and the exact representation of the events, all the API
> does is hide the exact format of the two extra items that come with
> each event: timestamp and length.
>
> In fact the API so 'thin' that one could wonder if it would not be
> better to absorb its functionality into the user code that has to be
> there anyway to decode the events themselves, and document the raw
> buffer format instead. That's what we do for audio buffers anyway.
> All that's required to read or write events is advancing a pointer.
> Surely, calling a function to copy data between the buffer and an
> event struct is as much as waste of cycles as would be e.g. casting
> a float to an int (according to some).

Unfortunately the buffers in Jack MIDI are not just filled with events,
there's a heap of other crap in there used by the internal
implementation.

Now, whether there /should/ be might be a valid question....

-DR-



-------------------------------------------------------
This SF.Net email is sponsored by the JBoss Inc.  Get Certified Today
Register for a JBoss Training Course.  Free Certification Exam
for All Training Attendees Through End of 2005. For more info visit:
http://ads.osdn.com/?ad_id=7628&alloc_id=16845&op=click
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: Another angle on JACK MIDI

Simon Jenkins
In reply to this post by Fons Adriaensen
On Mon, 2005-11-14 at 20:13 +0100, fons adriaensen wrote:

> [...] is as much as waste of cycles as would be e.g. casting
> a float to an int (according to some).
>

According to who? ;) Oh... hang on... you must mean Erik:

http://mega-nerd.com/FPcast/

So, hmmmm.... does lrintf make my objection go away? Well, yes, maybe,
(sort of), and no.

If the fractional part is simply to be ignored then OK, lrintf would
speed things up, but IIUC (which I might not) it is still non-trivial,
at least on some architectures. Its not just the conversion itself but
also (IIUC!) pipeline issues when you come to use the result as an
integer. Also: Beware the event who's timestamp gets rounded into the
next buffer! Thats more code to write.

OTOH: If the fractional part is to be used, but the app needs to
separate integer from fraction, then its truncation not rounding that is
required, and we're back to that inefficient casting.


Now a slight change of subject, and a genuine question: Forgetting about
fixed vs float for a moment, how much sub-sample timing precision would
the kinds of applications you were thinking about require? You can't
have wanted more than about 16 bits of sub-sample precision (else your
floats would not cut it towards the end of a largeish buffer!) but would
they even require that much?

I'll admit I've been thinking about all this in terms of a very simple
use case: A stream of events being used as if it were an LFO running at
some audible frequency eg to hard-sync another (audio) oscillator. I
think that forcing the events to sample boundaries would introduce
noticeable artifacts here (hence my support for sub-sample timing) but
guess that even 8 bits of sub-sample precision would sort it out in this
case. I know that you have somewhat different and more sophisticated use
cases in mind, eg granular synthesis, so its a genuine question: How
much precision would they need?

Cheers

Simon




-------------------------------------------------------
This SF.Net email is sponsored by the JBoss Inc.  Get Certified Today
Register for a JBoss Training Course.  Free Certification Exam
for All Training Attendees Through End of 2005. For more info visit:
http://ads.osdn.com/?ad_id=7628&alloc_id=16845&op=click
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: Another angle on JACK MIDI

Alfons Adriaensen
On Tue, Nov 15, 2005 at 12:38:30AM +0000, Simon Jenkins wrote:

> So, hmmmm.... does lrintf make my objection go away? Well, yes, maybe,
> (sort of), and no.
>
> If the fractional part is simply to be ignored then OK, lrintf would
> speed things up, but IIUC (which I might not) it is still non-trivial,
> at least on some architectures. Its not just the conversion itself but
> also (IIUC!) pipeline issues when you come to use the result as an
> integer. Also: Beware the event who's timestamp gets rounded into the
> next buffer! Thats more code to write.

There is another issue related to this that will open up a new can of
worms. I'll wait with it until the end of this post :-)

> OTOH: If the fractional part is to be used, but the app needs to
> separate integer from fraction, then its truncation not rounding that is
> required, and we're back to that inefficient casting.

if f(x) rounds, then f(x-0.5f) truncates.

Regarding the float / fixed issue, there is also a third option wich is
more or less halfway: integer + float, with the float representing a
fractional sample (0 <= f < 1).

Also we should consider this: those cases where a int provides all the
precision required will also be the ones having relatively few events
(note on / off, and parameter changes limited to the MIDI bandwidth).
The cases where fractional offsets are needed, e.g. granular synthesis,
will be those using *many* events. It would make sense to optimize
those. Whatever the cost of truncating a float to an int, it's probably
peanuts compared to whatever is required to generate the complete
waveform of a note, or to recalculate internal processing parameters,
typically requiring trancendental functions.

When, as in granular synthesis, your next event is just a few samples
away, the overhead of converting e.g. an offset that in all probability
will have been computed as a float, to another representation and back
again at the other end, is not trivial at all.


> Now a slight change of subject, and a genuine question: Forgetting about
> fixed vs float for a moment, how much sub-sample timing precision would
> the kinds of applications you were thinking about require? You can't
> have wanted more than about 16 bits of sub-sample precision (else your
> floats would not cut it towards the end of a largeish buffer!) but would
> they even require that much?

The i,f format suggested above would solve that problem.

> I'll admit I've been thinking about all this in terms of a very simple
> use case: A stream of events being used as if it were an LFO running at
> some audible frequency eg to hard-sync another (audio) oscillator.
> I think that forcing the events to sample boundaries would introduce
> noticeable artifacts here (hence my support for sub-sample timing) but
> guess that even 8 bits of sub-sample precision would sort it out in this
> case. I know that you have somewhat different and more sophisticated use
> cases in mind, eg granular synthesis, so its a genuine question: How
> much precision would they need?

What happens in granular synthesis is that event _timing_ is used as a
means to control the _spectrum_ of your signal - it's this what makes
the method interesting from a musical POV. So any error in the event
timing will translate into spectral changes. If the errors are 'random'
(i.e. not correlated with the value), the result will be noise, the
error energy will be spread over a large bandwidth, and probably not
be problem. If the error is systematic, the result will be one ore more
unwanted discrete frequencies appearing in your spectrum. These can be
*very* disruptive, even at quite low levels. So to summarise: you'd want
all the precision you can get, and above all you want to avoid 'simple'
error patterns. That is really my main objection to fixed point in
synthesis: unless it uses a large number of bits, and some randomness
is added, the error patterns can easily become quite systematic.

This has become quite evident to me in another context involving timing:
the resampling code that is used in Aeolus to impose a per pipe phase
modulation. I tried all sorts of 'simple' algorithms such as oversampling
(2^n, to simplify the index calculations), in order to avoid full floating
point interpolation. All of those simple schemes introduced perceptible
errors into the resulting sound (unless blown up to unreasonable sizes)
Even if they would be near perfect for 'general' signals, they failed
on the very structured sounds they had to operate on, because of the
systematic timing errors. But that is of course exactly the situation
that any sound synthesis code would find itself in. So in the end the
solution was a combination of oversampling (by 2 or 3), combined with
linear interpolation, all done with floats.

I really have to get back to work, so I leave the fresh can of worms
for later.

--
FA




-------------------------------------------------------
This SF.Net email is sponsored by the JBoss Inc.  Get Certified Today
Register for a JBoss Training Course.  Free Certification Exam
for All Training Attendees Through End of 2005. For more info visit:
http://ads.osdn.com/?ad_id=7628&alloc_id=16845&op=click
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: Another angle on JACK MIDI

Simon Jenkins
On Tue, 2005-11-15 at 12:30 +0100, Alfons Adriaensen wrote:

>[lots of stuff]

Interesting mail. I could argue with some parts, have been educated by
others, but maybe its time to see if there's some agreement to be had?
That way, decision makers can decide, coders can code, users can have
their MIDI, and I can switch back to lurk mode. (At least until I've
coded up proof of concept for that "virtual clients" thing I went on
about a while back). So I've got three proposals - one of them is
actually yours. They can't all be my favorite, but I could live with any
of them.

Proposal 1: Your int.float compromise.

Make the sample position an integer and the sub-sample position a float.

I'm a bit worried that this could be "lose-lose" rather than "win-win",
but still, it gets the apps which want integer timestamps completely out
of the fire and leaves "your" kind of app and "my" kind of app with
similar amounts of work to do instead of heaping it all on one or the
other.


Proposal 2: Let the future decide.

Choose float or fixed point - (toss a coin, whatever) - but hide access
to the timestamp field behind macros or inlines.

This would make accessing the "chosen" format trivial whilst accessing
the "rejected" format would be costly. But the decision could be
reviewed and reversed when there is real data about real apps. Also, if
it turned out that which is best depends heavily on (eg) what processor
is being used (/and/ if one was not audibly inferior to the other), then
JACK could even be compiled with the appropriate option according to the
circumstance.


Proposal 3: A combination of the above.

Make sample position an integer, sub-sample position a whatever hidden
behind macros/inlines.

Apps which want integers are out of the fire, the problem where floats
would lose precision towards the end of a buffer is solved, we get to
look at real data before a final decision. Altogether, my favorite.



So Fons: I can live with any of these. Can you?
Commentators/voters/stakeholders: Any comments, votes or (erm) stakes?
Paul: IIRC you said you were going to weigh in on this...

Cheers

Simon






-------------------------------------------------------
This SF.Net email is sponsored by the JBoss Inc.  Get Certified Today
Register for a JBoss Training Course.  Free Certification Exam
for All Training Attendees Through End of 2005. For more info visit:
http://ads.osdn.com/?ad_id=7628&alloc_id=16845&op=click
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: Another angle on JACK MIDI

Dave Robillard
On Tue, 2005-15-11 at 23:44 +0000, Simon Jenkins wrote:

> On Tue, 2005-11-15 at 12:30 +0100, Alfons Adriaensen wrote:
>
> >[lots of stuff]
>
> Interesting mail. I could argue with some parts, have been educated by
> others, but maybe its time to see if there's some agreement to be had?
> That way, decision makers can decide, coders can code, users can have
> their MIDI, and I can switch back to lurk mode. (At least until I've
> coded up proof of concept for that "virtual clients" thing I went on
> about a while back). So I've got three proposals - one of them is
> actually yours. They can't all be my favorite, but I could live with any
> of them.
>
> Proposal 1: Your int.float compromise.
>
> Make the sample position an integer and the sub-sample position a float.
>
> I'm a bit worried that this could be "lose-lose" rather than "win-win",
> but still, it gets the apps which want integer timestamps completely out
> of the fire and leaves "your" kind of app and "my" kind of app with
> similar amounts of work to do instead of heaping it all on one or the
> other.
>
>
> Proposal 2: Let the future decide.
>
> Choose float or fixed point - (toss a coin, whatever) - but hide access
> to the timestamp field behind macros or inlines.
>
> This would make accessing the "chosen" format trivial whilst accessing
> the "rejected" format would be costly. But the decision could be
> reviewed and reversed when there is real data about real apps. Also, if
> it turned out that which is best depends heavily on (eg) what processor
> is being used (/and/ if one was not audibly inferior to the other), then
> JACK could even be compiled with the appropriate option according to the
> circumstance.
>
>
> Proposal 3: A combination of the above.
>
> Make sample position an integer, sub-sample position a whatever hidden
> behind macros/inlines.
>
> Apps which want integers are out of the fire, the problem where floats
> would lose precision towards the end of a buffer is solved, we get to
> look at real data before a final decision. Altogether, my favorite.

I don't think hiding this behind function calls is really possible.
This timestamp is in a struct the user deals with directly, and I can't
see any way of changing that which is even remotely a good idea.

I think I like the integer offset + float fractional.  Simple apps who
don't want fractional get their offset, and if an app wants a full
floating point offset all they have to do is sum the two (which is far
less confusing and probably faster than any fixed point converting
acrobatics).

How expensive is int+float compared to casting float->int?

-DR-



-------------------------------------------------------
This SF.Net email is sponsored by the JBoss Inc.  Get Certified Today
Register for a JBoss Training Course.  Free Certification Exam
for All Training Attendees Through End of 2005. For more info visit:
http://ads.osdn.com/?ad_id=7628&alloc_id=16845&op=click
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: Jack MIDI revised API

Dave Robillard
In reply to this post by deviant
On Sun, 2005-13-11 at 19:24 -0800, ian esten wrote:
> this functionality must be something
> that jack provides under the hood, to support the different api's, and
> should not be exposed to clients.

On the topic of exposing to clients, I'm taking a look at this API now,
and I really see no reason why this event _buffer_ is being exposed to
the client at all.  They're not allowed to access it whatsoever, so why
expose it in the first place?

I think it would be much cleaner if the event API took jack_port_t's
instead of this void* pointer (typedeffed though it may be...).  Is
there any reason why not?

-DR-



-------------------------------------------------------
This SF.Net email is sponsored by the JBoss Inc.  Get Certified Today
Register for a JBoss Training Course.  Free Certification Exam
for All Training Attendees Through End of 2005. For more info visit:
http://ads.osdn.com/?ad_id=7628&alloc_id=16845&op=click
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: Another angle on JACK MIDI

Simon Jenkins
In reply to this post by Dave Robillard
On Wed, 2005-11-16 at 14:28 +1100, Dave Robillard wrote:

> On Tue, 2005-15-11 at 23:44 +0000, Simon Jenkins wrote:
> > On Tue, 2005-11-15 at 12:30 +0100, Alfons Adriaensen wrote:
> >
> > >[lots of stuff]
> >
> >  
> > Proposal 3: A combination of the above.
> >
> > Make sample position an integer, sub-sample position a whatever hidden
> > behind macros/inlines.
> >
> > Apps which want integers are out of the fire, the problem where floats
> > would lose precision towards the end of a buffer is solved, we get to
> > look at real data before a final decision. Altogether, my favorite.
>
> I don't think hiding this behind function calls is really possible.
> This timestamp is in a struct the user deals with directly, and I can't
> see any way of changing that which is even remotely a good idea.

Just to clarify what I meant, I meant providing something like:

inline unsigned short jack_get_timestamp_intpart ( event_struct *s );
inline unsigned int jack_get_timestamp_fracpart ( event_struct *s );
inline float jack_get_timestamp_float( event_struct *s );
inline void jack_put_timestamp_fixed( event_struct *s,
        unsigned short i, unsigned int f );
inline void jack_put_timestamp_float( event_struct *s, float t );

(Typing fast... got work... something _like_ these).

Depending on what was _actually_ stored in the structure, 2 or 3 of
these would be zero overhead direct accesses to the structure. The other
2 or 3 would have to do the conversion, but we could make sure they did
the "best" conversion. We could then change our minds about which 2 or 3
incurred the overhead in the future. I'll agree its slightly ugly, but
its flexible.

> I think I like the integer offset + float fractional.  Simple apps who
> don't want fractional get their offset, and if an app wants a full
> floating point offset all they have to do is sum the two (which is far
> less confusing and probably faster than any fixed point converting
> acrobatics).
>
> How expensive is int+float compared to casting float->int?

I guess if truncation is done by hand ( round(n - 0.5) ) they might be
about the same. But its still better because apps that want the int
don't /have/ to cast. I've always maintained that apps which want it as
float will probably /also/ need it as int at some point (if they're ever
planning to put data in the buffer), so everybody saves.

Simon




-------------------------------------------------------
This SF.Net email is sponsored by the JBoss Inc.  Get Certified Today
Register for a JBoss Training Course.  Free Certification Exam
for All Training Attendees Through End of 2005. For more info visit:
http://ads.osdn.com/?ad_id=7628&alloc_id=16845&op=click
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: Another angle on JACK MIDI

Simon Jenkins
In reply to this post by Simon Jenkins
On Tue, 2005-11-15 at 22:55 -0600, Jack O'Quin wrote:
> Proposal 4: use double

I was looking for something between my position & Fons'. This is more
like Fons' position on steroids. ;) But OK. In which case can we also
have...

Proposal 5: use fixed point.

Simon




-------------------------------------------------------
This SF.Net email is sponsored by the JBoss Inc.  Get Certified Today
Register for a JBoss Training Course.  Free Certification Exam
for All Training Attendees Through End of 2005. For more info visit:
http://ads.osdn.com/?ad_id=7628&alloc_id=16845&op=click
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: Another angle on JACK MIDI

stefan kersten
In reply to this post by Simon Jenkins
On Wed, Nov 16, 2005 at 09:47:11AM +0000, Simon Jenkins wrote:
> > I think I like the integer offset + float fractional.  Simple apps who
> > don't want fractional get their offset, and if an app wants a full
> > floating point offset all they have to do is sum the two (which is far
> > less confusing and probably faster than any fixed point converting
> > acrobatics).
> >
> > How expensive is int+float compared to casting float->int?

apart from the fp control word problem on i386 afaik you
have to go through memory to transfer values between fp and
gp registers on both intel and ppc (at least when not using
the vector unit).

> I guess if truncation is done by hand ( round(n - 0.5) ) they might be
> about the same. But its still better because apps that want the int
> don't /have/ to cast. I've always maintained that apps which want it as
> float will probably /also/ need it as int at some point (if they're ever
> planning to put data in the buffer), so everybody saves.

many (?) applications abstract from the driver and have
their own internal event dispatching mechanism, where
timestamps already are expressed as, say, floating point
buffer offsets (e.g. as in supercollider). truncation
doesn't happen in the process function but deep down in the
application, so it's inconvenient having a timestamp format
comprised of two parts which you have to reassemble anyway.

i'd vote for a floating point timestamp (preferably double
precision) or a 64 bit fixed point format with accessor
macros for efficient conversion in either direction. the
cost of per event float<->int conversion seems rather small
compared to the rest of the process loop ...

<sk>


-------------------------------------------------------
This SF.Net email is sponsored by the JBoss Inc.  Get Certified Today
Register for a JBoss Training Course.  Free Certification Exam
for All Training Attendees Through End of 2005. For more info visit:
http://ads.osdn.com/?ad_id=7628&alloc_id=16845&op=click
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
12