Mercurial > hg > index.fcgi > lsonify > lsonify-1pba
changeset 0:047192fef940
copy metro.c from jack example-clients
author | paulo@localhost |
---|---|
date | Sat, 16 May 2009 23:03:46 -0700 |
parents | |
children | 46d4c88917a2 |
files | metro.c |
diffstat | 1 files changed, 270 insertions(+), 0 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/metro.c Sat May 16 23:03:46 2009 -0700 1.3 @@ -0,0 +1,270 @@ 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: jack_metro \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 +" --bpm OR -b beats per minute\n" 1.64 +); 1.65 +} 1.66 + 1.67 +void 1.68 +process_silence (jack_nframes_t nframes) 1.69 +{ 1.70 + sample_t *buffer = (sample_t *) jack_port_get_buffer (output_port, nframes); 1.71 + memset (buffer, 0, sizeof (jack_default_audio_sample_t) * nframes); 1.72 +} 1.73 + 1.74 +void 1.75 +process_audio (jack_nframes_t nframes) 1.76 +{ 1.77 + 1.78 + sample_t *buffer = (sample_t *) jack_port_get_buffer (output_port, nframes); 1.79 + jack_nframes_t frames_left = nframes; 1.80 + 1.81 + while (wave_length - offset < frames_left) { 1.82 + memcpy (buffer + (nframes - frames_left), wave + offset, sizeof (sample_t) * (wave_length - offset)); 1.83 + frames_left -= wave_length - offset; 1.84 + offset = 0; 1.85 + } 1.86 + if (frames_left > 0) { 1.87 + memcpy (buffer + (nframes - frames_left), wave + offset, sizeof (sample_t) * frames_left); 1.88 + offset += frames_left; 1.89 + } 1.90 +} 1.91 + 1.92 +int 1.93 +process (jack_nframes_t nframes, void *arg) 1.94 +{ 1.95 + if (transport_aware) { 1.96 + jack_position_t pos; 1.97 + 1.98 + if (jack_transport_query (client, &pos) 1.99 + != JackTransportRolling) { 1.100 + 1.101 + process_silence (nframes); 1.102 + return 0; 1.103 + } 1.104 + offset = pos.frame % wave_length; 1.105 + } 1.106 + process_audio (nframes); 1.107 + return 0; 1.108 +} 1.109 + 1.110 +int 1.111 +sample_rate_change () { 1.112 + printf("Sample rate has changed! Exiting...\n"); 1.113 + exit(-1); 1.114 +} 1.115 + 1.116 +int 1.117 +main (int argc, char *argv[]) 1.118 +{ 1.119 + 1.120 + sample_t scale; 1.121 + int i, attack_length, decay_length; 1.122 + double *amp; 1.123 + double max_amp = 0.5; 1.124 + int option_index; 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 *bpm_string = "bpm"; 1.130 + int verbose = 0; 1.131 + jack_status_t status; 1.132 + 1.133 + const char *options = "f:A:D:a:d:b:n:thv"; 1.134 + struct option long_options[] = 1.135 + { 1.136 + {"frequency", 1, 0, 'f'}, 1.137 + {"amplitude", 1, 0, 'A'}, 1.138 + {"duration", 1, 0, 'D'}, 1.139 + {"attack", 1, 0, 'a'}, 1.140 + {"decay", 1, 0, 'd'}, 1.141 + {"bpm", 1, 0, 'b'}, 1.142 + {"name", 1, 0, 'n'}, 1.143 + {"transport", 0, 0, 't'}, 1.144 + {"help", 0, 0, 'h'}, 1.145 + {"verbose", 0, 0, 'v'}, 1.146 + {0, 0, 0, 0} 1.147 + }; 1.148 + 1.149 + while ((opt = getopt_long (argc, argv, options, long_options, &option_index)) != EOF) { 1.150 + switch (opt) { 1.151 + case 'f': 1.152 + if ((freq = atoi (optarg)) <= 0) { 1.153 + fprintf (stderr, "invalid frequency\n"); 1.154 + return -1; 1.155 + } 1.156 + break; 1.157 + case 'A': 1.158 + if (((max_amp = atof (optarg)) <= 0)|| (max_amp > 1)) { 1.159 + fprintf (stderr, "invalid amplitude\n"); 1.160 + return -1; 1.161 + } 1.162 + break; 1.163 + case 'D': 1.164 + dur_arg = atoi (optarg); 1.165 + fprintf (stderr, "durarg = %u\n", dur_arg); 1.166 + break; 1.167 + case 'a': 1.168 + if (((attack_percent = atoi (optarg)) < 0) || (attack_percent > 100)) { 1.169 + fprintf (stderr, "invalid attack percent\n"); 1.170 + return -1; 1.171 + } 1.172 + break; 1.173 + case 'd': 1.174 + if (((decay_percent = atoi (optarg)) < 0) || (decay_percent > 100)) { 1.175 + fprintf (stderr, "invalid decay percent\n"); 1.176 + return -1; 1.177 + } 1.178 + break; 1.179 + case 'b': 1.180 + got_bpm = 1; 1.181 + if ((bpm = atoi (optarg)) < 0) { 1.182 + fprintf (stderr, "invalid bpm\n"); 1.183 + return -1; 1.184 + } 1.185 + bpm_string = (char *) malloc ((strlen (optarg) + 4) * sizeof (char)); 1.186 + strcpy (bpm_string, optarg); 1.187 + strcat (bpm_string, "_bpm"); 1.188 + break; 1.189 + case 'n': 1.190 + client_name = (char *) malloc (strlen (optarg) * sizeof (char)); 1.191 + strcpy (client_name, optarg); 1.192 + break; 1.193 + case 'v': 1.194 + verbose = 1; 1.195 + break; 1.196 + case 't': 1.197 + transport_aware = 1; 1.198 + break; 1.199 + default: 1.200 + fprintf (stderr, "unknown option %c\n", opt); 1.201 + case 'h': 1.202 + usage (); 1.203 + return -1; 1.204 + } 1.205 + } 1.206 + if (!got_bpm) { 1.207 + fprintf (stderr, "bpm not specified\n"); 1.208 + usage (); 1.209 + return -1; 1.210 + } 1.211 + 1.212 + /* Initial Jack setup, get sample rate */ 1.213 + if (!client_name) { 1.214 + client_name = (char *) malloc (9 * sizeof (char)); 1.215 + strcpy (client_name, "metro"); 1.216 + } 1.217 + if ((client = jack_client_open (client_name, JackNoStartServer, &status)) == 0) { 1.218 + fprintf (stderr, "jack server not running?\n"); 1.219 + return 1; 1.220 + } 1.221 + jack_set_process_callback (client, process, 0); 1.222 + output_port = jack_port_register (client, bpm_string, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); 1.223 + 1.224 + sr = jack_get_sample_rate (client); 1.225 + 1.226 + /* setup wave table parameters */ 1.227 + wave_length = 60 * sr / bpm; 1.228 + tone_length = sr * dur_arg / 1000; 1.229 + attack_length = tone_length * attack_percent / 100; 1.230 + decay_length = tone_length * decay_percent / 100; 1.231 + scale = 2 * PI * freq / sr; 1.232 + 1.233 + if (tone_length >= wave_length) { 1.234 + fprintf (stderr, "invalid duration (tone length = %" PRIu32 1.235 + ", wave length = %" PRIu32 "\n", tone_length, 1.236 + wave_length); 1.237 + return -1; 1.238 + } 1.239 + if (attack_length + decay_length > (int)tone_length) { 1.240 + fprintf (stderr, "invalid attack/decay\n"); 1.241 + return -1; 1.242 + } 1.243 + 1.244 + /* Build the wave table */ 1.245 + wave = (sample_t *) malloc (wave_length * sizeof(sample_t)); 1.246 + amp = (double *) malloc (tone_length * sizeof(double)); 1.247 + 1.248 + for (i = 0; i < attack_length; i++) { 1.249 + amp[i] = max_amp * i / ((double) attack_length); 1.250 + } 1.251 + for (i = attack_length; i < (int)tone_length - decay_length; i++) { 1.252 + amp[i] = max_amp; 1.253 + } 1.254 + for (i = (int)tone_length - decay_length; i < (int)tone_length; i++) { 1.255 + amp[i] = - max_amp * (i - (double) tone_length) / ((double) decay_length); 1.256 + } 1.257 + for (i = 0; i < (int)tone_length; i++) { 1.258 + wave[i] = amp[i] * sin (scale * i); 1.259 + } 1.260 + for (i = tone_length; i < (int)wave_length; i++) { 1.261 + wave[i] = 0; 1.262 + } 1.263 + 1.264 + if (jack_activate (client)) { 1.265 + fprintf (stderr, "cannot activate client"); 1.266 + return 1; 1.267 + } 1.268 + 1.269 + while (1) { 1.270 + sleep(1); 1.271 + }; 1.272 + 1.273 +}