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_pitch.c,v 1.2 2004/02/21 17:33:36 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 
31 /* The Unique ID of the plugin: */
32 
33 #define ID_MONO         2150
34 
35 /* The port numbers for the plugin: */
36 
37 #define SEMITONE        0
38 #define RATE            1
39 #define DRYLEVEL        2
40 #define WETLEVEL        3
41 #define LATENCY         4
42 #define INPUT           5
43 #define OUTPUT          6
44 
45 /* Total number of ports */
46 
47 
48 #define PORTCOUNT_MONO   7
49 
50 
51 /* depth of phase mod (yes, this is a magic number) */
52 #define PM_DEPTH 3681.0f
53 
54 
55 /* another magic number, derived from the above one */
56 #define PM_BUFLEN 16027
57 
58 
59 /* frequency of the modulation signal (Hz) */
60 #define PM_FREQ 6.0f
61 
62 
63 #define COS_TABLE_SIZE 1024
64 LADSPA_Data cos_table[COS_TABLE_SIZE];
65 
66 
67 /* \sqrt{12}{2} used for key frequency computing */
68 #define ROOT_12_2  1.059463094f
69 
70 
71 /* The structure used to hold port connection information and state */
72 
73 typedef struct {
74 	LADSPA_Data * rate;
75 	LADSPA_Data * semitone;
76 	LADSPA_Data * drylevel;
77 	LADSPA_Data * wetlevel;
78 	LADSPA_Data * latency;
79 	LADSPA_Data * input;
80 	LADSPA_Data * output;
81 
82 	LADSPA_Data * ringbuffer;
83 	unsigned long buflen;
84 	unsigned long pos;
85 	LADSPA_Data phase;
86 
87 	unsigned long sample_rate;
88 	LADSPA_Data run_adding_gain;
89 } Pitch;
90 
91 
92 
93 /* Construct a new plugin instance. */
94 LADSPA_Handle
instantiate_Pitch(const LADSPA_Descriptor * Descriptor,unsigned long sample_rate)95 instantiate_Pitch(const LADSPA_Descriptor * Descriptor,
96 		  unsigned long             sample_rate) {
97 
98         LADSPA_Handle * ptr;
99 
100 	if ((ptr = malloc(sizeof(Pitch))) != NULL) {
101 		((Pitch *)ptr)->sample_rate = sample_rate;
102 		((Pitch *)ptr)->run_adding_gain = 1.0f;
103 
104 		if ((((Pitch *)ptr)->ringbuffer =
105 		     calloc(2 * PM_BUFLEN, sizeof(LADSPA_Data))) == NULL)
106 			return NULL;
107 		((Pitch *)ptr)->buflen = 2 * PM_BUFLEN * sample_rate / 192000;
108 		((Pitch *)ptr)->pos = 0;
109 
110 		return ptr;
111 	}
112        	return NULL;
113 }
114 
115 
116 void
activate_Pitch(LADSPA_Handle Instance)117 activate_Pitch(LADSPA_Handle Instance) {
118 
119 	Pitch * ptr = (Pitch *)Instance;
120 	unsigned long i;
121 
122 	for (i = 0; i < ptr->buflen; i++)
123 		ptr->ringbuffer[i] = 0.0f;
124 
125 	ptr->phase = 0.0f;
126 }
127 
128 
129 
130 
131 
132 /* Connect a port to a data location. */
133 void
connect_port_Pitch(LADSPA_Handle Instance,unsigned long Port,LADSPA_Data * DataLocation)134 connect_port_Pitch(LADSPA_Handle Instance,
135 		     unsigned long Port,
136 		     LADSPA_Data * DataLocation) {
137 
138 	Pitch * ptr = (Pitch *)Instance;
139 
140 	switch (Port) {
141 	case RATE:
142 		ptr->rate = DataLocation;
143 		break;
144 	case SEMITONE:
145 		ptr->semitone = DataLocation;
146 		break;
147 	case DRYLEVEL:
148 		ptr->drylevel = DataLocation;
149 		break;
150 	case WETLEVEL:
151 		ptr->wetlevel = DataLocation;
152 		break;
153 	case LATENCY:
154 		ptr->latency = DataLocation;
155 		*(ptr->latency) = ptr->buflen / 2; /* IS THIS LEGAL? */
156 		break;
157 	case INPUT:
158 		ptr->input = DataLocation;
159 		break;
160 	case OUTPUT:
161 		ptr->output = DataLocation;
162 		break;
163 	}
164 }
165 
166 
167 
168 void
run_Pitch(LADSPA_Handle Instance,unsigned long SampleCount)169 run_Pitch(LADSPA_Handle Instance,
170 	    unsigned long SampleCount) {
171 
172 	Pitch * ptr = (Pitch *)Instance;
173 	LADSPA_Data * input = ptr->input;
174 	LADSPA_Data * output = ptr->output;
175 	LADSPA_Data drylevel = db2lin(LIMIT(*(ptr->drylevel),-90.0f,20.0f));
176 	LADSPA_Data wetlevel = 0.333333f * db2lin(LIMIT(*(ptr->wetlevel),-90.0f,20.0f));
177 	LADSPA_Data buflen = ptr->buflen / 2.0f;
178 	LADSPA_Data semitone = LIMIT(*(ptr->semitone),-12.0f,12.0f);
179 	LADSPA_Data rate;
180 	LADSPA_Data r;
181 	LADSPA_Data depth;
182 
183 	unsigned long sample_index;
184 	unsigned long sample_count = SampleCount;
185 
186 	LADSPA_Data in = 0.0f;
187 	LADSPA_Data sign = 1.0f;
188 	LADSPA_Data phase_0 = 0.0f;
189 	LADSPA_Data phase_am_0 = 0.0f;
190 	LADSPA_Data phase_1 = 0.0f;
191 	LADSPA_Data phase_am_1 = 0.0f;
192 	LADSPA_Data phase_2 = 0.0f;
193 	LADSPA_Data phase_am_2 = 0.0f;
194 	LADSPA_Data fpos_0 = 0.0f, fpos_1 = 0.0f, fpos_2 = 0.0f;
195 	LADSPA_Data n_0 = 0.0f, n_1 = 0.0f, n_2 = 0.0f;
196 	LADSPA_Data rem_0 = 0.0f, rem_1 = 0.0f, rem_2 = 0.0f;
197 	LADSPA_Data sa_0, sb_0, sa_1, sb_1, sa_2, sb_2;
198 
199 
200 	if (semitone == 0.0f)
201 		rate = LIMIT(*(ptr->rate),-50.0f,100.0f);
202 	else
203 		rate = 100.0f * (powf(ROOT_12_2,semitone) - 1.0f);
204 
205 	r = -1.0f * ABS(rate);
206 	depth = buflen * LIMIT(ABS(r) / 100.0f, 0.0f, 1.0f);
207 
208 
209 	if (rate > 0.0f)
210 		sign = -1.0f;
211 
212 	for (sample_index = 0; sample_index < sample_count; sample_index++) {
213 
214 		in = *(input++);
215 
216 		phase_0 = COS_TABLE_SIZE * PM_FREQ * sample_index / ptr->sample_rate + ptr->phase;
217 		while (phase_0 >= COS_TABLE_SIZE)
218 		        phase_0 -= COS_TABLE_SIZE;
219 		phase_am_0 = phase_0 + COS_TABLE_SIZE/2;
220 		while (phase_am_0 >= COS_TABLE_SIZE)
221 			phase_am_0 -= COS_TABLE_SIZE;
222 
223 		phase_1 = phase_0 + COS_TABLE_SIZE/3.0f;
224 		while (phase_1 >= COS_TABLE_SIZE)
225 		        phase_1 -= COS_TABLE_SIZE;
226 		phase_am_1 = phase_1 + COS_TABLE_SIZE/2;
227 		while (phase_am_1 >= COS_TABLE_SIZE)
228 			phase_am_1 -= COS_TABLE_SIZE;
229 
230 		phase_2 = phase_0 + 2.0f*COS_TABLE_SIZE/3.0f;
231 		while (phase_2 >= COS_TABLE_SIZE)
232 		        phase_2 -= COS_TABLE_SIZE;
233 		phase_am_2 = phase_2 + COS_TABLE_SIZE/2;
234 		while (phase_am_2 >= COS_TABLE_SIZE)
235 			phase_am_2 -= COS_TABLE_SIZE;
236 
237 		push_buffer(in, ptr->ringbuffer, ptr->buflen, &(ptr->pos));
238 
239 		fpos_0 = depth * (1.0f - sign * (2.0f * phase_0 / COS_TABLE_SIZE - 1.0f));
240 		n_0 = floorf(fpos_0);
241 		rem_0 = fpos_0 - n_0;
242 
243 		fpos_1 = depth * (1.0f - sign * (2.0f * phase_1 / COS_TABLE_SIZE - 1.0f));
244 		n_1 = floorf(fpos_1);
245 		rem_1 = fpos_1 - n_1;
246 
247 		fpos_2 = depth * (1.0f - sign * (2.0f * phase_2 / COS_TABLE_SIZE - 1.0f));
248 		n_2 = floorf(fpos_2);
249 		rem_2 = fpos_2 - n_2;
250 
251 		sa_0 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_0);
252 		sb_0 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_0 + 1);
253 
254 		sa_1 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_1);
255 		sb_1 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_1 + 1);
256 
257 		sa_2 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_2);
258 		sb_2 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_2 + 1);
259 
260 		*(output++) =
261 			wetlevel *
262 			((1.0f + cos_table[(unsigned long) phase_am_0]) *
263 			 ((1 - rem_0) * sa_0 + rem_0 * sb_0) +
264 			 (1.0f + cos_table[(unsigned long) phase_am_1]) *
265 			 ((1 - rem_1) * sa_1 + rem_1 * sb_1) +
266 			 (1.0f + cos_table[(unsigned long) phase_am_2]) *
267 			 ((1 - rem_2) * sa_2 + rem_2 * sb_2)) +
268 			drylevel *
269 			read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) depth);
270 
271 	}
272 
273 	ptr->phase += COS_TABLE_SIZE * PM_FREQ * sample_index / ptr->sample_rate;
274 	while (ptr->phase >= COS_TABLE_SIZE)
275 		ptr->phase -= COS_TABLE_SIZE;
276 
277 	*(ptr->latency) = buflen - (unsigned long) depth;
278 }
279 
280 
281 
282 void
set_run_adding_gain_Pitch(LADSPA_Handle Instance,LADSPA_Data gain)283 set_run_adding_gain_Pitch(LADSPA_Handle Instance, LADSPA_Data gain) {
284 
285 	Pitch * ptr = (Pitch *)Instance;
286 
287 	ptr->run_adding_gain = gain;
288 }
289 
290 
291 
292 void
run_adding_Pitch(LADSPA_Handle Instance,unsigned long SampleCount)293 run_adding_Pitch(LADSPA_Handle Instance,
294                  unsigned long SampleCount) {
295 
296 	Pitch * ptr = (Pitch *)Instance;
297 	LADSPA_Data * input = ptr->input;
298 	LADSPA_Data * output = ptr->output;
299 	LADSPA_Data drylevel = db2lin(LIMIT(*(ptr->drylevel),-90.0f,20.0f));
300 	LADSPA_Data wetlevel = 0.333333f * db2lin(LIMIT(*(ptr->wetlevel),-90.0f,20.0f));
301 	LADSPA_Data buflen = ptr->buflen / 2.0f;
302 	LADSPA_Data semitone = LIMIT(*(ptr->semitone),-12.0f,12.0f);
303 	LADSPA_Data rate;
304 	LADSPA_Data r;
305 	LADSPA_Data depth;
306 
307 	unsigned long sample_index;
308 	unsigned long sample_count = SampleCount;
309 
310 	LADSPA_Data in = 0.0f;
311 	LADSPA_Data sign = 1.0f;
312 	LADSPA_Data phase_0 = 0.0f;
313 	LADSPA_Data phase_am_0 = 0.0f;
314 	LADSPA_Data phase_1 = 0.0f;
315 	LADSPA_Data phase_am_1 = 0.0f;
316 	LADSPA_Data phase_2 = 0.0f;
317 	LADSPA_Data phase_am_2 = 0.0f;
318 	LADSPA_Data fpos_0 = 0.0f, fpos_1 = 0.0f, fpos_2 = 0.0f;
319 	LADSPA_Data n_0 = 0.0f, n_1 = 0.0f, n_2 = 0.0f;
320 	LADSPA_Data rem_0 = 0.0f, rem_1 = 0.0f, rem_2 = 0.0f;
321 	LADSPA_Data sa_0, sb_0, sa_1, sb_1, sa_2, sb_2;
322 
323 
324 	if (semitone == 0.0f)
325 		rate = LIMIT(*(ptr->rate),-50.0f,100.0f);
326 	else
327 		rate = 100.0f * (powf(ROOT_12_2,semitone) - 1.0f);
328 
329 	r = -1.0f * ABS(rate);
330 	depth = buflen * LIMIT(ABS(r) / 100.0f, 0.0f, 1.0f);
331 
332 
333 	if (rate > 0.0f)
334 		sign = -1.0f;
335 
336 	for (sample_index = 0; sample_index < sample_count; sample_index++) {
337 
338 		in = *(input++);
339 
340 		phase_0 = COS_TABLE_SIZE * PM_FREQ * sample_index / ptr->sample_rate + ptr->phase;
341 		while (phase_0 >= COS_TABLE_SIZE)
342 		        phase_0 -= COS_TABLE_SIZE;
343 		phase_am_0 = phase_0 + COS_TABLE_SIZE/2;
344 		while (phase_am_0 >= COS_TABLE_SIZE)
345 			phase_am_0 -= COS_TABLE_SIZE;
346 
347 		phase_1 = phase_0 + COS_TABLE_SIZE/3.0f;
348 		while (phase_1 >= COS_TABLE_SIZE)
349 		        phase_1 -= COS_TABLE_SIZE;
350 		phase_am_1 = phase_1 + COS_TABLE_SIZE/2;
351 		while (phase_am_1 >= COS_TABLE_SIZE)
352 			phase_am_1 -= COS_TABLE_SIZE;
353 
354 		phase_2 = phase_0 + 2.0f*COS_TABLE_SIZE/3.0f;
355 		while (phase_2 >= COS_TABLE_SIZE)
356 		        phase_2 -= COS_TABLE_SIZE;
357 		phase_am_2 = phase_2 + COS_TABLE_SIZE/2;
358 		while (phase_am_2 >= COS_TABLE_SIZE)
359 			phase_am_2 -= COS_TABLE_SIZE;
360 
361 		push_buffer(in, ptr->ringbuffer, ptr->buflen, &(ptr->pos));
362 
363 		fpos_0 = depth * (1.0f - sign * (2.0f * phase_0 / COS_TABLE_SIZE - 1.0f));
364 		n_0 = floorf(fpos_0);
365 		rem_0 = fpos_0 - n_0;
366 
367 		fpos_1 = depth * (1.0f - sign * (2.0f * phase_1 / COS_TABLE_SIZE - 1.0f));
368 		n_1 = floorf(fpos_1);
369 		rem_1 = fpos_1 - n_1;
370 
371 		fpos_2 = depth * (1.0f - sign * (2.0f * phase_2 / COS_TABLE_SIZE - 1.0f));
372 		n_2 = floorf(fpos_2);
373 		rem_2 = fpos_2 - n_2;
374 
375 		sa_0 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_0);
376 		sb_0 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_0 + 1);
377 
378 		sa_1 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_1);
379 		sb_1 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_1 + 1);
380 
381 		sa_2 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_2);
382 		sb_2 = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n_2 + 1);
383 
384 		*(output++) += ptr->run_adding_gain *
385 			wetlevel *
386 			((1.0f + cos_table[(unsigned long) phase_am_0]) *
387 			 ((1 - rem_0) * sa_0 + rem_0 * sb_0) +
388 			 (1.0f + cos_table[(unsigned long) phase_am_1]) *
389 			 ((1 - rem_1) * sa_1 + rem_1 * sb_1) +
390 			 (1.0f + cos_table[(unsigned long) phase_am_2]) *
391 			 ((1 - rem_2) * sa_2 + rem_2 * sb_2)) +
392 			drylevel *
393 			read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) depth);
394 
395 	}
396 
397 	ptr->phase += COS_TABLE_SIZE * PM_FREQ * sample_index / ptr->sample_rate;
398 	while (ptr->phase >= COS_TABLE_SIZE)
399 		ptr->phase -= COS_TABLE_SIZE;
400 
401 	*(ptr->latency) = buflen - (unsigned long) depth;
402 }
403 
404 
405 
406 /* Throw away a Pitch effect instance. */
407 void
cleanup_Pitch(LADSPA_Handle Instance)408 cleanup_Pitch(LADSPA_Handle Instance) {
409 
410   	Pitch * ptr = (Pitch *)Instance;
411 	free(ptr->ringbuffer);
412 	free(Instance);
413 }
414 
415 
416 
417 LADSPA_Descriptor * mono_descriptor = NULL;
418 
419 
420 
421 /* _init() is called automatically when the plugin library is first
422    loaded. */
423 void
_init()424 _init() {
425 
426 	int i;
427 	char ** port_names;
428 	LADSPA_PortDescriptor * port_descriptors;
429 	LADSPA_PortRangeHint * port_range_hints;
430 
431 	if ((mono_descriptor =
432 	     (LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor))) == NULL)
433 		exit(1);
434 
435 	for (i = 0; i < COS_TABLE_SIZE; i++)
436 		cos_table[i] = cosf(i * 2.0f * M_PI / COS_TABLE_SIZE);
437 
438 
439 	mono_descriptor->UniqueID = ID_MONO;
440 	mono_descriptor->Label = strdup("tap_pitch");
441 	mono_descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE;
442 	mono_descriptor->Name = strdup("TAP Pitch Shifter");
443 	mono_descriptor->Maker = strdup("Tom Szilagyi");
444 	mono_descriptor->Copyright = strdup("GPL");
445 	mono_descriptor->PortCount = PORTCOUNT_MONO;
446 
447 	if ((port_descriptors =
448 	     (LADSPA_PortDescriptor *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortDescriptor))) == NULL)
449 		exit(1);
450 
451 	mono_descriptor->PortDescriptors = (const LADSPA_PortDescriptor *)port_descriptors;
452 	port_descriptors[RATE] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
453 	port_descriptors[SEMITONE] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
454 	port_descriptors[DRYLEVEL] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
455 	port_descriptors[WETLEVEL] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
456 	port_descriptors[LATENCY] = LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL;
457 	port_descriptors[INPUT] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
458 	port_descriptors[OUTPUT] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
459 
460 	if ((port_names =
461 	     (char **)calloc(PORTCOUNT_MONO, sizeof(char *))) == NULL)
462 		exit(1);
463 
464 	mono_descriptor->PortNames = (const char **)port_names;
465 	port_names[SEMITONE] = strdup("Semitone Shift");
466 	port_names[RATE] = strdup("Rate Shift [%]");
467 	port_names[DRYLEVEL] = strdup("Dry Level [dB]");
468 	port_names[WETLEVEL] = strdup("Wet Level [dB]");
469 	port_names[LATENCY] = strdup("latency");
470 	port_names[INPUT] = strdup("Input");
471 	port_names[OUTPUT] = strdup("Output");
472 
473 	if ((port_range_hints =
474 	     ((LADSPA_PortRangeHint *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortRangeHint)))) == NULL)
475 		exit(1);
476 
477 	mono_descriptor->PortRangeHints	= (const LADSPA_PortRangeHint *)port_range_hints;
478 	port_range_hints[RATE].HintDescriptor =
479 		(LADSPA_HINT_BOUNDED_BELOW |
480 		 LADSPA_HINT_BOUNDED_ABOVE |
481 		 LADSPA_HINT_DEFAULT_0);
482 	port_range_hints[SEMITONE].HintDescriptor =
483 		(LADSPA_HINT_BOUNDED_BELOW |
484 		 LADSPA_HINT_BOUNDED_ABOVE |
485 		 LADSPA_HINT_DEFAULT_0);
486 	port_range_hints[DRYLEVEL].HintDescriptor =
487 		(LADSPA_HINT_BOUNDED_BELOW |
488 		 LADSPA_HINT_BOUNDED_ABOVE |
489 		 LADSPA_HINT_DEFAULT_MINIMUM);
490 	port_range_hints[WETLEVEL].HintDescriptor =
491 		(LADSPA_HINT_BOUNDED_BELOW |
492 		 LADSPA_HINT_BOUNDED_ABOVE |
493 		 LADSPA_HINT_DEFAULT_0);
494 	port_range_hints[LATENCY].HintDescriptor =
495 		(LADSPA_HINT_BOUNDED_BELOW |
496 		 LADSPA_HINT_BOUNDED_ABOVE |
497 		 LADSPA_HINT_DEFAULT_MAXIMUM);
498 	port_range_hints[RATE].LowerBound = -50.0f;
499 	port_range_hints[RATE].UpperBound = 100.0f;
500 	port_range_hints[SEMITONE].LowerBound = -12.0f;
501 	port_range_hints[SEMITONE].UpperBound = 12.0f;
502 	port_range_hints[DRYLEVEL].LowerBound = -90.0f;
503 	port_range_hints[DRYLEVEL].UpperBound = 20.0f;
504 	port_range_hints[WETLEVEL].LowerBound = -90.0f;
505 	port_range_hints[WETLEVEL].UpperBound = 20.0f;
506 	port_range_hints[LATENCY].LowerBound = 0;
507 	port_range_hints[LATENCY].UpperBound = PM_BUFLEN;
508 	port_range_hints[INPUT].HintDescriptor = 0;
509 	port_range_hints[OUTPUT].HintDescriptor = 0;
510 	mono_descriptor->instantiate = instantiate_Pitch;
511 	mono_descriptor->connect_port = connect_port_Pitch;
512 	mono_descriptor->activate = activate_Pitch;
513 	mono_descriptor->run = run_Pitch;
514 	mono_descriptor->run_adding = run_adding_Pitch;
515 	mono_descriptor->set_run_adding_gain = set_run_adding_gain_Pitch;
516 	mono_descriptor->deactivate = NULL;
517 	mono_descriptor->cleanup = cleanup_Pitch;
518 }
519 
520 
521 void
delete_descriptor(LADSPA_Descriptor * descriptor)522 delete_descriptor(LADSPA_Descriptor * descriptor) {
523 	unsigned long index;
524 	if (descriptor) {
525 		free((char *)descriptor->Label);
526 		free((char *)descriptor->Name);
527 		free((char *)descriptor->Maker);
528 		free((char *)descriptor->Copyright);
529 		free((LADSPA_PortDescriptor *)descriptor->PortDescriptors);
530 		for (index = 0; index < descriptor->PortCount; index++)
531 			free((char *)(descriptor->PortNames[index]));
532 		free((char **)descriptor->PortNames);
533 		free((LADSPA_PortRangeHint *)descriptor->PortRangeHints);
534 		free(descriptor);
535 	}
536 }
537 
538 
539 /* _fini() is called automatically when the library is unloaded. */
540 void
_fini()541 _fini() {
542 	delete_descriptor(mono_descriptor);
543 }
544 
545 
546 /* Return a descriptor of the requested plugin type. */
547 const LADSPA_Descriptor *
ladspa_descriptor(unsigned long Index)548 ladspa_descriptor(unsigned long Index) {
549 
550 	switch (Index) {
551 	case 0:
552 		return mono_descriptor;
553 	default:
554 		return NULL;
555 	}
556 }
557