Re: [Jack-Devel] Jack's timing functions

PrevNext  Index
DateTue, 27 Dec 2011 11:08:49 +0100
From Florian Paul Schmidt <[hidden] at gmx dot net>
To[hidden] at lists dot jackaudio dot org
In-Reply-ToFons Adriaensen [Jack-Devel] Jack's timing functions
Follow-UpJohn Rigg Re: [Jack-Devel] Jack's timing functions
I have nothing to add except for my support for your proposal, whatever 
it's worth. Your first suggestion seems to be the least amount of work, 
so +1 :D

Flo

On 12/26/2011 06:06 PM, Fons Adriaensen wrote:
> Hello all,
>
> During the weekend I've been working on adaptive resampling
> algorithms (as required for e.g. alsa_in and similar apps).
>
> The first tentative result produces around 100 times less
> jitter on the dynamic resample ratio than alsa_in. See
> <http://kokkinizita.linuxaudio.org/linuxaudio/resample.html>,
> The difference in phase noise levels is roughly 40 dB.
>
> In fact it has reached the point where the performance is no
> longer dominated by random timing errors, but also systematic
> ones resulting from quantisation of some of the variables
> involved in the calculation (mostly frame counts expressed
> as integers) start to show up.
>
> This is very visible in the time domain test results, but even
> the frequency domain ones start to show this, Note all those
> little discrete lines in the first plot (link above) - each
> of these is the result of a deterministic error pattern.
>
> This in turn made me look into Jack's timing-related functions.
>
> One of the values I needed was the microseconds time for the
> start of the current cycle (the one filtered by the DLL). This
> is not available in the public API. It can be computed in two
> ways. The first is
> jack_frames_to_time (client, jack_last_frame_time (client));
> which is a rather convolved way to recompute an already known
> value: client->engine->current_time.current_wakeup.
>
> The second involves using jack_frames_since_cycle_start() and
> jack_get_time() and compute the result from those. This is even
> more convolved and won't produce an accurate result because:
>
> a) the usecs clock is read twice, the values used should be the
>     same but they won't,
> b) the value returned by jack_frames_since_cycle_start() is
>     quantised to an integer and precision is lost,
> c) the base usecs time used by this function is apparently not
>     the DLL filtered time but the unfiltered one.
>
> (c) in fact introduces an inconsistency in the set of time-related
> functions.
>
> So my first suggestion is to add two functions to transclient.c:
>
> jack_time_t jack_current_wakeup_time (const jack_client_t *client)
> {
>      return client->engine->frame_timer.current_wakeup;
> }
>
> jack_time_t jack_next_wakeup_time (const jack_client_t *client)
> {
>      return client->engine->frame_timer.next_wakeup;
> }
>
> which together with jack_last_frame_time() provide all the
> info a client could need to do its own calculations to full
> precision.
>
> Note that it is perfectly safe to read these three values in
> the process callback even without the 'guards' used to ensure
> an atomic copy in jack_read_frame_time() - a new cycle isn't
> supposed to start at that time (and if it does there is bigger
> trouble ahead anyway).
>
> An alternative would be to provide a single function to allow
> a client to read all three in a single call, with or without
> guards.
>
> Another way to provide better precision would be to let
> jack_frames_since_cycle_start() return a double or float,
> and to modify the two frames<->usecs conversion functions
> to accept/return a float or double frametime referenced
> to the start of the cycle (i.e. removing the potentially
> large offset, which is given by jack_last_frame_time()
> anyway).
>
> Ciao,
>
>
PrevNext  Index

1324980542.16108_0.ltw:2,a <4EF99931.1030809 at gmx dot net>