** Warning: Cannot open xref database.
1 /*
2 Copyright (C) 2002 Anthony Van Groningen
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <errno.h>
22 #include <unistd.h>
23 #include <math.h>
24 #include <jack/jack.h>
25 #include <jack/transport.h>
26 #include <getopt.h>
27 #include <string.h>
28
29 typedef jack_default_audio_sample_t sample_t;
30
31 const double PI = 3.14;
32
33 jack_client_t *client;
34 jack_port_t *output_port;
35 unsigned long sr;
36 int freq = 880;
37 int bpm;
38 jack_nframes_t tone_length, wave_length;
39 sample_t *wave;
40 long offset = 0;
41 int transport_aware = 0;
42 jack_transport_state_t transport_state;
43
44 void
45 usage ()
46
47 {
48 fprintf (stderr, "\n"
49 "usage: jack_metro \n"
50 " [ --frequency OR -f frequency (in Hz) ]\n"
51 " [ --amplitude OR -A maximum amplitude (between 0 and 1) ]\n"
52 " [ --duration OR -D duration (in ms) ]\n"
53 " [ --attack OR -a attack (in percent of duration) ]\n"
54 " [ --decay OR -d decay (in percent of duration) ]\n"
55 " [ --name OR -n jack name for metronome client ]\n"
56 " [ --transport OR -t transport aware ]\n"
57 " --bpm OR -b beats per minute\n"
58 );
59 }
60
61 void
62 process_silence (jack_nframes_t nframes)
63 {
64 sample_t *buffer = (sample_t *) jack_port_get_buffer (output_port, nframes);
65 memset (buffer, 0, sizeof (jack_default_audio_sample_t) * nframes);
66 }
67
68 void
69 process_audio (jack_nframes_t nframes)
70 {
71
72 sample_t *buffer = (sample_t *) jack_port_get_buffer (output_port, nframes);
73 jack_nframes_t frames_left = nframes;
74
75 while (wave_length - offset < frames_left) {
76 memcpy (buffer + (nframes - frames_left), wave + offset, sizeof (sample_t) * (wave_length - offset));
77 frames_left -= wave_length - offset;
78 offset = 0;
79 }
80 if (frames_left > 0) {
81 memcpy (buffer + (nframes - frames_left), wave + offset, sizeof (sample_t) * frames_left);
82 offset += frames_left;
83 }
84 }
85
86 int
87 process (jack_nframes_t nframes, void *arg)
88 {
89 if (transport_aware) {
90 jack_position_t pos;
91
92 if (jack_transport_query (client, &pos)
93 != JackTransportRolling) {
94
95 process_silence (nframes);
96 return 0;
97 }
98 offset = pos.frame % wave_length;
99 }
100 process_audio (nframes);
101 return 0;
102 }
103
104 int
105 sample_rate_change () {
106 printf("Sample rate has changed! Exiting...\n");
107 exit(-1);
108 }
109
110 int
111 main (int argc, char *argv[])
112 {
113
114 sample_t scale;
115 int i, attack_length, decay_length;
116 double *amp;
117 double max_amp = 0.5;
118 int option_index;
119 int opt;
120 int got_bpm = 0;
121 int attack_percent = 1, decay_percent = 10, dur_arg = 100;
122 char *client_name = 0;
123 char *bpm_string = "bpm";
124 int verbose = 0;
125
126 const char *options = "f:A:D:a:d:b:n:thv";
127 struct option long_options[] =
128 {
129 {"frequency", 1, 0, 'f'},
130 {"amplitude", 1, 0, 'A'},
131 {"duration", 1, 0, 'D'},
132 {"attack", 1, 0, 'a'},
133 {"decay", 1, 0, 'd'},
134 {"bpm", 1, 0, 'b'},
135 {"name", 1, 0, 'n'},
136 {"transport", 0, 0, 't'},
137 {"help", 0, 0, 'h'},
138 {"verbose", 0, 0, 'v'},
139 {0, 0, 0, 0}
140 };
141
142 while ((opt = getopt_long (argc, argv, options, long_options, &option_index)) != EOF) {
143 switch (opt) {
144 case 'f':
145 if ((freq = atoi (optarg)) <= 0) {
146 fprintf (stderr, "invalid frequency\n");
147 return -1;
148 }
149 break;
150 case 'A':
151 if (((max_amp = atof (optarg)) <= 0)|| (max_amp > 1)) {
152 fprintf (stderr, "invalid amplitude\n");
153 return -1;
154 }
155 break;
156 case 'D':
157 dur_arg = atoi (optarg);
158 fprintf (stderr, "durarg = %u\n", dur_arg);
159 break;
160 case 'a':
161 if (((attack_percent = atoi (optarg)) < 0) || (attack_percent > 100)) {
162 fprintf (stderr, "invalid attack percent\n");
163 return -1;
164 }
165 break;
166 case 'd':
167 if (((decay_percent = atoi (optarg)) < 0) || (decay_percent > 100)) {
168 fprintf (stderr, "invalid decay percent\n");
169 return -1;
170 }
171 break;
172 case 'b':
173 got_bpm = 1;
174 if ((bpm = atoi (optarg)) < 0) {
175 fprintf (stderr, "invalid bpm\n");
176 return -1;
177 }
178 bpm_string = (char *) malloc ((strlen (optarg) + 4) * sizeof (char));
179 strcpy (bpm_string, optarg);
180 strcat (bpm_string, "_bpm");
181 break;
182 case 'n':
183 client_name = (char *) malloc (strlen (optarg) * sizeof (char));
184 strcpy (client_name, optarg);
185 break;
186 case 'v':
187 verbose = 1;
188 break;
189 case 't':
190 transport_aware = 1;
191 break;
192 default:
193 fprintf (stderr, "unknown option %c\n", opt);
194 case 'h':
195 usage ();
196 return -1;
197 }
198 }
199 if (!got_bpm) {
200 fprintf (stderr, "bpm not specified\n");
201 usage ();
202 return -1;
203 }
204
205 /* Initial Jack setup, get sample rate */
206 if (!client_name) {
207 client_name = (char *) malloc (9 * sizeof (char));
208 strcpy (client_name, "metro");
209 }
210 if ((client = jack_client_new (client_name)) == 0) {
211 fprintf (stderr, "jack server not running?\n");
212 return 1;
213 }
214 jack_set_process_callback (client, process, 0);
215 output_port = jack_port_register (client, bpm_string, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
216
217 sr = jack_get_sample_rate (client);
218
219 /* setup wave table parameters */
220 wave_length = 60 * sr / bpm;
221 tone_length = sr * dur_arg / 1000;
222 attack_length = tone_length * attack_percent / 100;
223 decay_length = tone_length * decay_percent / 100;
224 scale = 2 * PI * freq / sr;
225
226 if (tone_length >= wave_length) {
227 fprintf (stderr, "invalid duration (tone length = %" PRIu32
228 ", wave length = %" PRIu32 "\n", tone_length,
229 wave_length);
230 return -1;
231 }
232 if (attack_length + decay_length > (int)tone_length) {
233 fprintf (stderr, "invalid attack/decay\n");
234 return -1;
235 }
236
237 /* Build the wave table */
238 wave = (sample_t *) malloc (wave_length * sizeof(sample_t));
239 amp = (double *) malloc (tone_length * sizeof(double));
240
241 for (i = 0; i < attack_length; i++) {
242 amp[i] = max_amp * i / ((double) attack_length);
243 }
244 for (i = attack_length; i < (int)tone_length - decay_length; i++) {
245 amp[i] = max_amp;
246 }
247 for (i = (int)tone_length - decay_length; i < (int)tone_length; i++) {
248 amp[i] = - max_amp * (i - (double) tone_length) / ((double) decay_length);
249 }
250 for (i = 0; i < (int)tone_length; i++) {
251 wave[i] = amp[i] * sin (scale * i);
252 }
253 for (i = tone_length; i < (int)wave_length; i++) {
254 wave[i] = 0;
255 }
256
257 if (jack_activate (client)) {
258 fprintf (stderr, "cannot activate client");
259 return 1;
260 }
261
262 while (1) {
263 sleep(1);
264 };
265
266 }
267
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.