~ubuntu-branches/ubuntu/trusty/jack-audio-connection-kit/trusty

« back to all changes in this revision

Viewing changes to example-clients/intime.c

  • Committer: Bazaar Package Importer
  • Author(s): Luca Falavigna
  • Date: 2008-12-06 11:05:15 UTC
  • mfrom: (4.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20081206110515-xa9v9pajr9jqvfvg
Tags: 0.115.6-1ubuntu1
* Merge from Debian unstable, remaining Ubuntu changes:
  - Redirect stderr in bash completion (Debian #504488).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 = 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 *load_init)
 
126
{
 
127
        JackTimebaseCallback callback = timebbt;
 
128
 
 
129
        int rc = sscanf(load_init, " %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
        } else {
 
137
                int len = strlen(load_init);
 
138
                if ((len > 0) && (strncmp(load_init, "timecode", len) == 0))
 
139
                        callback = timecode;
 
140
        }
 
141
 
 
142
        if (jack_set_timebase_callback(client, 0, callback, NULL) != 0) {
 
143
                fprintf (stderr, "Unable to take over timebase.\n");
 
144
                return 1;               /* terminate */
 
145
        }
 
146
 
 
147
        fprintf (stderr, "Internal timebase master defined.\n");
 
148
        jack_activate (client);
 
149
        return 0;                       /* success */
 
150
}
 
151
 
 
152
/* before unloading */
 
153
void
 
154
jack_finish (void *arg)
 
155
{
 
156
        fprintf (stderr, "Internal timebase client exiting.\n");
 
157
}