Mercurial > hg > index.fcgi > lsonify > lsonify-1pba
diff lsonify.c @ 2:ff028323c114
rename metro.c to lsonify.c
author | paulo@localhost |
---|---|
date | Thu, 21 May 2009 00:00:49 -0700 |
parents | metro.c@46d4c88917a2 |
children | 3dd48f06493e |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/lsonify.c Thu May 21 00:00:49 2009 -0700 1.3 @@ -0,0 +1,281 @@ 1.4 +/* 1.5 + Copyright (C) 2002 Anthony Van Groningen 1.6 + 1.7 + This program is free software; you can redistribute it and/or modify 1.8 + it under the terms of the GNU General Public License as published by 1.9 + the Free Software Foundation; either version 2 of the License, or 1.10 + (at your option) any later version. 1.11 + 1.12 + This program is distributed in the hope that it will be useful, 1.13 + but WITHOUT ANY WARRANTY; without even the implied warranty of 1.14 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1.15 + GNU General Public License for more details. 1.16 + 1.17 + You should have received a copy of the GNU General Public License 1.18 + along with this program; if not, write to the Free Software 1.19 + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 1.20 +*/ 1.21 + 1.22 +// 20090516 PBA: started modifying metro.c for lsonify 1.23 + 1.24 +#include <stdlib.h> 1.25 +#include <stdio.h> 1.26 +#include <errno.h> 1.27 +#include <unistd.h> 1.28 +#include <math.h> 1.29 +#include <getopt.h> 1.30 +#include <string.h> 1.31 + 1.32 +#include <jack/jack.h> 1.33 +#include <jack/transport.h> 1.34 + 1.35 +typedef jack_default_audio_sample_t sample_t; 1.36 + 1.37 +const double PI = 3.14; 1.38 + 1.39 +jack_client_t *client; 1.40 +jack_port_t *output_port; 1.41 +unsigned long sr; 1.42 +int freq = 880; 1.43 +int bpm; 1.44 +jack_nframes_t tone_length, wave_length; 1.45 +sample_t *wave; 1.46 +long offset = 0; 1.47 +int transport_aware = 0; 1.48 +jack_transport_state_t transport_state; 1.49 + 1.50 +void 1.51 +usage () 1.52 + 1.53 +{ 1.54 + fprintf (stderr, "\n" 1.55 +"usage: lsonify \n" 1.56 +" [ --frequency OR -f frequency (in Hz) ]\n" 1.57 +" [ --amplitude OR -A maximum amplitude (between 0 and 1) ]\n" 1.58 +" [ --duration OR -D duration (in ms) ]\n" 1.59 +" [ --attack OR -a attack (in percent of duration) ]\n" 1.60 +" [ --decay OR -d decay (in percent of duration) ]\n" 1.61 +" [ --name OR -n jack name for metronome client ]\n" 1.62 +" [ --transport OR -t transport aware ]\n" 1.63 +" [ --nophysical OR -p to prevent auto-connect to all physical ports]\n" 1.64 +" --bpm OR -b beats per minute\n" 1.65 +); 1.66 +} 1.67 + 1.68 +void 1.69 +process_silence (jack_nframes_t nframes) 1.70 +{ 1.71 + sample_t *buffer = (sample_t *) jack_port_get_buffer (output_port, nframes); 1.72 + memset (buffer, 0, sizeof (jack_default_audio_sample_t) * nframes); 1.73 +} 1.74 + 1.75 +void 1.76 +process_audio (jack_nframes_t nframes) 1.77 +{ 1.78 + 1.79 + sample_t *buffer = (sample_t *) jack_port_get_buffer (output_port, nframes); 1.80 + jack_nframes_t frames_left = nframes; 1.81 + 1.82 + while (wave_length - offset < frames_left) { 1.83 + memcpy (buffer + (nframes - frames_left), wave + offset, sizeof (sample_t) * (wave_length - offset)); 1.84 + frames_left -= wave_length - offset; 1.85 + offset = 0; 1.86 + } 1.87 + if (frames_left > 0) { 1.88 + memcpy (buffer + (nframes - frames_left), wave + offset, sizeof (sample_t) * frames_left); 1.89 + offset += frames_left; 1.90 + } 1.91 +} 1.92 + 1.93 +int 1.94 +process (jack_nframes_t nframes, void *arg) 1.95 +{ 1.96 + if (transport_aware) { 1.97 + jack_position_t pos; 1.98 + 1.99 + if (jack_transport_query (client, &pos) 1.100 + != JackTransportRolling) { 1.101 + 1.102 + process_silence (nframes); 1.103 + return 0; 1.104 + } 1.105 + offset = pos.frame % wave_length; 1.106 + } 1.107 + process_audio (nframes); 1.108 + return 0; 1.109 +} 1.110 + 1.111 +int 1.112 +sample_rate_change () { 1.113 + printf("Sample rate has changed! Exiting...\n"); 1.114 + exit(-1); 1.115 +} 1.116 + 1.117 +int 1.118 +main (int argc, char *argv[]) 1.119 +{ 1.120 + 1.121 + sample_t scale; 1.122 + int i, attack_length, decay_length; 1.123 + double *amp; 1.124 + double max_amp = 0.5; 1.125 + int opt; 1.126 + int got_bpm = 0; 1.127 + int attack_percent = 1, decay_percent = 10, dur_arg = 100; 1.128 + char *client_name = 0; 1.129 + char *port_string = "out"; 1.130 + int verbose = 0; 1.131 + int connect_physical_ports = 1; 1.132 + jack_status_t status; 1.133 + 1.134 + const char *options = "f:A:D:a:d:b:n:tphv"; 1.135 + struct option long_options[] = 1.136 + { 1.137 + {"frequency", 1, 0, 'f'}, 1.138 + {"amplitude", 1, 0, 'A'}, 1.139 + {"duration", 1, 0, 'D'}, 1.140 + {"attack", 1, 0, 'a'}, 1.141 + {"decay", 1, 0, 'd'}, 1.142 + {"bpm", 1, 0, 'b'}, 1.143 + {"name", 1, 0, 'n'}, 1.144 + {"transport", 0, 0, 't'}, 1.145 + {"nophysical", 0, 0, 'p'}, 1.146 + {"help", 0, 0, 'h'}, 1.147 + {"verbose", 0, 0, 'v'}, 1.148 + {0, 0, 0, 0} 1.149 + }; 1.150 + 1.151 + while ((opt = getopt_long (argc, argv, options, long_options, NULL)) != EOF) { 1.152 + switch (opt) { 1.153 + case 'f': 1.154 + if ((freq = atoi (optarg)) <= 0) { 1.155 + fprintf (stderr, "invalid frequency\n"); 1.156 + return -1; 1.157 + } 1.158 + break; 1.159 + case 'A': 1.160 + if (((max_amp = atof (optarg)) <= 0)|| (max_amp > 1)) { 1.161 + fprintf (stderr, "invalid amplitude\n"); 1.162 + return -1; 1.163 + } 1.164 + break; 1.165 + case 'D': 1.166 + dur_arg = atoi (optarg); 1.167 + fprintf (stderr, "durarg = %u\n", dur_arg); 1.168 + break; 1.169 + case 'a': 1.170 + if (((attack_percent = atoi (optarg)) < 0) || (attack_percent > 100)) { 1.171 + fprintf (stderr, "invalid attack percent\n"); 1.172 + return -1; 1.173 + } 1.174 + break; 1.175 + case 'd': 1.176 + if (((decay_percent = atoi (optarg)) < 0) || (decay_percent > 100)) { 1.177 + fprintf (stderr, "invalid decay percent\n"); 1.178 + return -1; 1.179 + } 1.180 + break; 1.181 + case 'b': 1.182 + got_bpm = 1; 1.183 + if ((bpm = atoi (optarg)) < 0) { 1.184 + fprintf (stderr, "invalid bpm\n"); 1.185 + return -1; 1.186 + } 1.187 + break; 1.188 + case 'n': 1.189 + client_name = (char *) malloc (strlen (optarg) * sizeof (char)); 1.190 + strcpy (client_name, optarg); 1.191 + break; 1.192 + case 'v': 1.193 + verbose = 1; 1.194 + break; 1.195 + case 't': 1.196 + transport_aware = 1; 1.197 + break; 1.198 + case 'p': 1.199 + connect_physical_ports = 0; 1.200 + break; 1.201 + default: 1.202 + fprintf (stderr, "unknown option %c\n", opt); 1.203 + case 'h': 1.204 + usage (); 1.205 + return -1; 1.206 + } 1.207 + } 1.208 + if (!got_bpm) { 1.209 + fprintf (stderr, "bpm not specified\n"); 1.210 + usage (); 1.211 + return -1; 1.212 + } 1.213 + 1.214 + /* Initial Jack setup, get sample rate */ 1.215 + if (!client_name) { 1.216 + pid_t pid = getpid(); 1.217 + client_name = (char *) malloc (32 * sizeof (char)); 1.218 + snprintf (client_name, 32, "metro_%d", pid); 1.219 + } 1.220 + if ((client = jack_client_open (client_name, JackNoStartServer, &status)) == 0) { 1.221 + fprintf (stderr, "jack server not running?\n"); 1.222 + return 1; 1.223 + } 1.224 + jack_set_process_callback (client, process, 0); 1.225 + output_port = jack_port_register (client, port_string, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); 1.226 + 1.227 + sr = jack_get_sample_rate (client); 1.228 + 1.229 + /* setup wave table parameters */ 1.230 + wave_length = 60 * sr / bpm; 1.231 + tone_length = sr * dur_arg / 1000; 1.232 + attack_length = tone_length * attack_percent / 100; 1.233 + decay_length = tone_length * decay_percent / 100; 1.234 + scale = 2 * PI * freq / sr; 1.235 + 1.236 + if (tone_length >= wave_length) { 1.237 + fprintf (stderr, "invalid duration (tone length = %" PRIu32 1.238 + ", wave length = %" PRIu32 "\n", tone_length, 1.239 + wave_length); 1.240 + return -1; 1.241 + } 1.242 + if (attack_length + decay_length > (int)tone_length) { 1.243 + fprintf (stderr, "invalid attack/decay\n"); 1.244 + return -1; 1.245 + } 1.246 + 1.247 + /* Build the wave table */ 1.248 + wave = (sample_t *) malloc (wave_length * sizeof(sample_t)); 1.249 + amp = (double *) malloc (tone_length * sizeof(double)); 1.250 + 1.251 + for (i = 0; i < attack_length; i++) { 1.252 + amp[i] = max_amp * i / ((double) attack_length); 1.253 + } 1.254 + for (i = attack_length; i < (int)tone_length - decay_length; i++) { 1.255 + amp[i] = max_amp; 1.256 + } 1.257 + for (i = (int)tone_length - decay_length; i < (int)tone_length; i++) { 1.258 + amp[i] = - max_amp * (i - (double) tone_length) / ((double) decay_length); 1.259 + } 1.260 + for (i = 0; i < (int)tone_length; i++) { 1.261 + wave[i] = amp[i] * sin (scale * i); 1.262 + } 1.263 + for (i = tone_length; i < (int)wave_length; i++) { 1.264 + wave[i] = 0; 1.265 + } 1.266 + 1.267 + if (jack_activate (client)) { 1.268 + fprintf (stderr, "cannot activate client"); 1.269 + return 1; 1.270 + } 1.271 + 1.272 + /* connect to physical ports */ 1.273 + if (connect_physical_ports) { 1.274 + const char **ports = jack_get_ports (client, NULL, NULL, JackPortIsPhysical | JackPortIsInput); 1.275 + const char **c; 1.276 + for (c = ports; c && *c; c++) 1.277 + jack_connect (client, jack_port_name(output_port), *c); 1.278 + } 1.279 + 1.280 + while (1) { 1.281 + sleep(1); 1.282 + }; 1.283 + 1.284 +}