~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
JACK/example-clients/intime.c


** Warning: Cannot open xref database.

1 /* 2 * intime.c -- JACK internal timebase master example client. 3 * 4 * To run: first start `jackd', then `jack_load intime intime 6/8,180bpm'. 5 */ 6 7 /* Copyright (C) 2003 Jack O'Quin. 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22 */ 23 24 #include <stdio.h> 25 #include <string.h> 26 #include <jack/jack.h> 27 28 /* Time and tempo variables, global to the entire transport timeline. 29 * There is no attempt to keep a true tempo map. The default time 30 * signature is "march time": 4/4, 120bpm 31 */ 32 float time_beats_per_bar = 4.0; 33 float time_beat_type = 1.0 / 4.0; 34 double time_ticks_per_beat = 1920.0; 35 double time_beats_per_minute = 120.0; 36 37 /* BBT timebase callback. 38 * 39 * Runs in the process thread. Realtime, must not wait. 40 */ 41 void 42 timebbt (jack_transport_state_t state, jack_nframes_t nframes, 43 jack_position_t *pos, int new_pos, void *arg) 44 { 45 double min; /* minutes since frame 0 */ 46 long abs_tick; /* ticks since frame 0 */ 47 long abs_beat; /* beats since frame 0 */ 48 49 if (new_pos) { 50 51 pos->valid = JackPositionBBT; 52 pos->beats_per_bar = time_beats_per_bar; 53 pos->beat_type = time_beat_type; 54 pos->ticks_per_beat = time_ticks_per_beat; 55 pos->beats_per_minute = time_beats_per_minute; 56 57 /* Compute BBT info from frame number. This is 58 * relatively simple here, but would become complex if 59 * we supported tempo or time signature changes at 60 * specific locations in the transport timeline. I 61 * make no claims for the numerical accuracy or 62 * efficiency of these calculations. */ 63 64 min = pos->frame / ((double) pos->frame_rate * 60.0); 65 abs_tick = min * pos->beats_per_minute * pos->ticks_per_beat; 66 abs_beat = abs_tick / pos->ticks_per_beat; 67 68 pos->bar = abs_beat / pos->beats_per_bar; 69 pos->beat = abs_beat - (pos->bar * pos->beats_per_bar) + 1; 70 pos->tick = abs_tick - (abs_beat * pos->ticks_per_beat); 71 pos->bar_start_tick = pos->bar * pos->beats_per_bar * 72 pos->ticks_per_beat; 73 pos->bar++; /* adjust start to bar 1 */ 74 75 /* some debug code... */ 76 fprintf(stderr, "\nnew position: %" PRIu32 "\tBBT: %3" 77 PRIi32 "|%" PRIi32 "|%04" PRIi32 "\n", 78 pos->frame, pos->bar, pos->beat, pos->tick); 79 80 } else { 81 82 /* Compute BBT info based on previous period. */ 83 pos->tick += (nframes * pos->ticks_per_beat * 84 pos->beats_per_minute / (pos->frame_rate * 60)); 85 86 while (pos->tick >= pos->ticks_per_beat) { 87 pos->tick -= pos->ticks_per_beat; 88 if (++pos->beat > pos->beats_per_bar) { 89 pos->beat = 1; 90 ++pos->bar; 91 pos->bar_start_tick += (pos->beats_per_bar * 92 pos->ticks_per_beat); 93 } 94 } 95 } 96 } 97 98 /* experimental timecode callback 99 * 100 * Fill in extended timecode fields using the trivial assumption that 101 * we are running at nominal speed, hence with no drift. 102 * 103 * It would probably be faster to compute frame_time without the 104 * conditional expression. But, this demonstrates the invariant: 105 * next_time[i] == frame_time[i+1], unless a reposition occurs. 106 * 107 * Runs in the process thread. Realtime, must not wait. 108 */ 109 void 110 timecode (jack_transport_state_t state, jack_nframes_t nframes, 111 jack_position_t *pos, int new_pos, void *arg) 112 { 113 /* nominal transport speed */ 114 double seconds_per_frame = 1.0 / (double) pos->frame_rate; 115 116 pos->valid = JackPositionTimecode; 117 pos->frame_time = (new_pos? 118 pos->frame * seconds_per_frame: 119 pos->next_time); 120 pos->next_time = (pos->frame + nframes) * seconds_per_frame; 121 } 122 123 /* after internal client loaded */ 124 int 125 jack_initialize (jack_client_t *client, const char *arg) 126 { 127 JackTimebaseCallback callback = timebbt; 128 129 int rc = sscanf(arg, " %f/%f, %lf bpm ", &time_beats_per_bar, 130 &time_beat_type, &time_beats_per_minute); 131 132 if (rc > 0) { 133 fprintf (stderr, "counting %.1f/%.1f at %.2f bpm\n", 134 time_beats_per_bar, time_beat_type, 135 time_beats_per_minute); 136 time_beat_type = 1.0 / time_beat_type; 137 } else { 138 int len = strlen(arg); 139 if ((len > 0) && (strncmp(arg, "timecode", len) == 0)) 140 callback = timecode; 141 } 142 143 if (jack_set_timebase_callback(client, 0, callback, NULL) != 0) { 144 fprintf (stderr, "Unable to take over timebase.\n"); 145 return 1; 146 } 147 148 fprintf (stderr, "Internal timebase master defined.\n"); 149 jack_activate (client); 150 return 0; 151 } 152 153 /* before unloading */ 154 void 155 jack_finish (void) 156 { 157 fprintf (stderr, "Internal timebase client exiting.\n"); 158 } 159

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.