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
;
49 int attack_percent
= 1, decay_percent
= 10;
50 const 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_open (client_name
, JackNullOption
, NULL
)) == 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 InternalMetro::~InternalMetro()
117 jack_deactivate(client
);
118 jack_port_unregister(client
, input_port
);
119 jack_port_unregister(client
, output_port
);
120 jack_client_close(client
);