2 Copyright (C) 2002 Anthony Van Groningen
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.
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.
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.
19 #include "external_metro.h"
21 typedef jack_default_audio_sample_t sample_t
;
23 const double PI
= 3.14;
25 static int process_audio (jack_nframes_t nframes
, void* arg
)
27 ExternalMetro
* metro
= (ExternalMetro
*)arg
;
28 sample_t
*buffer
= (sample_t
*) jack_port_get_buffer (metro
->output_port
, nframes
);
29 jack_nframes_t frames_left
= nframes
;
31 while (metro
->wave_length
- metro
->offset
< frames_left
) {
32 memcpy (buffer
+ (nframes
- frames_left
), metro
->wave
+ metro
->offset
, sizeof (sample_t
) * (metro
->wave_length
- metro
->offset
));
33 frames_left
-= metro
->wave_length
- metro
->offset
;
36 if (frames_left
> 0) {
37 memcpy (buffer
+ (nframes
- frames_left
), metro
->wave
+ metro
->offset
, sizeof (sample_t
) * frames_left
);
38 metro
->offset
+= frames_left
;
44 ExternalMetro::ExternalMetro(int freq
, double max_amp
, int dur_arg
, int bpm
, char* client_name
)
47 int i
, attack_length
, decay_length
;
49 int attack_percent
= 1, decay_percent
= 10;
50 char *bpm_string
= "bpm";
54 /* Initial Jack setup, get sample rate */
56 client_name
= (char *) malloc (9 * sizeof (char));
57 strcpy (client_name
, "metro");
59 if ((client
= jack_client_new (client_name
)) == 0) {
60 fprintf (stderr
, "jack server not running?\n");
64 jack_set_process_callback (client
, process_audio
, this);
65 output_port
= jack_port_register (client
, bpm_string
, JACK_DEFAULT_AUDIO_TYPE
, JackPortIsOutput
, 0);
66 input_port
= jack_port_register (client
, "metro_in", JACK_DEFAULT_AUDIO_TYPE
, JackPortIsInput
, 0);
68 sr
= jack_get_sample_rate (client
);
70 /* setup wave table parameters */
71 wave_length
= 60 * sr
/ bpm
;
72 tone_length
= sr
* dur_arg
/ 1000;
73 attack_length
= tone_length
* attack_percent
/ 100;
74 decay_length
= tone_length
* decay_percent
/ 100;
75 scale
= 2 * PI
* freq
/ sr
;
77 if (tone_length
>= wave_length
) {
79 fprintf (stderr, "invalid duration (tone length = %" PRIu32
80 ", wave length = %" PRIu32 "\n", tone_length,
85 if (attack_length
+ decay_length
> (int)tone_length
) {
86 fprintf (stderr
, "invalid attack/decay\n");
90 /* Build the wave table */
91 wave
= (sample_t
*) malloc (wave_length
* sizeof(sample_t
));
92 amp
= (double *) malloc (tone_length
* sizeof(double));
94 for (i
= 0; i
< attack_length
; i
++) {
95 amp
[i
] = max_amp
* i
/ ((double) attack_length
);
97 for (i
= attack_length
; i
< (int) tone_length
- decay_length
; i
++) {
100 for (i
= (int)tone_length
- decay_length
; i
< (int)tone_length
; i
++) {
101 amp
[i
] = - max_amp
* (i
- (double) tone_length
) / ((double) decay_length
);
103 for (i
= 0; i
< (int) tone_length
; i
++) {
104 wave
[i
] = amp
[i
] * sin (scale
* i
);
106 for (i
= tone_length
; i
< (int) wave_length
; i
++) {
110 if (jack_activate (client
)) {
111 fprintf (stderr
, "cannot activate client");
115 ExternalMetro::~ExternalMetro()
117 jack_deactivate(client
);
118 jack_port_unregister(client
, input_port
);
119 jack_port_unregister(client
, output_port
);
120 jack_client_close(client
);
123 int main (int argc
, char *argv
[])
125 ExternalMetro
* client1
= NULL
;
126 ExternalMetro
* client2
= NULL
;
127 ExternalMetro
* client3
= NULL
;
128 ExternalMetro
* client4
= NULL
;
129 ExternalMetro
* client5
= NULL
;
131 client1
= new ExternalMetro(1200, 0.4, 20, 80, "t1");
132 client2
= new ExternalMetro(600, 0.4, 20, 150, "t2");
133 client3
= new ExternalMetro(1000, 0.4, 20, 110, "t3");
134 client4
= new ExternalMetro(400, 0.4, 20, 200, "t4");
135 client5
= new ExternalMetro(1500, 0.4, 20, 150, "t5");
137 while ((getchar() != 'q')) {