How to measure time intervals with JACK?

View: New views
9 Messages — Rating Filter:   Alert me  

How to measure time intervals with JACK?

by trece ocho :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi, I'm new at JACK and I'm trying to write some code to measure how
much people synchronize with metronomes.
I hope my question is just a basic one, but i have to measure time
intervals with JACK in "realtime". I mean, not recording audio and
THEN analyze it and measure time between two events (like zero
crossings).

I coulnd't see how to achieve this. I'm trying just modifying the
simple_client.c example, but i'm clueless when it comes to time
measurement.

For example, how can I measure the time between zero-crossings (of the
signal at the input of the soundcard)? In particular, how can I
measure that when the two zero crossings are further apart than the
time of the buffer?

I red the reference, but I can't figure out what "usecs" is or means
("monotonic, free-rolling" ? )

ANYTHING helps...

Sorry for my english,
cheers from Argentina,
trece.
_______________________________________________
Jack-Devel mailing list
Jack-Devel@...
http://lists.jackaudio.org/listinfo.cgi/jack-devel-jackaudio.org

Re: How to measure time intervals with JACK?

by Fons Adriaensen-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Sat, May 10, 2008 at 12:47:33AM -0300, trece ocho wrote:

> For example, how can I measure the time between zero-crossings (of the
> signal at the input of the soundcard)? In particular, how can I
> measure that when the two zero crossings are further apart than the
> time of the buffer?

Clearly you need to 'remember' some data from one call to your process
callback to the next.

There are several ways to do this.

The quick and dirty one is to use global variables.

The clean way is to use the "arg" parameter you give when registering
your callback. You get it back in each callback. Use it as a pointer
to a struct (C) or object (C++) that contains the data you want to
keep.

Inding the distance between zero crossings.

For example, you get a buffer wich contains a zero crossing at offset
K, and the buffer is N samples long. You remember the value D = N - K.
That is how long ago the last zero crossing was as seen from the
the start of the next buffer. You store D somewhere you can find it
back next time, as explained above.

You get the next buffer. Suppose there is no zero crossing. You add
N to D.

You get the nex buffer, and there is a zero crossing at position K
The distance to the last one is D + K. The time between the two (in
seconds) is this value divided by the sample frequency (use floats
or doubles for this).


Ciao,


--
FA

Laboratorio di Acustica ed Elettroacustica
Parma, Italia

Lascia la spina, cogli la rosa.

_______________________________________________
Jack-Devel mailing list
Jack-Devel@...
http://lists.jackaudio.org/listinfo.cgi/jack-devel-jackaudio.org

Parent Message unknown Re: How to measure time intervals with JACK?

by Gabriel M. Beddingfield :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


Hi Fons,

Thanks for your answers!  Also, I'm sorry that I sent it to you rather
than the list.  FWIW, I wasn't the original asker... but I've asked a
similar question in the past with no responses.

> Maybe this is not true but then you to explain more exactly you want
> to do.

Well, for me, I've been working on a tap-tempo thing that controls the
Jack Transport (for use in live performance).  So, I'm looking for
real-time intervals (not absolute time).  When I last worked on it, I
was confused about what notion of time I should use to record taps.

   * Using transport frames for this is only valid
     while the transport is rolling and not freewheeling.

   * Using absolute sample frames is only valid as
     long as jack isn't freewheeling.

   * I couldn't find a good definition of freewheeling
     anywhere -- so I wasn't sure what it meant or when
     it happens.

   * If the sample rate changes, time calcs using frame
     rates get messy.

   * Using timestamps (usecs) looks like a good way, but
     it appears to be very machine-dependent and I don't
     think there's a mechanism in libjack to make the
     conversion to real-time intervals (e.g.
     jack_usec_per_sec()).  The documentation for usecs
     doesn't guarantee any sort of conversion rate... only
     that it's always increasing (monotonic) and never resets
     (free-rolling).

I don't want to be another application that is constantly using the
gettimeofday() call... especially since jack and the like are probably
already doing this for me.  Once I get clarity on these things, I would
gladly send a patch that updates the documentation.

Peace,
Gabriel

_______________________________________________
Jack-Devel mailing list
Jack-Devel@...
http://lists.jackaudio.org/listinfo.cgi/jack-devel-jackaudio.org

Re: How to measure time intervals with JACK?

by Fons Adriaensen-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Sat, May 10, 2008 at 09:44:15AM -0500, Gabriel M. Beddingfield wrote:

> Well, for me, I've been working on a tap-tempo thing that controls the Jack
> Transport (for use in live performance).  So, I'm looking for real-time
> intervals (not absolute time).  When I last worked on it, I was confused
> about what notion of time I should use to record taps.

It's still not clear at all what you want to do. Measure a tempo ?
Make jack_transport start after you tapped two measures ? What is
it ?

Please explain what you mean by 'real time' and 'real time intervals',
if that is not the same as absolute time.

If you want to measure the time *between* two or more events
in an audio stream you don't need any clock or timer. Just
count samples and divide by the sample frequency.

>   * Using transport frames for this is only valid
>     while the transport is rolling and not freewheeling.
>
>   * Using absolute sample frames is only valid as
>     long as jack isn't freewheeling.

What are 'absolute frames' ?? Anyway forget freewheeling.
There is _no meaningfull concept of time_ when jack is
freewheeling. 'Live' and freewheeling are contradictory.
You can count samples and convert differences to time
intervals, but they only tell you what the timing would
be if jack were not freewheeling.

>   * I couldn't find a good definition of freewheeling
>     anywhere -- so I wasn't sure what it meant or when
>     it happens.

Just forget about it. You don't want it.

>   * If the sample rate changes, time calcs using frame
>     rates get messy.

No. You get the sample rate from jack when your app starts.
Normally the sample rate does not change as long as jack is
running. If it does, you can have a callback to inform
you of the change.  But nobody does that while an app is
running.

>   * Using timestamps (usecs) looks like a good way, but
>     it appears to be very machine-dependent and I don't
>     think there's a mechanism in libjack to make the
>     conversion to real-time intervals (e.g.
>     jack_usec_per_sec()).

usec means 'microsecond'. There are always 1000000 of them
in a second. That never changes.

Ciao,

--
FA

Laboratorio di Acustica ed Elettroacustica
Parma, Italia

Lascia la spina, cogli la rosa.

_______________________________________________
Jack-Devel mailing list
Jack-Devel@...
http://lists.jackaudio.org/listinfo.cgi/jack-devel-jackaudio.org

Re: How to measure time intervals with JACK?

by Gabriel M. Beddingfield :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Fons,

First:  Thanks a lot!  You're really clearing up a lot of stuff.

> It's still not clear at all what you want to do. Measure a tempo ?
> Make jack_transport start after you tapped two measures ? What is
> it ?

Yes.  Measure a tempo.  Make the transport start after tapping (but also
adjust the tempo while the transport is rolling).

> Please explain what you mean by 'real time' and 'real time intervals',
> if that is not the same as absolute time.

Real time (absolute):  The actual time of day, or some direct indication
of the time of day that can be mapped back to the actual day/date/time.

Real time interval:  The actual difference in time between two events.
In simple terms it's the D/S (D = number of frames between, S = sample
rate).  When you throw in freewheeling and whether or not you're
counting transport frames, I wasn't sure what to use to measure this.

> What are 'absolute frames' ?? Anyway forget freewheeling.

jack_frame_time() or jack_get_time()... as opposed to
jack_get_current_transport_frame().  However, while jack_get_time() is
sample-rate independent, it's not guaranteed to be linear.

Thanks,
Gabriel

_______________________________________________
Jack-Devel mailing list
Jack-Devel@...
http://lists.jackaudio.org/listinfo.cgi/jack-devel-jackaudio.org

Re: How to measure time intervals with JACK?

by Fons Adriaensen-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Sun, May 11, 2008 at 10:12:09PM -0500, Gabriel M. Beddingfield wrote:

> Yes.  Measure a tempo.  Make the transport start after tapping

I'll assume you tap someting like

1 - 2 - 1 2 3 - S - - - ....

and you want the transport to start on S.  

(but also adjust the tempo while the transport is rolling).

You can't change jack's speed, so I assume you mean updating
the tempo information in the transport data.

Note that for the first part, the transport can start only on
a period boundary. That will almost never be exactly the sample
corresponding to S. How you handle the remaining error depends
on what exactly you want to do with the transport. If you want
some app to start playback at S, you will have to remove the
remaining error by adjusting its start position. There are some
other complications with starting the transport in this way but
let's keep those for later.

Before we can go on, you should really understand the
following:

1. Freewheeling. Forget about it. When freewheeling jack does
not use the soundcard. There is no audio input and output.
All jack does it run as fast as the clients will permit. When
all the processing for a period is done, the next one starts
immediately. Freewheeling is used to make jack clients work as
fast as possible on *stored* data, without any consideration of
physical time.

2. When as a musician you maintain tempo, or you start a song
after a countdown like the one above, does it matter what time
it is ? When a DJ starts a track in sync with the previous one,
does he look at his watch ? You will agree that the answer is
no. This means that *you don't need 'absolute' time at all*.
Any attempt to try and use it will only lead to failure and
frustration, or in the best case, a solution that is much more
complicated than it should be. This is all about tempo (i.e.
relative timing, and speed), and you can select the time unit
(seconds, frames) and the reference time (the 'zero' of your
time scale) as you want. Since you are dealing with samples,
and these have a fixed speed, the easiest thing to do is to
'think' in samples as the time unit and only convert to more
conventional units (seconds, BPM) where it is needed.

3. Since you are dealing with samples and try to extract timing
information from them, you will need to use the sample rate if
you like it or not. There is no problem with this - it is in
effect a just a constant you get from jack. I know of no
situation or application where it could ever change while
clients are running.

4. In Jack, audio processing and transport are completely
independent of each other, except that transport states can
change only on a period boundary. Transport is just a set
of data that is passed between clients. It does not affect
anything in the audio processing part.


I'll try to give an outline of how you could make the
transport start at S (assuming that's what you want).

R = sample rate
N = period size

First we need to define a time scale, measured in samples.
It will be zero at the start of some period. You could start
counting from the first callback you get, or use jack's
built-in counter. The function jack_last_frame_time() gives
the count for the first sample of the current period. Call
it once in the first callback, then continue counting from
there by adding N in each period. Or just start from zero.

Suppose you can somehow detect the taps, and obtain the
corresponding sample counts for each of them. For the
sequence

1 - 2 - 1 2 3 - S

Let k1 be the sample index of the first '1' and k2 the
one for the '3' in the second measure. There are six
beats between them. So one beat is B = (k2 - k1) / 6
frames. The tempo is 60 * R / B in beats per minute.

We can now predict the sample count corresponding to
'S', the first beat of the first measure. Clearly this
will be S = k1 + 8 * B.

Now we need to take into account the round-trip latency
of your system. This will be close to the number of
periods 'n' that the jack backend is configured for
(the -n parameter). The adjusted start index is now
S' = S - n * N.

Given S', you can work out in which period (relative
to the current one) it will fall, and what will be
the offset within that period. You set the transport
position to minus that offset, and set the transport
state to RUNNING two periods before the one S' is in.

Note that clients can delay the transport start, but
this can be disabled.

Ciao,

--
FA

Laboratorio di Acustica ed Elettroacustica
Parma, Italia

Lascia la spina, cogli la rosa.

_______________________________________________
Jack-Devel mailing list
Jack-Devel@...
http://lists.jackaudio.org/listinfo.cgi/jack-devel-jackaudio.org

Re: How to measure time intervals with JACK?

by Gabriel M. Beddingfield :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Fons,

Fons Adriaensen wrote:
>
>> Yes.  Measure a tempo.  Make the transport start after tapping
>
> I'll assume you tap someting like
>
> 1 - 2 - 1 2 3 - S - - - ....
>
> and you want the transport to start on S.  

Yes, that's correct.  Thanks for all the other info, too.  It's helped a
lot.  You're awesome!

> Now we need to take into account the round-trip latency
> of your system. This will be close to the number of
> periods 'n' that the jack backend is configured for
> (the -n parameter). The adjusted start index is now
> S' = S - n * N.

Is there currently any way for a jack client to query this parameter
(--nperiods)?  If not... could there be?  Maybe add a new driver
interface like JackDriverNTQueryFunction to jack_driver_nt_t, and then
an API function like jack_query_backend()?  It could be used for more
than just nperiods.

In the mean-time... I'll add it as a user-option to my application.  It
just doesn't look good.  :-)

Thanks,
Gabriel

_______________________________________________
Jack-Devel mailing list
Jack-Devel@...
http://lists.jackaudio.org/listinfo.cgi/jack-devel-jackaudio.org

Re: How to measure time intervals with JACK?

by Fons Adriaensen-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Gabriel,

> Is there currently any way for a jack client to query this parameter
> (--nperiods)?  If not... could there be?  Maybe add a new driver interface
> like JackDriverNTQueryFunction to jack_driver_nt_t, and then an API
> function like jack_query_backend()?  It could be used for more than just
> nperiods.

There is as far as I know no way to query the value of the -n parameter,
but you can find the round-trip latency in frames like this:

D = jack_port_get_latency (jack_port_by_name (jack_client, "system:capture_1"))
  + jack_port_get_latency (jack_port_by_name (jack_client, "system:playback_1"));

where 'jack_client' is your jack client handle.
If you have an older Jack then "system" should be "alsa_pcm".

Ciao,

--
FA

Laboratorio di Acustica ed Elettroacustica
Parma, Italia

Lascia la spina, cogli la rosa.

_______________________________________________
Jack-Devel mailing list
Jack-Devel@...
http://lists.jackaudio.org/listinfo.cgi/jack-devel-jackaudio.org

Re: How to measure time intervals with JACK?

by Gabriel M. Beddingfield :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Fons Adriaensen wrote:
> There is as far as I know no way to query the value of the -n parameter,
> but you can find the round-trip latency in frames like this:
>
> D = jack_port_get_latency (jack_port_by_name (jack_client, "system:capture_1"))
>   + jack_port_get_latency (jack_port_by_name (jack_client, "system:playback_1"));

Thanks, Fons.  I think this would work a little better for the app.
Having the user declare primary in/out ports is a little more intuitive
than asking for the --nperiods parameter.

Thanks,
Gabriel

_______________________________________________
Jack-Devel mailing list
Jack-Devel@...
http://lists.jackaudio.org/listinfo.cgi/jack-devel-jackaudio.org
LightInTheBox - Buy quality products at wholesale price!