2 Copyright (C) 2002 Anthony Van Groningen
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.
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.
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.
30 #include <jack/jack.h>
31 #include <jack/transport.h>
33 typedef jack_default_audio_sample_t sample_t
;
35 const double PI
= 3.14;
37 jack_client_t
*client
;
38 jack_port_t
*output_port
;
42 jack_nframes_t tone_length
, wave_length
;
45 int transport_aware
= 0;
46 jack_transport_state_t transport_state
;
48 static void signal_handler(int sig
)
50 jack_client_close(client
);
51 fprintf(stderr
, "signal received, exiting ...\n");
59 "usage: jack_metro \n"
60 " [ --frequency OR -f frequency (in Hz) ]\n"
61 " [ --amplitude OR -A maximum amplitude (between 0 and 1) ]\n"
62 " [ --duration OR -D duration (in ms) ]\n"
63 " [ --attack OR -a attack (in percent of duration) ]\n"
64 " [ --decay OR -d decay (in percent of duration) ]\n"
65 " [ --name OR -n jack name for metronome client ]\n"
66 " [ --transport OR -t transport aware ]\n"
67 " --bpm OR -b beats per minute\n"
72 process_silence (jack_nframes_t nframes
)
74 sample_t
*buffer
= (sample_t
*) jack_port_get_buffer (output_port
, nframes
);
75 memset (buffer
, 0, sizeof (jack_default_audio_sample_t
) * nframes
);
79 process_audio (jack_nframes_t nframes
)
81 sample_t
*buffer
= (sample_t
*) jack_port_get_buffer (output_port
, nframes
);
82 jack_nframes_t frames_left
= nframes
;
84 while (wave_length
- offset
< frames_left
) {
85 memcpy (buffer
+ (nframes
- frames_left
), wave
+ offset
, sizeof (sample_t
) * (wave_length
- offset
));
86 frames_left
-= wave_length
- offset
;
89 if (frames_left
> 0) {
90 memcpy (buffer
+ (nframes
- frames_left
), wave
+ offset
, sizeof (sample_t
) * frames_left
);
91 offset
+= frames_left
;
96 process (jack_nframes_t nframes
, void *arg
)
98 if (transport_aware
) {
101 if (jack_transport_query (client
, &pos
)
102 != JackTransportRolling
) {
104 process_silence (nframes
);
107 offset
= pos
.frame
% wave_length
;
109 process_audio (nframes
);
114 main (int argc
, char *argv
[])
117 int i
, attack_length
, decay_length
;
119 double max_amp
= 0.5;
123 int attack_percent
= 1, decay_percent
= 10, dur_arg
= 100;
124 char *client_name
= 0;
125 char *bpm_string
= "bpm";
127 jack_status_t status
;
129 const char *options
= "f:A:D:a:d:b:n:thv";
130 struct option long_options
[] =
132 {"frequency", 1, 0, 'f'},
133 {"amplitude", 1, 0, 'A'},
134 {"duration", 1, 0, 'D'},
135 {"attack", 1, 0, 'a'},
136 {"decay", 1, 0, 'd'},
139 {"transport", 0, 0, 't'},
141 {"verbose", 0, 0, 'v'},
145 while ((opt
= getopt_long (argc
, argv
, options
, long_options
, &option_index
)) != EOF
) {
148 if ((freq
= atoi (optarg
)) <= 0) {
149 fprintf (stderr
, "invalid frequency\n");
154 if (((max_amp
= atof (optarg
)) <= 0)|| (max_amp
> 1)) {
155 fprintf (stderr
, "invalid amplitude\n");
160 dur_arg
= atoi (optarg
);
161 fprintf (stderr
, "durarg = %u\n", dur_arg
);
164 if (((attack_percent
= atoi (optarg
)) < 0) || (attack_percent
> 100)) {
165 fprintf (stderr
, "invalid attack percent\n");
170 if (((decay_percent
= atoi (optarg
)) < 0) || (decay_percent
> 100)) {
171 fprintf (stderr
, "invalid decay percent\n");
177 if ((bpm
= atoi (optarg
)) < 0) {
178 fprintf (stderr
, "invalid bpm\n");
181 bpm_string
= (char *) malloc ((strlen (optarg
) + 4) * sizeof (char));
182 strcpy (bpm_string
, optarg
);
183 strcat (bpm_string
, "_bpm");
186 client_name
= (char *) malloc (strlen (optarg
) * sizeof (char));
187 strcpy (client_name
, optarg
);
196 fprintf (stderr
, "unknown option %c\n", opt
);
203 fprintf (stderr
, "bpm not specified\n");
208 /* Initial Jack setup, get sample rate */
210 client_name
= (char *) malloc (9 * sizeof (char));
211 strcpy (client_name
, "metro");
213 if ((client
= jack_client_open (client_name
, JackNoStartServer
, &status
)) == 0) {
214 fprintf (stderr
, "jack server not running?\n");
217 jack_set_process_callback (client
, process
, 0);
218 output_port
= jack_port_register (client
, bpm_string
, JACK_DEFAULT_AUDIO_TYPE
, JackPortIsOutput
, 0);
220 sr
= jack_get_sample_rate (client
);
222 /* setup wave table parameters */
223 wave_length
= 60 * sr
/ bpm
;
224 tone_length
= sr
* dur_arg
/ 1000;
225 attack_length
= tone_length
* attack_percent
/ 100;
226 decay_length
= tone_length
* decay_percent
/ 100;
227 scale
= 2 * PI
* freq
/ sr
;
229 if (tone_length
>= wave_length
) {
230 fprintf (stderr
, "invalid duration (tone length = %u, wave length = %u\n", tone_length
, wave_length
);
233 if (attack_length
+ decay_length
> (int)tone_length
) {
234 fprintf (stderr
, "invalid attack/decay\n");
238 /* Build the wave table */
239 wave
= (sample_t
*) malloc (wave_length
* sizeof(sample_t
));
240 amp
= (double *) malloc (tone_length
* sizeof(double));
242 for (i
= 0; i
< attack_length
; i
++) {
243 amp
[i
] = max_amp
* i
/ ((double) attack_length
);
245 for (i
= attack_length
; i
< (int)tone_length
- decay_length
; i
++) {
248 for (i
= (int)tone_length
- decay_length
; i
< (int)tone_length
; i
++) {
249 amp
[i
] = - max_amp
* (i
- (double) tone_length
) / ((double) decay_length
);
251 for (i
= 0; i
< (int)tone_length
; i
++) {
252 wave
[i
] = amp
[i
] * sin (scale
* i
);
254 for (i
= tone_length
; i
< (int)wave_length
; i
++) {
258 if (jack_activate (client
)) {
259 fprintf (stderr
, "cannot activate client\n");
263 /* install a signal handler to properly quits jack client */
265 signal(SIGINT
, signal_handler
);
266 signal(SIGABRT
, signal_handler
);
267 signal(SIGTERM
, signal_handler
);
269 signal(SIGQUIT
, signal_handler
);
270 signal(SIGTERM
, signal_handler
);
271 signal(SIGHUP
, signal_handler
);
272 signal(SIGINT
, signal_handler
);
275 /* run until interrupted */
284 jack_client_close(client
);