1 /*
2  * GNUitar
3  * Echo effect
4  * Copyright (C) 2000,2001,2003 Max Rudensky         <fonin@ziet.zhitomir.ua>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * $Id: echo.c,v 1.11 2004/08/10 15:07:31 fonin Exp $
21  *
22  * $Log: echo.c,v $
23  * Revision 1.11  2004/08/10 15:07:31  fonin
24  * Support processing in float/int - type DSP_SAMPLE
25  *
26  * Revision 1.10  2004/07/07 19:18:42  fonin
27  * GTK2 port
28  *
29  * Revision 1.9  2003/03/14 19:20:31  fonin
30  * Unreferenced variables fixed.
31  *
32  * Revision 1.8  2003/03/12 20:53:54  fonin
33  * - meaningful sliders measure units;
34  * - code cleanup.
35  *
36  * Revision 1.7  2003/02/03 11:39:25  fonin
37  * Copyright year changed.
38  *
39  * Revision 1.6  2003/02/01 19:15:12  fonin
40  * Use sizeof(variable) instead sizeof(type) in load/save procedures,
41  * when reading/writing from file.
42  *
43  * Revision 1.5  2003/01/30 21:35:29  fonin
44  * Got rid of rnd_window_pos().
45  *
46  * Revision 1.4  2003/01/29 19:34:00  fonin
47  * Win32 port.
48  *
49  * Revision 1.3  2001/06/02 14:05:59  fonin
50  * Added GNU disclaimer.
51  *
52  * Revision 1.2  2001/03/25 12:10:49  fonin
53  * Effect window control ignores delete event.
54  *
55  * Revision 1.1.1.1  2001/01/11 13:21:41  fonin
56  * Version 0.1.0 Release 1 beta
57  *
58  */
59 
60 #include "echo.h"
61 #include "gui.h"
62 #include <stdlib.h>
63 #ifndef _WIN32
64 #    include <unistd.h>
65 #else
66 #    include <io.h>
67 #endif
68 
69 void
70                 echo_filter(struct effect *p, struct data_block *db);
71 
72 void
update_echo_decay(GtkAdjustment * adj,struct echo_params * params)73 update_echo_decay(GtkAdjustment * adj, struct echo_params *params)
74 {
75     params->echo_decay = (int) adj->value * 10;
76 }
77 
78 void
update_echo_count(GtkAdjustment * adj,struct echo_params * params)79 update_echo_count(GtkAdjustment * adj, struct echo_params *params)
80 {
81     params->buffer_count = (int) adj->value;
82 }
83 
84 void
update_echo_size(GtkAdjustment * adj,struct echo_params * params)85 update_echo_size(GtkAdjustment * adj, struct echo_params *params)
86 {
87     params->echo_size = (int) adj->value * sample_rate * nchannels / 1000;
88 }
89 
90 void
toggle_echo(void * bullshit,struct effect * p)91 toggle_echo(void *bullshit, struct effect *p)
92 {
93     if (p->toggle == 1) {
94 	p->proc_filter = passthru;
95 	p->toggle = 0;
96     } else {
97 	p->proc_filter = echo_filter;
98 	p->toggle = 1;
99     }
100 }
101 
102 
103 int
prime(int n)104 prime(int n)
105 {
106     int             i;
107 
108     for (i = 2; i < n; i++)
109 	if (n % i == 0)
110 	    return 0;
111 
112     return 1;
113 }
114 
115 void
echo_init(struct effect * p)116 echo_init(struct effect *p)
117 {
118     struct echo_params *pecho;
119 
120     GtkWidget      *decay;
121     GtkWidget      *decay_label;
122     GtkObject      *adj_decay;
123 
124     GtkWidget      *count;
125     GtkWidget      *count_label;
126     GtkObject      *adj_count;
127 
128     GtkWidget      *size;
129     GtkWidget      *size_label;
130     GtkObject      *adj_size;
131 
132     GtkWidget      *button;
133     GtkWidget      *parmTable;
134 
135     pecho = (struct echo_params *) p->params;
136 
137     /*
138      * GUI Init
139      */
140 #ifdef HAVE_GTK
141     p->control = gtk_window_new(GTK_WINDOW_DIALOG);
142 #elif defined HAVE_GTK2
143     p->control = gtk_window_new(GTK_WINDOW_TOPLEVEL);
144 #endif
145 
146     gtk_signal_connect(GTK_OBJECT(p->control), "delete_event",
147 		       GTK_SIGNAL_FUNC(delete_event), NULL);
148 
149     parmTable = gtk_table_new(2, 8, FALSE);
150 
151     adj_decay = gtk_adjustment_new(pecho->echo_decay / 10,
152 				   1.0, 100.0, 1.0, 10.0, 1.0);
153     decay_label = gtk_label_new("Decay\n%");
154     gtk_table_attach(GTK_TABLE(parmTable), decay_label, 0, 1, 0, 1,
155 		     __GTKATTACHOPTIONS(GTK_FILL | GTK_EXPAND |
156 					GTK_SHRINK),
157 		     __GTKATTACHOPTIONS(GTK_FILL | GTK_EXPAND |
158 					GTK_SHRINK), 0, 0);
159 
160 
161     gtk_signal_connect(GTK_OBJECT(adj_decay), "value_changed",
162 		       GTK_SIGNAL_FUNC(update_echo_decay), pecho);
163 
164     decay = gtk_vscale_new(GTK_ADJUSTMENT(adj_decay));
165 #ifdef HAVE_GTK2
166     gtk_widget_set_size_request(GTK_WIDGET(decay),0,100);
167 #endif
168 
169     gtk_table_attach(GTK_TABLE(parmTable), decay, 0, 1, 1, 2,
170 		     __GTKATTACHOPTIONS(GTK_FILL | GTK_EXPAND |
171 					GTK_SHRINK),
172 		     __GTKATTACHOPTIONS(GTK_FILL | GTK_EXPAND |
173 					GTK_SHRINK), 0, 0);
174 
175 
176     adj_count = gtk_adjustment_new(pecho->buffer_count,
177 				   1.0, MAX_ECHO_COUNT, 1.0, 1.0, 1.0);
178     count_label = gtk_label_new("Repeat\ntimes");
179     gtk_table_attach(GTK_TABLE(parmTable), count_label, 3, 4, 0, 1,
180 		     __GTKATTACHOPTIONS(GTK_FILL | GTK_EXPAND |
181 					GTK_SHRINK),
182 		     __GTKATTACHOPTIONS(GTK_FILL | GTK_EXPAND |
183 					GTK_SHRINK), 0, 0);
184 
185 
186     gtk_signal_connect(GTK_OBJECT(adj_count), "value_changed",
187 		       GTK_SIGNAL_FUNC(update_echo_count), pecho);
188 
189     count = gtk_vscale_new(GTK_ADJUSTMENT(adj_count));
190 
191     gtk_table_attach(GTK_TABLE(parmTable), count, 3, 4, 1, 2,
192 		     __GTKATTACHOPTIONS
193 		     (GTK_FILL | GTK_EXPAND | GTK_SHRINK),
194 		     __GTKATTACHOPTIONS
195 		     (GTK_FILL | GTK_EXPAND | GTK_SHRINK), 0, 0);
196 
197     adj_size =
198 	gtk_adjustment_new(pecho->echo_size * 1000 /
199 			   (sample_rate * nchannels), 1.0,
200 			   MAX_ECHO_SIZE * 1000 / (sample_rate *
201 						   nchannels), 1.0, 1.0,
202 			   1.0);
203     size_label = gtk_label_new("Delay\nms");
204     gtk_table_attach(GTK_TABLE(parmTable), size_label, 5, 6, 0, 1,
205 		     __GTKATTACHOPTIONS(GTK_FILL | GTK_EXPAND |
206 					GTK_SHRINK),
207 		     __GTKATTACHOPTIONS(GTK_FILL | GTK_EXPAND |
208 					GTK_SHRINK), 0, 0);
209 
210 
211     gtk_signal_connect(GTK_OBJECT(adj_size), "value_changed",
212 		       GTK_SIGNAL_FUNC(update_echo_size), pecho);
213 
214     size = gtk_vscale_new(GTK_ADJUSTMENT(adj_size));
215 
216     gtk_table_attach(GTK_TABLE(parmTable), size, 5, 6, 1, 2,
217 		     __GTKATTACHOPTIONS
218 		     (GTK_FILL | GTK_EXPAND | GTK_SHRINK),
219 		     __GTKATTACHOPTIONS
220 		     (GTK_FILL | GTK_EXPAND | GTK_SHRINK), 0, 0);
221 
222 
223     button = gtk_check_button_new_with_label("On");
224     gtk_signal_connect(GTK_OBJECT(button), "toggled",
225 		       GTK_SIGNAL_FUNC(toggle_echo), p);
226 
227     gtk_table_attach(GTK_TABLE(parmTable), button, 3, 4, 3, 4,
228 		     __GTKATTACHOPTIONS
229 		     (GTK_FILL | GTK_EXPAND | GTK_SHRINK),
230 		     __GTKATTACHOPTIONS
231 		     (GTK_FILL | GTK_EXPAND | GTK_SHRINK), 0, 0);
232     if (p->toggle == 1) {
233 	p->toggle = 0;
234 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
235     }
236 
237     gtk_window_set_title(GTK_WINDOW(p->control), (gchar *) ("Echo"));
238     gtk_container_add(GTK_CONTAINER(p->control), parmTable);
239 
240     gtk_widget_show_all(p->control);
241 
242 }
243 
244 void
echo_filter(struct effect * p,struct data_block * db)245 echo_filter(struct effect *p, struct data_block *db)
246 {
247     DSP_SAMPLE     *s,sample;
248     int             j,
249                     count;
250     struct echo_params *ep;
251 
252     s = db->data;
253     count = db->len;
254 
255     ep = p->params;
256 
257     while (count) {
258 	sample = *s * ep->buffer_count;
259 	/*
260 	 * add sample, decay history
261 	 */
262 	for (j = 0; j < ep->buffer_count; j++) {
263 	    sample +=
264 		(ep->history[j][ep->index[j]] =
265 		 ep->history[j][ep->index[j]] * (ep->echo_decay +
266 						 j * 0) / 1000 + *s);
267 	    ep->index[j]++;
268 	    if (ep->index[j] >= ep->size[j])
269 		ep->index[j] = 0;
270 	}
271 	sample = sample / 2 / ep->buffer_count;
272 	*s = sample;
273 
274 	s++;
275 	count--;
276     }
277 }
278 
279 void
echo_done(struct effect * p)280 echo_done(struct effect *p)
281 {
282     struct echo_params *ep;
283     int             i;
284 
285     ep = p->params;
286 
287     for (i = 0; i < ep->buffer_count; i++) {
288 	free(ep->history[i]);
289     }
290 
291     free(ep->history);
292     gtk_widget_destroy(p->control);
293     free(p);
294     p = NULL;
295 }
296 
297 void
echo_save(struct effect * p,int fd)298 echo_save(struct effect *p, int fd)
299 {
300     struct echo_params *ep;
301 
302     ep = (struct echo_params *) p->params;
303 
304     write(fd, &ep->echo_size, sizeof(ep->echo_size));
305     write(fd, &ep->echo_decay, sizeof(ep->echo_decay));
306     write(fd, &ep->buffer_count, sizeof(ep->buffer_count));
307 }
308 
309 void
echo_load(struct effect * p,int fd)310 echo_load(struct effect *p, int fd)
311 {
312     struct echo_params *ep;
313 
314     ep = (struct echo_params *) p->params;
315 
316     read(fd, &ep->echo_size, sizeof(ep->echo_size));
317     read(fd, &ep->echo_decay, sizeof(ep->echo_decay));
318     read(fd, &ep->buffer_count, sizeof(ep->buffer_count));
319     if (p->toggle == 0) {
320 	p->proc_filter = passthru;
321     } else {
322 	p->proc_filter = echo_filter;
323     }
324 }
325 
326 void
echo_create(struct effect * p)327 echo_create(struct effect *p)
328 {
329     struct echo_params *pecho;
330     int             i = 10,
331                     k = 0;
332 
333     p->params = (struct echo_params *) malloc(sizeof(struct echo_params));
334     p->proc_init = echo_init;
335     p->proc_filter = passthru;
336     p->proc_save = echo_save;
337     p->proc_load = echo_load;
338     p->toggle = 0;
339     p->id = ECHO;
340     p->proc_done = echo_done;
341 
342     pecho = (struct echo_params *) p->params;
343 
344     pecho->echo_size = 128;
345     pecho->echo_decay = 700;
346     pecho->buffer_count = 20;
347 
348     pecho->history = (DSP_SAMPLE **) malloc(MAX_ECHO_COUNT * sizeof(DSP_SAMPLE *));
349     pecho->index = (int *) calloc(MAX_ECHO_COUNT, sizeof(int));
350     pecho->size = (int *) malloc(MAX_ECHO_COUNT * sizeof(int));
351     pecho->factor = (int *) malloc(MAX_ECHO_COUNT * sizeof(int));
352 
353     while (k < MAX_ECHO_COUNT) {
354 	while (!prime(i))
355 	    i++;
356 	i++;
357 	while (!prime(i))
358 	    i++;
359 	pecho->factor[k] = i;
360 	k++;
361 	i++;
362     }
363 
364     for (i = 0; i < MAX_ECHO_COUNT; i++) {
365 	pecho->size[i] = pecho->factor[i] * MAX_ECHO_SIZE;
366 	pecho->history[i] = (DSP_SAMPLE *) calloc(pecho->size[i], sizeof(DSP_SAMPLE));
367     }
368 }
369