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

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


** 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

~ [ 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.