1 #include <stdlib.h>
2 #include <string.h>
3 #ifndef WIN32
4 #include "config.h"
5 #endif
6 
7 #ifdef ENABLE_NLS
8 #include <libintl.h>
9 #endif
10 
11 #define         _ISOC9X_SOURCE  1
12 #define         _ISOC99_SOURCE  1
13 #define         __USE_ISOC99    1
14 #define         __USE_ISOC9X    1
15 
16 #include <math.h>
17 
18 #include "ladspa.h"
19 
20 #ifdef WIN32
21 #define _WINDOWS_DLL_EXPORT_ __declspec(dllexport)
22 int bIsFirstTime = 1;
23 static void __attribute__((constructor)) swh_init(); // forward declaration
24 #else
25 #define _WINDOWS_DLL_EXPORT_
26 #endif
27 
28 #line 10 "sc4m_1916.xml"
29 
30 #include "util/db.h"
31 #include "util/rms.h"
32 
33 #define A_TBL 256
34 
35 #define SC4M_RMS_PEAK                  0
36 #define SC4M_ATTACK                    1
37 #define SC4M_RELEASE                   2
38 #define SC4M_THRESHOLD                 3
39 #define SC4M_RATIO                     4
40 #define SC4M_KNEE                      5
41 #define SC4M_MAKEUP_GAIN               6
42 #define SC4M_AMPLITUDE                 7
43 #define SC4M_GAIN_RED                  8
44 #define SC4M_INPUT                     9
45 #define SC4M_OUTPUT                    10
46 
47 static LADSPA_Descriptor *sc4mDescriptor = NULL;
48 
49 typedef struct {
50 	LADSPA_Data *rms_peak;
51 	LADSPA_Data *attack;
52 	LADSPA_Data *release;
53 	LADSPA_Data *threshold;
54 	LADSPA_Data *ratio;
55 	LADSPA_Data *knee;
56 	LADSPA_Data *makeup_gain;
57 	LADSPA_Data *amplitude;
58 	LADSPA_Data *gain_red;
59 	LADSPA_Data *input;
60 	LADSPA_Data *output;
61 	float        amp;
62 	float *      as;
63 	unsigned int count;
64 	float        env;
65 	float        env_peak;
66 	float        env_rms;
67 	float        gain;
68 	float        gain_t;
69 	rms_env *    rms;
70 	float        sum;
71 	LADSPA_Data run_adding_gain;
72 } Sc4m;
73 
74 _WINDOWS_DLL_EXPORT_
ladspa_descriptor(unsigned long index)75 const LADSPA_Descriptor *ladspa_descriptor(unsigned long index) {
76 
77 #ifdef WIN32
78 	if (bIsFirstTime) {
79 		swh_init();
80 		bIsFirstTime = 0;
81 	}
82 #endif
83 	switch (index) {
84 	case 0:
85 		return sc4mDescriptor;
86 	default:
87 		return NULL;
88 	}
89 }
90 
cleanupSc4m(LADSPA_Handle instance)91 static void cleanupSc4m(LADSPA_Handle instance) {
92 #line 46 "sc4m_1916.xml"
93 	Sc4m *plugin_data = (Sc4m *)instance;
94 	rms_env_free(plugin_data->rms);
95 	free(plugin_data->as);
96 	free(instance);
97 }
98 
connectPortSc4m(LADSPA_Handle instance,unsigned long port,LADSPA_Data * data)99 static void connectPortSc4m(
100  LADSPA_Handle instance,
101  unsigned long port,
102  LADSPA_Data *data) {
103 	Sc4m *plugin;
104 
105 	plugin = (Sc4m *)instance;
106 	switch (port) {
107 	case SC4M_RMS_PEAK:
108 		plugin->rms_peak = data;
109 		break;
110 	case SC4M_ATTACK:
111 		plugin->attack = data;
112 		break;
113 	case SC4M_RELEASE:
114 		plugin->release = data;
115 		break;
116 	case SC4M_THRESHOLD:
117 		plugin->threshold = data;
118 		break;
119 	case SC4M_RATIO:
120 		plugin->ratio = data;
121 		break;
122 	case SC4M_KNEE:
123 		plugin->knee = data;
124 		break;
125 	case SC4M_MAKEUP_GAIN:
126 		plugin->makeup_gain = data;
127 		break;
128 	case SC4M_AMPLITUDE:
129 		plugin->amplitude = data;
130 		break;
131 	case SC4M_GAIN_RED:
132 		plugin->gain_red = data;
133 		break;
134 	case SC4M_INPUT:
135 		plugin->input = data;
136 		break;
137 	case SC4M_OUTPUT:
138 		plugin->output = data;
139 		break;
140 	}
141 }
142 
instantiateSc4m(const LADSPA_Descriptor * descriptor,unsigned long s_rate)143 static LADSPA_Handle instantiateSc4m(
144  const LADSPA_Descriptor *descriptor,
145  unsigned long s_rate) {
146 	Sc4m *plugin_data = (Sc4m *)calloc(1, sizeof(Sc4m));
147 	float amp;
148 	float *as = NULL;
149 	unsigned int count;
150 	float env;
151 	float env_peak;
152 	float env_rms;
153 	float gain;
154 	float gain_t;
155 	rms_env *rms = NULL;
156 	float sum;
157 
158 #line 23 "sc4m_1916.xml"
159 	unsigned int i;
160 	float sample_rate = (float)s_rate;
161 
162 	rms = rms_env_new();
163 	sum = 0.0f;
164 	amp = 0.0f;
165 	gain = 0.0f;
166 	gain_t = 0.0f;
167 	env = 0.0f;
168 	env_rms = 0.0f;
169 	env_peak = 0.0f;
170 	count = 0;
171 
172 	as = malloc(A_TBL * sizeof(float));
173 	as[0] = 1.0f;
174 	for (i=1; i<A_TBL; i++) {
175 	  as[i] = expf(-1.0f / (sample_rate * (float)i / (float)A_TBL));
176 	}
177 
178 	db_init();
179 
180 	plugin_data->amp = amp;
181 	plugin_data->as = as;
182 	plugin_data->count = count;
183 	plugin_data->env = env;
184 	plugin_data->env_peak = env_peak;
185 	plugin_data->env_rms = env_rms;
186 	plugin_data->gain = gain;
187 	plugin_data->gain_t = gain_t;
188 	plugin_data->rms = rms;
189 	plugin_data->sum = sum;
190 
191 	return (LADSPA_Handle)plugin_data;
192 }
193 
194 #undef buffer_write
195 #undef RUN_ADDING
196 #undef RUN_REPLACING
197 
198 #define buffer_write(b, v) (b = v)
199 #define RUN_ADDING    0
200 #define RUN_REPLACING 1
201 
runSc4m(LADSPA_Handle instance,unsigned long sample_count)202 static void runSc4m(LADSPA_Handle instance, unsigned long sample_count) {
203 	Sc4m *plugin_data = (Sc4m *)instance;
204 
205 	/* RMS/peak (float value) */
206 	const LADSPA_Data rms_peak = *(plugin_data->rms_peak);
207 
208 	/* Attack time (ms) (float value) */
209 	const LADSPA_Data attack = *(plugin_data->attack);
210 
211 	/* Release time (ms) (float value) */
212 	const LADSPA_Data release = *(plugin_data->release);
213 
214 	/* Threshold level (dB) (float value) */
215 	const LADSPA_Data threshold = *(plugin_data->threshold);
216 
217 	/* Ratio (1:n) (float value) */
218 	const LADSPA_Data ratio = *(plugin_data->ratio);
219 
220 	/* Knee radius (dB) (float value) */
221 	const LADSPA_Data knee = *(plugin_data->knee);
222 
223 	/* Makeup gain (dB) (float value) */
224 	const LADSPA_Data makeup_gain = *(plugin_data->makeup_gain);
225 
226 	/* Input (array of floats of length sample_count) */
227 	const LADSPA_Data * const input = plugin_data->input;
228 
229 	/* Output (array of floats of length sample_count) */
230 	LADSPA_Data * const output = plugin_data->output;
231 	float amp = plugin_data->amp;
232 	float * as = plugin_data->as;
233 	unsigned int count = plugin_data->count;
234 	float env = plugin_data->env;
235 	float env_peak = plugin_data->env_peak;
236 	float env_rms = plugin_data->env_rms;
237 	float gain = plugin_data->gain;
238 	float gain_t = plugin_data->gain_t;
239 	rms_env * rms = plugin_data->rms;
240 	float sum = plugin_data->sum;
241 
242 #line 51 "sc4m_1916.xml"
243 	unsigned long pos;
244 
245 	const float ga = attack < 2.0f ? 0.0f : as[f_round(attack * 0.001f * (float)(A_TBL-1))];
246 	const float gr = as[f_round(release * 0.001f * (float)(A_TBL-1))];
247 	const float rs = (ratio - 1.0f) / ratio;
248 	const float mug = db2lin(makeup_gain);
249 	const float knee_min = db2lin(threshold - knee);
250 	const float knee_max = db2lin(threshold + knee);
251 	const float ef_a = ga * 0.25f;
252 	const float ef_ai = 1.0f - ef_a;
253 
254 	for (pos = 0; pos < sample_count; pos++) {
255 	         const float lev_in = input[pos];
256 	  sum += lev_in * lev_in;
257 
258 	  if (amp > env_rms) {
259 	    env_rms = env_rms * ga + amp * (1.0f - ga);
260 	  } else {
261 	    env_rms = env_rms * gr + amp * (1.0f - gr);
262 	  }
263 	  round_to_zero(&env_rms);
264 	  if (lev_in > env_peak) {
265 	    env_peak = env_peak * ga + lev_in * (1.0f - ga);
266 	  } else {
267 	    env_peak = env_peak * gr + lev_in * (1.0f - gr);
268 	  }
269 	  round_to_zero(&env_peak);
270 	  if ((count++ & 3) == 3) {
271 	    amp = rms_env_process(rms, sum * 0.25f);
272 	    sum = 0.0f;
273 
274 	    env = LIN_INTERP(rms_peak, env_rms, env_peak);
275 
276 	    if (env <= knee_min) {
277 	      gain_t = 1.0f;
278 	    } else if (env < knee_max) {
279 	      const float x = -(threshold - knee - lin2db(env)) / knee;
280 	      gain_t = db2lin(-knee * rs * x * x * 0.25f);
281 	    } else {
282 	      gain_t = db2lin((threshold - lin2db(env)) * rs);
283 	    }
284 	  }
285 	  gain = gain * ef_a + gain_t * ef_ai;
286 	  buffer_write(output[pos], input[pos] * gain * mug);
287 	}
288 	plugin_data->sum = sum;
289 	plugin_data->amp = amp;
290 	plugin_data->gain = gain;
291 	plugin_data->gain_t = gain_t;
292 	plugin_data->env = env;
293 	plugin_data->env_rms = env_rms;
294 	plugin_data->env_peak = env_peak;
295 	plugin_data->count = count;
296 
297 	*(plugin_data->amplitude) = lin2db(env);
298 	*(plugin_data->gain_red) = lin2db(gain);
299 }
300 #undef buffer_write
301 #undef RUN_ADDING
302 #undef RUN_REPLACING
303 
304 #define buffer_write(b, v) (b += (v) * run_adding_gain)
305 #define RUN_ADDING    1
306 #define RUN_REPLACING 0
307 
setRunAddingGainSc4m(LADSPA_Handle instance,LADSPA_Data gain)308 static void setRunAddingGainSc4m(LADSPA_Handle instance, LADSPA_Data gain) {
309 	((Sc4m *)instance)->run_adding_gain = gain;
310 }
311 
runAddingSc4m(LADSPA_Handle instance,unsigned long sample_count)312 static void runAddingSc4m(LADSPA_Handle instance, unsigned long sample_count) {
313 	Sc4m *plugin_data = (Sc4m *)instance;
314 	LADSPA_Data run_adding_gain = plugin_data->run_adding_gain;
315 
316 	/* RMS/peak (float value) */
317 	const LADSPA_Data rms_peak = *(plugin_data->rms_peak);
318 
319 	/* Attack time (ms) (float value) */
320 	const LADSPA_Data attack = *(plugin_data->attack);
321 
322 	/* Release time (ms) (float value) */
323 	const LADSPA_Data release = *(plugin_data->release);
324 
325 	/* Threshold level (dB) (float value) */
326 	const LADSPA_Data threshold = *(plugin_data->threshold);
327 
328 	/* Ratio (1:n) (float value) */
329 	const LADSPA_Data ratio = *(plugin_data->ratio);
330 
331 	/* Knee radius (dB) (float value) */
332 	const LADSPA_Data knee = *(plugin_data->knee);
333 
334 	/* Makeup gain (dB) (float value) */
335 	const LADSPA_Data makeup_gain = *(plugin_data->makeup_gain);
336 
337 	/* Input (array of floats of length sample_count) */
338 	const LADSPA_Data * const input = plugin_data->input;
339 
340 	/* Output (array of floats of length sample_count) */
341 	LADSPA_Data * const output = plugin_data->output;
342 	float amp = plugin_data->amp;
343 	float * as = plugin_data->as;
344 	unsigned int count = plugin_data->count;
345 	float env = plugin_data->env;
346 	float env_peak = plugin_data->env_peak;
347 	float env_rms = plugin_data->env_rms;
348 	float gain = plugin_data->gain;
349 	float gain_t = plugin_data->gain_t;
350 	rms_env * rms = plugin_data->rms;
351 	float sum = plugin_data->sum;
352 
353 #line 51 "sc4m_1916.xml"
354 	unsigned long pos;
355 
356 	const float ga = attack < 2.0f ? 0.0f : as[f_round(attack * 0.001f * (float)(A_TBL-1))];
357 	const float gr = as[f_round(release * 0.001f * (float)(A_TBL-1))];
358 	const float rs = (ratio - 1.0f) / ratio;
359 	const float mug = db2lin(makeup_gain);
360 	const float knee_min = db2lin(threshold - knee);
361 	const float knee_max = db2lin(threshold + knee);
362 	const float ef_a = ga * 0.25f;
363 	const float ef_ai = 1.0f - ef_a;
364 
365 	for (pos = 0; pos < sample_count; pos++) {
366 	         const float lev_in = input[pos];
367 	  sum += lev_in * lev_in;
368 
369 	  if (amp > env_rms) {
370 	    env_rms = env_rms * ga + amp * (1.0f - ga);
371 	  } else {
372 	    env_rms = env_rms * gr + amp * (1.0f - gr);
373 	  }
374 	  round_to_zero(&env_rms);
375 	  if (lev_in > env_peak) {
376 	    env_peak = env_peak * ga + lev_in * (1.0f - ga);
377 	  } else {
378 	    env_peak = env_peak * gr + lev_in * (1.0f - gr);
379 	  }
380 	  round_to_zero(&env_peak);
381 	  if ((count++ & 3) == 3) {
382 	    amp = rms_env_process(rms, sum * 0.25f);
383 	    sum = 0.0f;
384 
385 	    env = LIN_INTERP(rms_peak, env_rms, env_peak);
386 
387 	    if (env <= knee_min) {
388 	      gain_t = 1.0f;
389 	    } else if (env < knee_max) {
390 	      const float x = -(threshold - knee - lin2db(env)) / knee;
391 	      gain_t = db2lin(-knee * rs * x * x * 0.25f);
392 	    } else {
393 	      gain_t = db2lin((threshold - lin2db(env)) * rs);
394 	    }
395 	  }
396 	  gain = gain * ef_a + gain_t * ef_ai;
397 	  buffer_write(output[pos], input[pos] * gain * mug);
398 	}
399 	plugin_data->sum = sum;
400 	plugin_data->amp = amp;
401 	plugin_data->gain = gain;
402 	plugin_data->gain_t = gain_t;
403 	plugin_data->env = env;
404 	plugin_data->env_rms = env_rms;
405 	plugin_data->env_peak = env_peak;
406 	plugin_data->count = count;
407 
408 	*(plugin_data->amplitude) = lin2db(env);
409 	*(plugin_data->gain_red) = lin2db(gain);
410 }
411 
swh_init()412 static void __attribute__((constructor)) swh_init() {
413 	char **port_names;
414 	LADSPA_PortDescriptor *port_descriptors;
415 	LADSPA_PortRangeHint *port_range_hints;
416 
417 #ifdef ENABLE_NLS
418 #define D_(s) dgettext(PACKAGE, s)
419 	bindtextdomain(PACKAGE, PACKAGE_LOCALE_DIR);
420 #else
421 #define D_(s) (s)
422 #endif
423 
424 
425 	sc4mDescriptor =
426 	 (LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor));
427 
428 	if (sc4mDescriptor) {
429 		sc4mDescriptor->UniqueID = 1916;
430 		sc4mDescriptor->Label = "sc4m";
431 		sc4mDescriptor->Properties =
432 		 LADSPA_PROPERTY_HARD_RT_CAPABLE;
433 		sc4mDescriptor->Name =
434 		 D_("SC4 mono");
435 		sc4mDescriptor->Maker =
436 		 "Steve Harris <steve@plugin.org.uk>";
437 		sc4mDescriptor->Copyright =
438 		 "GPL";
439 		sc4mDescriptor->PortCount = 11;
440 
441 		port_descriptors = (LADSPA_PortDescriptor *)calloc(11,
442 		 sizeof(LADSPA_PortDescriptor));
443 		sc4mDescriptor->PortDescriptors =
444 		 (const LADSPA_PortDescriptor *)port_descriptors;
445 
446 		port_range_hints = (LADSPA_PortRangeHint *)calloc(11,
447 		 sizeof(LADSPA_PortRangeHint));
448 		sc4mDescriptor->PortRangeHints =
449 		 (const LADSPA_PortRangeHint *)port_range_hints;
450 
451 		port_names = (char **)calloc(11, sizeof(char*));
452 		sc4mDescriptor->PortNames =
453 		 (const char **)port_names;
454 
455 		/* Parameters for RMS/peak */
456 		port_descriptors[SC4M_RMS_PEAK] =
457 		 LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
458 		port_names[SC4M_RMS_PEAK] =
459 		 D_("RMS/peak");
460 		port_range_hints[SC4M_RMS_PEAK].HintDescriptor =
461 		 LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MINIMUM;
462 		port_range_hints[SC4M_RMS_PEAK].LowerBound = 0;
463 		port_range_hints[SC4M_RMS_PEAK].UpperBound = 1;
464 
465 		/* Parameters for Attack time (ms) */
466 		port_descriptors[SC4M_ATTACK] =
467 		 LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
468 		port_names[SC4M_ATTACK] =
469 		 D_("Attack time (ms)");
470 		port_range_hints[SC4M_ATTACK].HintDescriptor =
471 		 LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_LOW;
472 		port_range_hints[SC4M_ATTACK].LowerBound = 1.5;
473 		port_range_hints[SC4M_ATTACK].UpperBound = 400;
474 
475 		/* Parameters for Release time (ms) */
476 		port_descriptors[SC4M_RELEASE] =
477 		 LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
478 		port_names[SC4M_RELEASE] =
479 		 D_("Release time (ms)");
480 		port_range_hints[SC4M_RELEASE].HintDescriptor =
481 		 LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MIDDLE;
482 		port_range_hints[SC4M_RELEASE].LowerBound = 2;
483 		port_range_hints[SC4M_RELEASE].UpperBound = 800;
484 
485 		/* Parameters for Threshold level (dB) */
486 		port_descriptors[SC4M_THRESHOLD] =
487 		 LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
488 		port_names[SC4M_THRESHOLD] =
489 		 D_("Threshold level (dB)");
490 		port_range_hints[SC4M_THRESHOLD].HintDescriptor =
491 		 LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MAXIMUM;
492 		port_range_hints[SC4M_THRESHOLD].LowerBound = -30;
493 		port_range_hints[SC4M_THRESHOLD].UpperBound = 0;
494 
495 		/* Parameters for Ratio (1:n) */
496 		port_descriptors[SC4M_RATIO] =
497 		 LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
498 		port_names[SC4M_RATIO] =
499 		 D_("Ratio (1:n)");
500 		port_range_hints[SC4M_RATIO].HintDescriptor =
501 		 LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_1;
502 		port_range_hints[SC4M_RATIO].LowerBound = 1;
503 		port_range_hints[SC4M_RATIO].UpperBound = 20;
504 
505 		/* Parameters for Knee radius (dB) */
506 		port_descriptors[SC4M_KNEE] =
507 		 LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
508 		port_names[SC4M_KNEE] =
509 		 D_("Knee radius (dB)");
510 		port_range_hints[SC4M_KNEE].HintDescriptor =
511 		 LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_LOW;
512 		port_range_hints[SC4M_KNEE].LowerBound = 1;
513 		port_range_hints[SC4M_KNEE].UpperBound = 10;
514 
515 		/* Parameters for Makeup gain (dB) */
516 		port_descriptors[SC4M_MAKEUP_GAIN] =
517 		 LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
518 		port_names[SC4M_MAKEUP_GAIN] =
519 		 D_("Makeup gain (dB)");
520 		port_range_hints[SC4M_MAKEUP_GAIN].HintDescriptor =
521 		 LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0;
522 		port_range_hints[SC4M_MAKEUP_GAIN].LowerBound = 0;
523 		port_range_hints[SC4M_MAKEUP_GAIN].UpperBound = +24;
524 
525 		/* Parameters for Amplitude (dB) */
526 		port_descriptors[SC4M_AMPLITUDE] =
527 		 LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL;
528 		port_names[SC4M_AMPLITUDE] =
529 		 D_("Amplitude (dB)");
530 		port_range_hints[SC4M_AMPLITUDE].HintDescriptor =
531 		 LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE;
532 		port_range_hints[SC4M_AMPLITUDE].LowerBound = -40;
533 		port_range_hints[SC4M_AMPLITUDE].UpperBound = +12;
534 
535 		/* Parameters for Gain reduction (dB) */
536 		port_descriptors[SC4M_GAIN_RED] =
537 		 LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL;
538 		port_names[SC4M_GAIN_RED] =
539 		 D_("Gain reduction (dB)");
540 		port_range_hints[SC4M_GAIN_RED].HintDescriptor =
541 		 LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE;
542 		port_range_hints[SC4M_GAIN_RED].LowerBound = -24;
543 		port_range_hints[SC4M_GAIN_RED].UpperBound = 0;
544 
545 		/* Parameters for Input */
546 		port_descriptors[SC4M_INPUT] =
547 		 LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
548 		port_names[SC4M_INPUT] =
549 		 D_("Input");
550 		port_range_hints[SC4M_INPUT].HintDescriptor = 0;
551 
552 		/* Parameters for Output */
553 		port_descriptors[SC4M_OUTPUT] =
554 		 LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
555 		port_names[SC4M_OUTPUT] =
556 		 D_("Output");
557 		port_range_hints[SC4M_OUTPUT].HintDescriptor = 0;
558 
559 		sc4mDescriptor->activate = NULL;
560 		sc4mDescriptor->cleanup = cleanupSc4m;
561 		sc4mDescriptor->connect_port = connectPortSc4m;
562 		sc4mDescriptor->deactivate = NULL;
563 		sc4mDescriptor->instantiate = instantiateSc4m;
564 		sc4mDescriptor->run = runSc4m;
565 		sc4mDescriptor->run_adding = runAddingSc4m;
566 		sc4mDescriptor->set_run_adding_gain = setRunAddingGainSc4m;
567 	}
568 }
569 
swh_fini()570 static void __attribute__((destructor)) swh_fini() {
571 	if (sc4mDescriptor) {
572 		free((LADSPA_PortDescriptor *)sc4mDescriptor->PortDescriptors);
573 		free((char **)sc4mDescriptor->PortNames);
574 		free((LADSPA_PortRangeHint *)sc4mDescriptor->PortRangeHints);
575 		free(sc4mDescriptor);
576 	}
577 	sc4mDescriptor = NULL;
578 
579 }
580