Mercurial > hg > index.fcgi > lsonify > lsonify-1pba
comparison metro.c @ 0:047192fef940
copy metro.c from jack example-clients
author | paulo@localhost |
---|---|
date | Sat, 16 May 2009 23:03:46 -0700 |
parents | |
children | 46d4c88917a2 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:ad2566db6ba4 |
---|---|
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 // 20090516 PBA: started modifying metro.c for lsonify | |
20 | |
21 #include <stdlib.h> | |
22 #include <stdio.h> | |
23 #include <errno.h> | |
24 #include <unistd.h> | |
25 #include <math.h> | |
26 #include <getopt.h> | |
27 #include <string.h> | |
28 | |
29 #include <jack/jack.h> | |
30 #include <jack/transport.h> | |
31 | |
32 typedef jack_default_audio_sample_t sample_t; | |
33 | |
34 const double PI = 3.14; | |
35 | |
36 jack_client_t *client; | |
37 jack_port_t *output_port; | |
38 unsigned long sr; | |
39 int freq = 880; | |
40 int bpm; | |
41 jack_nframes_t tone_length, wave_length; | |
42 sample_t *wave; | |
43 long offset = 0; | |
44 int transport_aware = 0; | |
45 jack_transport_state_t transport_state; | |
46 | |
47 void | |
48 usage () | |
49 | |
50 { | |
51 fprintf (stderr, "\n" | |
52 "usage: jack_metro \n" | |
53 " [ --frequency OR -f frequency (in Hz) ]\n" | |
54 " [ --amplitude OR -A maximum amplitude (between 0 and 1) ]\n" | |
55 " [ --duration OR -D duration (in ms) ]\n" | |
56 " [ --attack OR -a attack (in percent of duration) ]\n" | |
57 " [ --decay OR -d decay (in percent of duration) ]\n" | |
58 " [ --name OR -n jack name for metronome client ]\n" | |
59 " [ --transport OR -t transport aware ]\n" | |
60 " --bpm OR -b beats per minute\n" | |
61 ); | |
62 } | |
63 | |
64 void | |
65 process_silence (jack_nframes_t nframes) | |
66 { | |
67 sample_t *buffer = (sample_t *) jack_port_get_buffer (output_port, nframes); | |
68 memset (buffer, 0, sizeof (jack_default_audio_sample_t) * nframes); | |
69 } | |
70 | |
71 void | |
72 process_audio (jack_nframes_t nframes) | |
73 { | |
74 | |
75 sample_t *buffer = (sample_t *) jack_port_get_buffer (output_port, nframes); | |
76 jack_nframes_t frames_left = nframes; | |
77 | |
78 while (wave_length - offset < frames_left) { | |
79 memcpy (buffer + (nframes - frames_left), wave + offset, sizeof (sample_t) * (wave_length - offset)); | |
80 frames_left -= wave_length - offset; | |
81 offset = 0; | |
82 } | |
83 if (frames_left > 0) { | |
84 memcpy (buffer + (nframes - frames_left), wave + offset, sizeof (sample_t) * frames_left); | |
85 offset += frames_left; | |
86 } | |
87 } | |
88 | |
89 int | |
90 process (jack_nframes_t nframes, void *arg) | |
91 { | |
92 if (transport_aware) { | |
93 jack_position_t pos; | |
94 | |
95 if (jack_transport_query (client, &pos) | |
96 != JackTransportRolling) { | |
97 | |
98 process_silence (nframes); | |
99 return 0; | |
100 } | |
101 offset = pos.frame % wave_length; | |
102 } | |
103 process_audio (nframes); | |
104 return 0; | |
105 } | |
106 | |
107 int | |
108 sample_rate_change () { | |
109 printf("Sample rate has changed! Exiting...\n"); | |
110 exit(-1); | |
111 } | |
112 | |
113 int | |
114 main (int argc, char *argv[]) | |
115 { | |
116 | |
117 sample_t scale; | |
118 int i, attack_length, decay_length; | |
119 double *amp; | |
120 double max_amp = 0.5; | |
121 int option_index; | |
122 int opt; | |
123 int got_bpm = 0; | |
124 int attack_percent = 1, decay_percent = 10, dur_arg = 100; | |
125 char *client_name = 0; | |
126 char *bpm_string = "bpm"; | |
127 int verbose = 0; | |
128 jack_status_t status; | |
129 | |
130 const char *options = "f:A:D:a:d:b:n:thv"; | |
131 struct option long_options[] = | |
132 { | |
133 {"frequency", 1, 0, 'f'}, | |
134 {"amplitude", 1, 0, 'A'}, | |
135 {"duration", 1, 0, 'D'}, | |
136 {"attack", 1, 0, 'a'}, | |
137 {"decay", 1, 0, 'd'}, | |
138 {"bpm", 1, 0, 'b'}, | |
139 {"name", 1, 0, 'n'}, | |
140 {"transport", 0, 0, 't'}, | |
141 {"help", 0, 0, 'h'}, | |
142 {"verbose", 0, 0, 'v'}, | |
143 {0, 0, 0, 0} | |
144 }; | |
145 | |
146 while ((opt = getopt_long (argc, argv, options, long_options, &option_index)) != EOF) { | |
147 switch (opt) { | |
148 case 'f': | |
149 if ((freq = atoi (optarg)) <= 0) { | |
150 fprintf (stderr, "invalid frequency\n"); | |
151 return -1; | |
152 } | |
153 break; | |
154 case 'A': | |
155 if (((max_amp = atof (optarg)) <= 0)|| (max_amp > 1)) { | |
156 fprintf (stderr, "invalid amplitude\n"); | |
157 return -1; | |
158 } | |
159 break; | |
160 case 'D': | |
161 dur_arg = atoi (optarg); | |
162 fprintf (stderr, "durarg = %u\n", dur_arg); | |
163 break; | |
164 case 'a': | |
165 if (((attack_percent = atoi (optarg)) < 0) || (attack_percent > 100)) { | |
166 fprintf (stderr, "invalid attack percent\n"); | |
167 return -1; | |
168 } | |
169 break; | |
170 case 'd': | |
171 if (((decay_percent = atoi (optarg)) < 0) || (decay_percent > 100)) { | |
172 fprintf (stderr, "invalid decay percent\n"); | |
173 return -1; | |
174 } | |
175 break; | |
176 case 'b': | |
177 got_bpm = 1; | |
178 if ((bpm = atoi (optarg)) < 0) { | |
179 fprintf (stderr, "invalid bpm\n"); | |
180 return -1; | |
181 } | |
182 bpm_string = (char *) malloc ((strlen (optarg) + 4) * sizeof (char)); | |
183 strcpy (bpm_string, optarg); | |
184 strcat (bpm_string, "_bpm"); | |
185 break; | |
186 case 'n': | |
187 client_name = (char *) malloc (strlen (optarg) * sizeof (char)); | |
188 strcpy (client_name, optarg); | |
189 break; | |
190 case 'v': | |
191 verbose = 1; | |
192 break; | |
193 case 't': | |
194 transport_aware = 1; | |
195 break; | |
196 default: | |
197 fprintf (stderr, "unknown option %c\n", opt); | |
198 case 'h': | |
199 usage (); | |
200 return -1; | |
201 } | |
202 } | |
203 if (!got_bpm) { | |
204 fprintf (stderr, "bpm not specified\n"); | |
205 usage (); | |
206 return -1; | |
207 } | |
208 | |
209 /* Initial Jack setup, get sample rate */ | |
210 if (!client_name) { | |
211 client_name = (char *) malloc (9 * sizeof (char)); | |
212 strcpy (client_name, "metro"); | |
213 } | |
214 if ((client = jack_client_open (client_name, JackNoStartServer, &status)) == 0) { | |
215 fprintf (stderr, "jack server not running?\n"); | |
216 return 1; | |
217 } | |
218 jack_set_process_callback (client, process, 0); | |
219 output_port = jack_port_register (client, bpm_string, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |
220 | |
221 sr = jack_get_sample_rate (client); | |
222 | |
223 /* setup wave table parameters */ | |
224 wave_length = 60 * sr / bpm; | |
225 tone_length = sr * dur_arg / 1000; | |
226 attack_length = tone_length * attack_percent / 100; | |
227 decay_length = tone_length * decay_percent / 100; | |
228 scale = 2 * PI * freq / sr; | |
229 | |
230 if (tone_length >= wave_length) { | |
231 fprintf (stderr, "invalid duration (tone length = %" PRIu32 | |
232 ", wave length = %" PRIu32 "\n", tone_length, | |
233 wave_length); | |
234 return -1; | |
235 } | |
236 if (attack_length + decay_length > (int)tone_length) { | |
237 fprintf (stderr, "invalid attack/decay\n"); | |
238 return -1; | |
239 } | |
240 | |
241 /* Build the wave table */ | |
242 wave = (sample_t *) malloc (wave_length * sizeof(sample_t)); | |
243 amp = (double *) malloc (tone_length * sizeof(double)); | |
244 | |
245 for (i = 0; i < attack_length; i++) { | |
246 amp[i] = max_amp * i / ((double) attack_length); | |
247 } | |
248 for (i = attack_length; i < (int)tone_length - decay_length; i++) { | |
249 amp[i] = max_amp; | |
250 } | |
251 for (i = (int)tone_length - decay_length; i < (int)tone_length; i++) { | |
252 amp[i] = - max_amp * (i - (double) tone_length) / ((double) decay_length); | |
253 } | |
254 for (i = 0; i < (int)tone_length; i++) { | |
255 wave[i] = amp[i] * sin (scale * i); | |
256 } | |
257 for (i = tone_length; i < (int)wave_length; i++) { | |
258 wave[i] = 0; | |
259 } | |
260 | |
261 if (jack_activate (client)) { | |
262 fprintf (stderr, "cannot activate client"); | |
263 return 1; | |
264 } | |
265 | |
266 while (1) { | |
267 sleep(1); | |
268 }; | |
269 | |
270 } |