Browse Source

intime enhancements; TODO update

git-svn-id: svn+ssh://jackaudio.org/trunk/jack@490 0c269be4-1314-0410-8aa9-9f06e86f4224
tags/0.109.0
joq 22 years ago
parent
commit
c98f37986a
2 changed files with 103 additions and 14 deletions
  1. +3
    -1
      TODO
  2. +100
    -13
      example-clients/intime.c

+ 3
- 1
TODO View File

@@ -17,15 +17,16 @@ TO BE DECIDED (owner)

TODO for 1.0 (owner)

- resolve helper thread design question?
- API to change buffer size (joq)

TODO post-1.0

- jack session handling (taybin)
- TBD

TODO general (owner)

- better scheme for handling machine and system dependencies (joq)
- don't build static libraries of drivers and ip-clients (kaiv)
- add explanation of protocol versioning to README.developers (kaiv)
- proper handling of client return values in libjack (kaiv)
@@ -62,5 +63,6 @@ CLOSED (date,who,comment)
- finalize discussion on transport API, and implement (2003/08/04, joq)
- whether to hide the transport.h structs from clients (2003/08/04, joq)
- define transport info struct contents (2003/08/13, joq)
- resolve helper thread design question? (2003/08/31, joq)

-----------------------------------------------------------------------

+ 100
- 13
example-clients/intime.c View File

@@ -1,13 +1,10 @@
/*
* intime.c -- JACK internal timebase master example client.
*
* This demonstrates how to write an internal timebase master client.
* It fills in extended timecode fields using the trivial assumption
* that we are running at nominal speed, hence there is no drift.
*
* To run, first start `jackd', then `jack_load intime intime'.
*
* Copyright (C) 2003 Jack O'Quin.
* To run: first start `jackd', then `jack_load intime intime 6/8,180bpm'.
*/

/* Copyright (C) 2003 Jack O'Quin.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -25,19 +22,93 @@
*/

#include <stdio.h>
#include <string.h>
#include <jack/jack.h>

/* Time and tempo variables, global to the entire transport timeline.
* There is no attempt to keep a true tempo map. The default time
* signature is "march time": 4/4, 120bpm
*/
float time_beats_per_bar = 4.0;
float time_beat_type = 1.0 / 4.0;
double time_ticks_per_beat = 1920.0;
double time_beats_per_minute = 120.0;

/* BBT timebase callback.
*
* Runs in the process thread. Realtime, must not wait.
*/
void
timebbt (jack_transport_state_t state, jack_nframes_t nframes,
jack_position_t *pos, int new_pos, void *arg)
{
double min; /* minutes since frame 0 */
long abs_tick; /* ticks since frame 0 */
long abs_beat; /* beats since frame 0 */

if (new_pos) {

pos->valid = JackPositionBBT;
pos->beats_per_bar = time_beats_per_bar;
pos->beat_type = time_beat_type;
pos->ticks_per_beat = time_ticks_per_beat;
pos->beats_per_minute = time_beats_per_minute;

/* Compute BBT info from frame number. This is
* relatively simple here, but would become complex if
* we supported tempo or time signature changes at
* specific locations in the transport timeline. I
* make no claims for the numerical accuracy or
* efficiency of these calculations. */

/* timebase callback
min = pos->frame / ((double) pos->frame_rate * 60.0);
abs_tick = min * pos->beats_per_minute * pos->ticks_per_beat;
abs_beat = abs_tick / pos->ticks_per_beat;

pos->bar = abs_beat / pos->beats_per_bar;
pos->beat = abs_beat - (pos->bar * pos->beats_per_bar) + 1;
pos->tick = abs_tick - (abs_beat * pos->ticks_per_beat);
pos->bar_start_tick = pos->bar * pos->beats_per_bar *
pos->ticks_per_beat;
pos->bar++; /* adjust start to bar 1 */

/* some debug code... */
fprintf(stderr, "\nnew position: %" PRIu32 "\tBBT: %3"
PRIi32 "|%" PRIi32 "|%04" PRIi32 "\n",
pos->frame, pos->bar, pos->beat, pos->tick);

} else {

/* Compute BBT info based on previous period. */
pos->tick += (nframes * pos->ticks_per_beat *
pos->beats_per_minute / (pos->frame_rate * 60));

while (pos->tick >= pos->ticks_per_beat) {
pos->tick -= pos->ticks_per_beat;
if (++pos->beat > pos->beats_per_bar) {
pos->beat = 1;
++pos->bar;
pos->bar_start_tick += (pos->beats_per_bar *
pos->ticks_per_beat);
}
}
}
}

/* experimental timecode callback
*
* Fill in extended timecode fields using the trivial assumption that
* we are running at nominal speed, hence with no drift.
*
* It would probably be faster to compute frame_time without the
* conditional expression. But, it demonstrates the invariant:
* conditional expression. But, this demonstrates the invariant:
* next_time[i] == frame_time[i+1], unless a reposition occurs.
*
* Runs in the process thread. Realtime, must not wait.
*/
void timebase(jack_transport_state_t state, jack_nframes_t nframes,
jack_position_t *pos, int new_pos, void *arg)
void
timecode (jack_transport_state_t state, jack_nframes_t nframes,
jack_position_t *pos, int new_pos, void *arg)
{
/* nominal transport speed */
double seconds_per_frame = 1.0 / (double) pos->frame_rate;
@@ -51,9 +122,25 @@ void timebase(jack_transport_state_t state, jack_nframes_t nframes,

/* after internal client loaded */
int
jack_initialize (jack_client_t *client, const char *data)
jack_initialize (jack_client_t *client, const char *arg)
{
if (jack_set_timebase_callback(client, 0, timebase, NULL) != 0) {
JackTimebaseCallback callback = timebbt;

int rc = sscanf(arg, " %f/%f, %lf bpm ", &time_beats_per_bar,
&time_beat_type, &time_beats_per_minute);

if (rc > 0) {
fprintf (stderr, "counting %.1f/%.1f at %.2f bpm\n",
time_beats_per_bar, time_beat_type,
time_beats_per_minute);
time_beat_type = 1.0 / time_beat_type;
} else {
int len = strlen(arg);
if ((len > 0) && (strncmp(arg, "timecode", len) == 0))
callback = timecode;
}

if (jack_set_timebase_callback(client, 0, callback, NULL) != 0) {
fprintf (stderr, "Unable to take over timebase.\n");
return 1;
}


Loading…
Cancel
Save