1 /*                                                     -*- linux-c -*-
2     Copyright (C) 2004 Tom Szilagyi
3 
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.
8 
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.
13 
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.
17 
18     $Id: tap_echo.c,v 1.7 2004/12/06 09:32:41 tszilagyi Exp $
19 */
20 
21 
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <math.h>
26 
27 #include "ladspa.h"
28 #include "tap_utils.h"
29 
30 /* The Unique ID of the plugin: */
31 
32 #define ID_STEREO       2143
33 
34 /* The port numbers for the plugin: */
35 
36 #define DELAYTIME_L 0
37 #define FEEDBACK_L  1
38 #define DELAYTIME_R 2
39 #define FEEDBACK_R  3
40 #define STRENGTH_L  4
41 #define STRENGTH_R  5
42 #define DRYLEVEL    6
43 #define MODE        7
44 #define HAAS        8
45 #define REV_OUTCH   9
46 
47 #define INPUT_L     10
48 #define OUTPUT_L    11
49 #define INPUT_R     12
50 #define OUTPUT_R    13
51 
52 /* Total number of ports */
53 
54 #define PORTCOUNT_STEREO 14
55 
56 
57 /* Maximum delay (ms) */
58 
59 #define MAX_DELAY        2000
60 
61 
62 /* The structure used to hold port connection information and state */
63 
64 typedef struct {
65 	LADSPA_Data * delaytime_L;
66 	LADSPA_Data * delaytime_R;
67 	LADSPA_Data * feedback_L;
68 	LADSPA_Data * feedback_R;
69 	LADSPA_Data * strength_L;
70 	LADSPA_Data * strength_R;
71 	LADSPA_Data * drylevel;
72 	LADSPA_Data * mode;
73 	LADSPA_Data * haas;
74 	LADSPA_Data * rev_outch;
75 
76 	LADSPA_Data * input_L;
77 	LADSPA_Data * output_L;
78 	LADSPA_Data * input_R;
79 	LADSPA_Data * output_R;
80 
81 	unsigned long sample_rate;
82 	LADSPA_Data mpx_out_L;
83 	LADSPA_Data mpx_out_R;
84 
85 	LADSPA_Data * ringbuffer_L;
86 	LADSPA_Data * ringbuffer_R;
87 	unsigned long * buffer_pos_L;
88 	unsigned long * buffer_pos_R;
89 
90 	LADSPA_Data run_adding_gain;
91 } Echo;
92 
93 
94 
95 
96 /* Construct a new plugin instance. */
97 LADSPA_Handle
instantiate_Echo(const LADSPA_Descriptor * Descriptor,unsigned long SampleRate)98 instantiate_Echo(const LADSPA_Descriptor * Descriptor,
99 		 unsigned long             SampleRate) {
100 
101 	LADSPA_Handle * ptr;
102 
103 	if ((ptr = malloc(sizeof(Echo))) != NULL) {
104 		((Echo *)ptr)->sample_rate = SampleRate;
105 		((Echo *)ptr)->run_adding_gain = 1.0f;
106 
107 		/* allocate memory for ringbuffers and related dynamic vars */
108 		if ((((Echo *)ptr)->ringbuffer_L =
109 		     calloc(MAX_DELAY * ((Echo *)ptr)->sample_rate / 1000,
110 			    sizeof(LADSPA_Data))) == NULL)
111 			exit(1);
112 		if ((((Echo *)ptr)->ringbuffer_R =
113 		     calloc(MAX_DELAY * ((Echo *)ptr)->sample_rate / 1000,
114 			    sizeof(LADSPA_Data))) == NULL)
115 			exit(1);
116 		if ((((Echo *)ptr)->buffer_pos_L = calloc(1, sizeof(unsigned long))) == NULL)
117 			exit(1);
118 		if ((((Echo *)ptr)->buffer_pos_R = calloc(1, sizeof(unsigned long))) == NULL)
119 			exit(1);
120 
121 		*(((Echo *)ptr)->buffer_pos_L) = 0;
122 		*(((Echo *)ptr)->buffer_pos_R) = 0;
123 
124 		return ptr;
125 	}
126 
127 	return NULL;
128 }
129 
130 
131 /* activate a plugin instance */
132 void
activate_Echo(LADSPA_Handle Instance)133 activate_Echo(LADSPA_Handle Instance) {
134 
135 	Echo * ptr = (Echo *)Instance;
136 	int i;
137 
138 	ptr->mpx_out_L = 0;
139 	ptr->mpx_out_R = 0;
140 
141 	*(ptr->buffer_pos_L) = 0;
142 	*(ptr->buffer_pos_R) = 0;
143 
144 	for (i = 0; i < MAX_DELAY * ptr->sample_rate / 1000; i++) {
145 		ptr->ringbuffer_L[i] = 0.0f;
146 		ptr->ringbuffer_R[i] = 0.0f;
147 	}
148 }
149 
150 
151 /* Connect a port to a data location. */
152 void
connect_port_Echo(LADSPA_Handle Instance,unsigned long Port,LADSPA_Data * DataLocation)153 connect_port_Echo(LADSPA_Handle Instance,
154 		   unsigned long Port,
155 		   LADSPA_Data * DataLocation) {
156 
157 	Echo * ptr;
158 
159 	ptr = (Echo *)Instance;
160 	switch (Port) {
161 	case DELAYTIME_L:
162 		ptr->delaytime_L = DataLocation;
163 		break;
164 	case DELAYTIME_R:
165 		ptr->delaytime_R = DataLocation;
166 		break;
167 	case FEEDBACK_L:
168 		ptr->feedback_L = DataLocation;
169 		break;
170 	case FEEDBACK_R:
171 		ptr->feedback_R = DataLocation;
172 		break;
173 	case STRENGTH_L:
174 		ptr->strength_L = DataLocation;
175 		break;
176 	case STRENGTH_R:
177 		ptr->strength_R = DataLocation;
178 		break;
179 	case MODE:
180 		ptr->mode = DataLocation;
181 		break;
182 	case HAAS:
183 		ptr->haas = DataLocation;
184 		break;
185 	case REV_OUTCH:
186 		ptr->rev_outch = DataLocation;
187 		break;
188 	case DRYLEVEL:
189 		ptr->drylevel = DataLocation;
190 		break;
191 	case INPUT_L:
192 		ptr->input_L = DataLocation;
193 		break;
194 	case OUTPUT_L:
195 		ptr->output_L = DataLocation;
196 		break;
197 	case INPUT_R:
198 		ptr->input_R = DataLocation;
199 		break;
200 	case OUTPUT_R:
201 		ptr->output_R = DataLocation;
202 		break;
203 	}
204 }
205 
206 
207 #define EPS 0.00000001f
208 
209 static inline float
M(float x)210 M(float x) {
211 
212         if ((x > EPS) || (x < -EPS))
213                 return x;
214         else
215                 return 0.0f;
216 }
217 
218 void
run_Echo(LADSPA_Handle Instance,unsigned long SampleCount)219 run_Echo(LADSPA_Handle Instance,
220 	 unsigned long SampleCount) {
221 
222 	Echo * ptr;
223 	unsigned long sample_index;
224 
225 	LADSPA_Data delaytime_L;
226 	LADSPA_Data delaytime_R;
227 	LADSPA_Data feedback_L;
228 	LADSPA_Data feedback_R;
229 	LADSPA_Data strength_L;
230 	LADSPA_Data strength_R;
231 	LADSPA_Data drylevel;
232 	LADSPA_Data mode;
233 	LADSPA_Data haas;
234 	LADSPA_Data rev_outch;
235 
236 	LADSPA_Data * input_L;
237 	LADSPA_Data * output_L;
238 	LADSPA_Data * input_R;
239 	LADSPA_Data * output_R;
240 
241 	unsigned long sample_rate;
242 	unsigned long buflen_L;
243 	unsigned long buflen_R;
244 
245 	LADSPA_Data out_L = 0;
246 	LADSPA_Data out_R = 0;
247 	LADSPA_Data in_L = 0;
248 	LADSPA_Data in_R = 0;
249 
250 	ptr = (Echo *)Instance;
251 
252 	delaytime_L = LIMIT(*(ptr->delaytime_L),0.0f,2000.0f);
253 	delaytime_R = LIMIT(*(ptr->delaytime_R),0.0f,2000.0f);
254 	feedback_L = LIMIT(*(ptr->feedback_L) / 100.0, 0.0f, 100.0f);
255 	feedback_R = LIMIT(*(ptr->feedback_R) / 100.0, 0.0f, 100.0f);
256         strength_L = db2lin(LIMIT(*(ptr->strength_L),-70.0f,10.0f));
257 	strength_R = db2lin(LIMIT(*(ptr->strength_R),-70.0f,10.0f));
258 	drylevel = db2lin(LIMIT(*(ptr->drylevel),-70.0f,10.0f));
259 	mode = LIMIT(*(ptr->mode),-2.0f,2.0f);
260 	haas = LIMIT(*(ptr->haas),-2.0f,2.0f);
261 	rev_outch = LIMIT(*(ptr->rev_outch),-2.0f,2.0f);
262 
263       	input_L = ptr->input_L;
264 	output_L = ptr->output_L;
265       	input_R = ptr->input_R;
266 	output_R = ptr->output_R;
267 
268 	sample_rate = ptr->sample_rate;
269 	buflen_L = delaytime_L * sample_rate / 1000;
270 	buflen_R = delaytime_R * sample_rate / 1000;
271 
272 
273 	for (sample_index = 0; sample_index < SampleCount; sample_index++) {
274 
275 		in_L = *(input_L++);
276 		in_R = *(input_R++);
277 
278 		out_L = in_L * drylevel + ptr->mpx_out_L * strength_L;
279 		out_R = in_R * drylevel + ptr->mpx_out_R * strength_R;
280 
281 		if (haas > 0.0f)
282 			in_R = 0.0f;
283 
284 		if (mode <= 0.0f) {
285 			ptr->mpx_out_L =
286 				M(push_buffer(in_L + ptr->mpx_out_L * feedback_L,
287 					      ptr->ringbuffer_L, buflen_L, ptr->buffer_pos_L));
288 			ptr->mpx_out_R =
289 				M(push_buffer(in_R + ptr->mpx_out_R * feedback_R,
290 					      ptr->ringbuffer_R, buflen_R, ptr->buffer_pos_R));
291 		} else {
292 			ptr->mpx_out_R =
293 				M(push_buffer(in_L + ptr->mpx_out_L * feedback_L,
294 					      ptr->ringbuffer_L, buflen_L, ptr->buffer_pos_L));
295 			ptr->mpx_out_L =
296 				M(push_buffer(in_R + ptr->mpx_out_R * feedback_R,
297 					      ptr->ringbuffer_R, buflen_R, ptr->buffer_pos_R));
298 		}
299 
300 		if (rev_outch <= 0.0f) {
301 			*(output_L++) = out_L;
302 			*(output_R++) = out_R;
303 		} else {
304 			*(output_L++) = out_R;
305 			*(output_R++) = out_L;
306 		}
307 	}
308 }
309 
310 
311 
312 
313 
314 void
set_run_adding_gain(LADSPA_Handle Instance,LADSPA_Data gain)315 set_run_adding_gain(LADSPA_Handle Instance, LADSPA_Data gain){
316 
317 	Echo * ptr;
318 
319 	ptr = (Echo *)Instance;
320 
321 	ptr->run_adding_gain = gain;
322 }
323 
324 
325 void
run_adding_gain_Echo(LADSPA_Handle Instance,unsigned long SampleCount)326 run_adding_gain_Echo(LADSPA_Handle Instance,
327 	 unsigned long SampleCount) {
328 
329 	Echo * ptr;
330 	unsigned long sample_index;
331 
332 	LADSPA_Data delaytime_L;
333 	LADSPA_Data delaytime_R;
334 	LADSPA_Data feedback_L;
335 	LADSPA_Data feedback_R;
336 	LADSPA_Data strength_L;
337 	LADSPA_Data strength_R;
338 	LADSPA_Data drylevel;
339 	LADSPA_Data mode;
340 	LADSPA_Data haas;
341 	LADSPA_Data rev_outch;
342 
343 	LADSPA_Data * input_L;
344 	LADSPA_Data * output_L;
345 	LADSPA_Data * input_R;
346 	LADSPA_Data * output_R;
347 
348 	unsigned long sample_rate;
349 	unsigned long buflen_L;
350 	unsigned long buflen_R;
351 
352 	LADSPA_Data out_L = 0;
353 	LADSPA_Data out_R = 0;
354 	LADSPA_Data in_L = 0;
355 	LADSPA_Data in_R = 0;
356 
357 	ptr = (Echo *)Instance;
358 
359 	delaytime_L = LIMIT(*(ptr->delaytime_L),0.0f,2000.0f);
360 	delaytime_R = LIMIT(*(ptr->delaytime_R),0.0f,2000.0f);
361 	feedback_L = LIMIT(*(ptr->feedback_L) / 100.0, 0.0f, 100.0f);
362 	feedback_R = LIMIT(*(ptr->feedback_R) / 100.0, 0.0f, 100.0f);
363         strength_L = db2lin(LIMIT(*(ptr->strength_L),-70.0f,10.0f));
364 	strength_R = db2lin(LIMIT(*(ptr->strength_R),-70.0f,10.0f));
365 	drylevel = db2lin(LIMIT(*(ptr->drylevel),-70.0f,10.0f));
366 	mode = LIMIT(*(ptr->mode),-2.0f,2.0f);
367 	haas = LIMIT(*(ptr->haas),-2.0f,2.0f);
368 	rev_outch = LIMIT(*(ptr->rev_outch),-2.0f,2.0f);
369 
370       	input_L = ptr->input_L;
371 	output_L = ptr->output_L;
372       	input_R = ptr->input_R;
373 	output_R = ptr->output_R;
374 
375 	sample_rate = ptr->sample_rate;
376 	buflen_L = delaytime_L * sample_rate / 1000;
377 	buflen_R = delaytime_R * sample_rate / 1000;
378 
379 
380 	for (sample_index = 0; sample_index < SampleCount; sample_index++) {
381 
382 		in_L = *(input_L++);
383 		in_R = *(input_R++);
384 
385 		out_L = in_L * drylevel + ptr->mpx_out_L * strength_L;
386 		out_R = in_R * drylevel + ptr->mpx_out_R * strength_R;
387 
388 		if (haas > 0.0f)
389 			in_R = 0.0f;
390 
391 		if (mode <= 0.0f) {
392 			ptr->mpx_out_L =
393 				M(push_buffer(in_L + ptr->mpx_out_L * feedback_L,
394 					      ptr->ringbuffer_L, buflen_L, ptr->buffer_pos_L));
395 			ptr->mpx_out_R =
396 				M(push_buffer(in_R + ptr->mpx_out_R * feedback_R,
397 					      ptr->ringbuffer_R, buflen_R, ptr->buffer_pos_R));
398 		} else {
399 			ptr->mpx_out_R =
400 				M(push_buffer(in_L + ptr->mpx_out_L * feedback_L,
401 					      ptr->ringbuffer_L, buflen_L, ptr->buffer_pos_L));
402 			ptr->mpx_out_L =
403 				M(push_buffer(in_R + ptr->mpx_out_R * feedback_R,
404 					      ptr->ringbuffer_R, buflen_R, ptr->buffer_pos_R));
405 		}
406 
407 		if (rev_outch <= 0.0f) {
408 			*(output_L++) += out_L * ptr->run_adding_gain;
409 			*(output_R++) += out_R * ptr->run_adding_gain;
410 		} else {
411 			*(output_L++) += out_R * ptr->run_adding_gain;
412 			*(output_R++) += out_L * ptr->run_adding_gain;
413 		}
414 	}
415 }
416 
417 
418 
419 /* Throw away an Echo effect instance. */
420 void
cleanup_Echo(LADSPA_Handle Instance)421 cleanup_Echo(LADSPA_Handle Instance) {
422 
423 	Echo * ptr = (Echo *)Instance;
424 
425 	free(ptr->ringbuffer_L);
426 	free(ptr->ringbuffer_R);
427 	free(ptr->buffer_pos_L);
428 	free(ptr->buffer_pos_R);
429 
430 	free(Instance);
431 }
432 
433 
434 
435 LADSPA_Descriptor * stereo_descriptor = NULL;
436 
437 
438 
439 /* _init() is called automatically when the plugin library is first
440    loaded. */
441 void
_init()442 _init() {
443 
444 	char ** port_names;
445 	LADSPA_PortDescriptor * port_descriptors;
446 	LADSPA_PortRangeHint * port_range_hints;
447 
448 	if ((stereo_descriptor =
449 	     (LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor))) == NULL)
450 		exit(1);
451 
452 
453 	/* init the stereo Echo */
454 
455 	stereo_descriptor->UniqueID = ID_STEREO;
456 	stereo_descriptor->Label = strdup("tap_stereo_echo");
457 	stereo_descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE;
458 	stereo_descriptor->Name = strdup("TAP Stereo Echo");
459 	stereo_descriptor->Maker = strdup("Tom Szilagyi");
460 	stereo_descriptor->Copyright = strdup("GPL");
461 	stereo_descriptor->PortCount = PORTCOUNT_STEREO;
462 
463 	if ((port_descriptors =
464 	     (LADSPA_PortDescriptor *)calloc(PORTCOUNT_STEREO, sizeof(LADSPA_PortDescriptor))) == NULL)
465 		exit(1);
466 
467 	stereo_descriptor->PortDescriptors = (const LADSPA_PortDescriptor *)port_descriptors;
468 	port_descriptors[DELAYTIME_L] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
469 	port_descriptors[DELAYTIME_R] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
470 	port_descriptors[FEEDBACK_L] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
471 	port_descriptors[FEEDBACK_R] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
472 	port_descriptors[STRENGTH_L] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
473 	port_descriptors[STRENGTH_R] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
474 	port_descriptors[DRYLEVEL] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
475 	port_descriptors[MODE] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
476 	port_descriptors[HAAS] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
477 	port_descriptors[REV_OUTCH] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
478 
479 	port_descriptors[INPUT_L] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
480 	port_descriptors[OUTPUT_L] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
481 	port_descriptors[INPUT_R] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
482 	port_descriptors[OUTPUT_R] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
483 
484 	if ((port_names =
485 	     (char **)calloc(PORTCOUNT_STEREO, sizeof(char *))) == NULL)
486 		exit(1);
487 
488 	stereo_descriptor->PortNames = (const char **)port_names;
489 
490 	port_names[DELAYTIME_L] = strdup("L Delay [ms]");
491 	port_names[DELAYTIME_R] = strdup("R/Haas Delay [ms]");
492 	port_names[FEEDBACK_L] = strdup("L Feedback [%]");
493 	port_names[FEEDBACK_R] = strdup("R/Haas Feedback [%]");
494 	port_names[STRENGTH_L] = strdup("L Echo Level [dB]");
495 	port_names[STRENGTH_R] = strdup("R Echo Level [dB]");
496 	port_names[DRYLEVEL] = strdup("Dry Level [dB]");
497 	port_names[MODE] = strdup("Cross Mode");
498 	port_names[HAAS] = strdup("Haas Effect");
499 	port_names[REV_OUTCH] = strdup("Swap Outputs");
500 
501 	port_names[INPUT_L] = strdup("Input Left");
502 	port_names[OUTPUT_L] = strdup("Output Left");
503 	port_names[INPUT_R] = strdup("Input Right");
504 	port_names[OUTPUT_R] = strdup("Output Right");
505 
506 	if ((port_range_hints =
507 	     ((LADSPA_PortRangeHint *)calloc(PORTCOUNT_STEREO, sizeof(LADSPA_PortRangeHint)))) == NULL)
508 		exit(1);
509 
510 	stereo_descriptor->PortRangeHints = (const LADSPA_PortRangeHint *)port_range_hints;
511 
512 	port_range_hints[DELAYTIME_L].HintDescriptor =
513 		(LADSPA_HINT_BOUNDED_BELOW |
514 		 LADSPA_HINT_BOUNDED_ABOVE |
515 		 LADSPA_HINT_DEFAULT_100);
516 	port_range_hints[DELAYTIME_L].LowerBound = 0;
517 	port_range_hints[DELAYTIME_L].UpperBound = MAX_DELAY;
518 
519 	port_range_hints[DELAYTIME_R].HintDescriptor =
520 		(LADSPA_HINT_BOUNDED_BELOW |
521 		 LADSPA_HINT_BOUNDED_ABOVE |
522 		 LADSPA_HINT_DEFAULT_100);
523 	port_range_hints[DELAYTIME_R].LowerBound = 0;
524 	port_range_hints[DELAYTIME_R].UpperBound = MAX_DELAY;
525 
526 	port_range_hints[FEEDBACK_L].HintDescriptor =
527 		(LADSPA_HINT_BOUNDED_BELOW |
528 		 LADSPA_HINT_BOUNDED_ABOVE |
529 		 LADSPA_HINT_DEFAULT_0);
530 	port_range_hints[FEEDBACK_L].LowerBound = 0;
531 	port_range_hints[FEEDBACK_L].UpperBound = 100;
532 
533 	port_range_hints[FEEDBACK_R].HintDescriptor =
534 		(LADSPA_HINT_BOUNDED_BELOW |
535 		 LADSPA_HINT_BOUNDED_ABOVE |
536 		 LADSPA_HINT_DEFAULT_0);
537 	port_range_hints[FEEDBACK_R].LowerBound = 0;
538 	port_range_hints[FEEDBACK_R].UpperBound = 100;
539 
540 	port_range_hints[STRENGTH_L].HintDescriptor =
541 		(LADSPA_HINT_BOUNDED_BELOW |
542 		 LADSPA_HINT_BOUNDED_ABOVE |
543 		 LADSPA_HINT_DEFAULT_0);
544 	port_range_hints[STRENGTH_L].LowerBound = -70;
545 	port_range_hints[STRENGTH_L].UpperBound = 10;
546 
547 	port_range_hints[STRENGTH_R].HintDescriptor =
548 		(LADSPA_HINT_BOUNDED_BELOW |
549 		 LADSPA_HINT_BOUNDED_ABOVE |
550 		 LADSPA_HINT_DEFAULT_0);
551 	port_range_hints[STRENGTH_R].LowerBound = -70;
552 	port_range_hints[STRENGTH_R].UpperBound = 10;
553 
554 	port_range_hints[MODE].HintDescriptor =
555 		(LADSPA_HINT_TOGGLED |
556 		 LADSPA_HINT_DEFAULT_0);
557 
558 	port_range_hints[HAAS].HintDescriptor =
559 		(LADSPA_HINT_TOGGLED |
560 		 LADSPA_HINT_DEFAULT_0);
561 
562 	port_range_hints[REV_OUTCH].HintDescriptor =
563 		(LADSPA_HINT_TOGGLED |
564 		 LADSPA_HINT_DEFAULT_0);
565 
566 	port_range_hints[DRYLEVEL].HintDescriptor =
567 		(LADSPA_HINT_BOUNDED_BELOW |
568 		 LADSPA_HINT_BOUNDED_ABOVE |
569 		 LADSPA_HINT_DEFAULT_0);
570 	port_range_hints[DRYLEVEL].LowerBound = -70;
571 	port_range_hints[DRYLEVEL].UpperBound = 10;
572 
573 
574 	port_range_hints[INPUT_L].HintDescriptor = 0;
575 	port_range_hints[OUTPUT_L].HintDescriptor = 0;
576 	port_range_hints[INPUT_R].HintDescriptor = 0;
577 	port_range_hints[OUTPUT_R].HintDescriptor = 0;
578 
579 
580 	stereo_descriptor->instantiate = instantiate_Echo;
581 	stereo_descriptor->connect_port = connect_port_Echo;
582 	stereo_descriptor->activate = activate_Echo;
583 	stereo_descriptor->run = run_Echo;
584 	stereo_descriptor->run_adding = run_adding_gain_Echo;
585 	stereo_descriptor->set_run_adding_gain = set_run_adding_gain;
586 	stereo_descriptor->deactivate = NULL;
587 	stereo_descriptor->cleanup = cleanup_Echo;
588 
589 }
590 
591 
592 void
delete_descriptor(LADSPA_Descriptor * descriptor)593 delete_descriptor(LADSPA_Descriptor * descriptor) {
594 	unsigned long index;
595 	if (descriptor) {
596 		free((char *)descriptor->Label);
597 		free((char *)descriptor->Name);
598 		free((char *)descriptor->Maker);
599 		free((char *)descriptor->Copyright);
600 		free((LADSPA_PortDescriptor *)descriptor->PortDescriptors);
601 		for (index = 0; index < descriptor->PortCount; index++)
602 			free((char *)(descriptor->PortNames[index]));
603 		free((char **)descriptor->PortNames);
604 		free((LADSPA_PortRangeHint *)descriptor->PortRangeHints);
605 		free(descriptor);
606 	}
607 }
608 
609 
610 /* _fini() is called automatically when the library is unloaded. */
611 void
_fini()612 _fini() {
613 	delete_descriptor(stereo_descriptor);
614 }
615 
616 
617 /* Return a descriptor of the requested plugin type. */
618 
619 const
620 LADSPA_Descriptor *
ladspa_descriptor(unsigned long Index)621 ladspa_descriptor(unsigned long Index) {
622 
623 	switch (Index) {
624 	case 0:
625 		return stereo_descriptor;
626 	default:
627 		return NULL;
628 	}
629 }
630