~ubuntu-branches/ubuntu/saucy/jack-audio-connection-kit/saucy

« back to all changes in this revision

Viewing changes to example-clients/metro.c

  • Committer: Bazaar Package Importer
  • Author(s): Luca Falavigna
  • Date: 2008-12-06 11:05:15 UTC
  • mfrom: (4.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20081206110515-xa9v9pajr9jqvfvg
Tags: 0.115.6-1ubuntu1
* Merge from Debian unstable, remaining Ubuntu changes:
  - Redirect stderr in bash completion (Debian #504488).

Show diffs side-by-side

added added

removed removed

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