2 Copyright (C) 2002 Anthony Van Groningen
3 Copyright (C) 2005 Grame
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include "internal_metro.h"
22 typedef jack_default_audio_sample_t sample_t
;
24 const double PI
= 3.14;
26 static int process_audio (jack_nframes_t nframes
, void* arg
)
28 InternalMetro
* metro
= (InternalMetro
*)arg
;
29 sample_t
*buffer
= (sample_t
*) jack_port_get_buffer (metro
->output_port
, nframes
);
30 jack_nframes_t frames_left
= nframes
;
32 while (metro
->wave_length
- metro
->offset
< frames_left
) {
33 memcpy (buffer
+ (nframes
- frames_left
), metro
->wave
+ metro
->offset
, sizeof (sample_t
) * (metro
->wave_length
- metro
->offset
));
34 frames_left
-= metro
->wave_length
- metro
->offset
;
37 if (frames_left
> 0) {
38 memcpy (buffer
+ (nframes
- frames_left
), metro
->wave
+ metro
->offset
, sizeof (sample_t
) * frames_left
);
39 metro
->offset
+= frames_left
;
45 InternalMetro::InternalMetro(int freq
, double max_amp
, int dur_arg
, int bpm
, char* client_name
)
48 int i
, attack_length
, decay_length
;
50 int attack_percent
= 1, decay_percent
= 10;
51 const char *bpm_string
= "bpm";
55 /* Initial Jack setup, get sample rate */
57 client_name
= (char *) malloc (9 * sizeof (char));
58 strcpy (client_name
, "metro");
60 if ((client
= jack_client_open (client_name
, JackNullOption
, NULL
)) == 0) {
61 fprintf (stderr
, "jack server not running?\n");
65 jack_set_process_callback (client
, process_audio
, this);
66 output_port
= jack_port_register (client
, bpm_string
, JACK_DEFAULT_AUDIO_TYPE
, JackPortIsOutput
, 0);
67 input_port
= jack_port_register (client
, "metro_in", JACK_DEFAULT_AUDIO_TYPE
, JackPortIsInput
, 0);
69 sr
= jack_get_sample_rate (client
);
71 /* setup wave table parameters */
72 wave_length
= 60 * sr
/ bpm
;
73 tone_length
= sr
* dur_arg
/ 1000;
74 attack_length
= tone_length
* attack_percent
/ 100;
75 decay_length
= tone_length
* decay_percent
/ 100;
76 scale
= 2 * PI
* freq
/ sr
;
78 if (tone_length
>= wave_length
) {
80 fprintf (stderr, "invalid duration (tone length = %" PRIu32
81 ", wave length = %" PRIu32 "\n", tone_length,
86 if (attack_length
+ decay_length
> (int)tone_length
) {
87 fprintf (stderr
, "invalid attack/decay\n");
91 /* Build the wave table */
92 wave
= (sample_t
*) malloc (wave_length
* sizeof(sample_t
));
93 amp
= (double *) malloc (tone_length
* sizeof(double));
95 for (i
= 0; i
< attack_length
; i
++) {
96 amp
[i
] = max_amp
* i
/ ((double) attack_length
);
98 for (i
= attack_length
; i
< (int) tone_length
- decay_length
; i
++) {
101 for (i
= (int)tone_length
- decay_length
; i
< (int)tone_length
; i
++) {
102 amp
[i
] = - max_amp
* (i
- (double) tone_length
) / ((double) decay_length
);
104 for (i
= 0; i
< (int) tone_length
; i
++) {
105 wave
[i
] = amp
[i
] * sin (scale
* i
);
107 for (i
= tone_length
; i
< (int) wave_length
; i
++) {
111 if (jack_activate (client
)) {
112 fprintf(stderr
, "cannot activate client");
117 InternalMetro::~InternalMetro()
119 jack_deactivate(client
);
120 jack_port_unregister(client
, input_port
);
121 jack_port_unregister(client
, output_port
);
122 jack_client_close(client
);