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