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 "fast_lookahead_limiter_1913.xml"
29 
30 #include "ladspa-util.h"
31 
32 //#define DEBUG
33 
34 #define NUM_CHUNKS 16
35 #define BUFFER_TIME 0.0053
36 
37 #ifdef DEBUG
38   #include "stdio.h"
39 #endif
40 
41 #define FASTLOOKAHEADLIMITER_INGAIN    0
42 #define FASTLOOKAHEADLIMITER_LIMIT     1
43 #define FASTLOOKAHEADLIMITER_RELEASE   2
44 #define FASTLOOKAHEADLIMITER_ATTENUATION 3
45 #define FASTLOOKAHEADLIMITER_IN_1      4
46 #define FASTLOOKAHEADLIMITER_IN_2      5
47 #define FASTLOOKAHEADLIMITER_OUT_1     6
48 #define FASTLOOKAHEADLIMITER_OUT_2     7
49 #define FASTLOOKAHEADLIMITER_LATENCY   8
50 
51 static LADSPA_Descriptor *fastLookaheadLimiterDescriptor = NULL;
52 
53 typedef struct {
54 	LADSPA_Data *ingain;
55 	LADSPA_Data *limit;
56 	LADSPA_Data *release;
57 	LADSPA_Data *attenuation;
58 	LADSPA_Data *in_1;
59 	LADSPA_Data *in_2;
60 	LADSPA_Data *out_1;
61 	LADSPA_Data *out_2;
62 	LADSPA_Data *latency;
63 	float        atten;
64 	float        atten_lp;
65 	LADSPA_Data *buffer;
66 	unsigned int buffer_len;
67 	unsigned int buffer_pos;
68 	unsigned int chunk_num;
69 	unsigned int chunk_pos;
70 	unsigned int chunk_size;
71 	float *      chunks;
72 	unsigned int delay;
73 	float        delta;
74 	unsigned int fs;
75 	float        peak;
76 	LADSPA_Data run_adding_gain;
77 } FastLookaheadLimiter;
78 
79 _WINDOWS_DLL_EXPORT_
ladspa_descriptor(unsigned long index)80 const LADSPA_Descriptor *ladspa_descriptor(unsigned long index) {
81 
82 #ifdef WIN32
83 	if (bIsFirstTime) {
84 		swh_init();
85 		bIsFirstTime = 0;
86 	}
87 #endif
88 	switch (index) {
89 	case 0:
90 		return fastLookaheadLimiterDescriptor;
91 	default:
92 		return NULL;
93 	}
94 }
95 
activateFastLookaheadLimiter(LADSPA_Handle instance)96 static void activateFastLookaheadLimiter(LADSPA_Handle instance) {
97 	FastLookaheadLimiter *plugin_data = (FastLookaheadLimiter *)instance;
98 	float atten = plugin_data->atten;
99 	float atten_lp = plugin_data->atten_lp;
100 	LADSPA_Data *buffer = plugin_data->buffer;
101 	unsigned int buffer_len = plugin_data->buffer_len;
102 	unsigned int buffer_pos = plugin_data->buffer_pos;
103 	unsigned int chunk_num = plugin_data->chunk_num;
104 	unsigned int chunk_pos = plugin_data->chunk_pos;
105 	unsigned int chunk_size = plugin_data->chunk_size;
106 	float *chunks = plugin_data->chunks;
107 	unsigned int delay = plugin_data->delay;
108 	float delta = plugin_data->delta;
109 	unsigned int fs = plugin_data->fs;
110 	float peak = plugin_data->peak;
111 #line 56 "fast_lookahead_limiter_1913.xml"
112 	memset(buffer, 0, NUM_CHUNKS * sizeof(float));
113 
114 	chunk_pos = 0;
115 	chunk_num = 0;
116 	peak = 0.0f;
117 	atten = 1.0f;
118 	atten_lp = 1.0f;
119 	delta = 0.0f;
120 	plugin_data->atten = atten;
121 	plugin_data->atten_lp = atten_lp;
122 	plugin_data->buffer = buffer;
123 	plugin_data->buffer_len = buffer_len;
124 	plugin_data->buffer_pos = buffer_pos;
125 	plugin_data->chunk_num = chunk_num;
126 	plugin_data->chunk_pos = chunk_pos;
127 	plugin_data->chunk_size = chunk_size;
128 	plugin_data->chunks = chunks;
129 	plugin_data->delay = delay;
130 	plugin_data->delta = delta;
131 	plugin_data->fs = fs;
132 	plugin_data->peak = peak;
133 
134 }
135 
cleanupFastLookaheadLimiter(LADSPA_Handle instance)136 static void cleanupFastLookaheadLimiter(LADSPA_Handle instance) {
137 #line 188 "fast_lookahead_limiter_1913.xml"
138 	FastLookaheadLimiter *plugin_data = (FastLookaheadLimiter *)instance;
139 	free(plugin_data->buffer);
140 	free(plugin_data->chunks);
141 	free(instance);
142 }
143 
connectPortFastLookaheadLimiter(LADSPA_Handle instance,unsigned long port,LADSPA_Data * data)144 static void connectPortFastLookaheadLimiter(
145  LADSPA_Handle instance,
146  unsigned long port,
147  LADSPA_Data *data) {
148 	FastLookaheadLimiter *plugin;
149 
150 	plugin = (FastLookaheadLimiter *)instance;
151 	switch (port) {
152 	case FASTLOOKAHEADLIMITER_INGAIN:
153 		plugin->ingain = data;
154 		break;
155 	case FASTLOOKAHEADLIMITER_LIMIT:
156 		plugin->limit = data;
157 		break;
158 	case FASTLOOKAHEADLIMITER_RELEASE:
159 		plugin->release = data;
160 		break;
161 	case FASTLOOKAHEADLIMITER_ATTENUATION:
162 		plugin->attenuation = data;
163 		break;
164 	case FASTLOOKAHEADLIMITER_IN_1:
165 		plugin->in_1 = data;
166 		break;
167 	case FASTLOOKAHEADLIMITER_IN_2:
168 		plugin->in_2 = data;
169 		break;
170 	case FASTLOOKAHEADLIMITER_OUT_1:
171 		plugin->out_1 = data;
172 		break;
173 	case FASTLOOKAHEADLIMITER_OUT_2:
174 		plugin->out_2 = data;
175 		break;
176 	case FASTLOOKAHEADLIMITER_LATENCY:
177 		plugin->latency = data;
178 		break;
179 	}
180 }
181 
instantiateFastLookaheadLimiter(const LADSPA_Descriptor * descriptor,unsigned long s_rate)182 static LADSPA_Handle instantiateFastLookaheadLimiter(
183  const LADSPA_Descriptor *descriptor,
184  unsigned long s_rate) {
185 	FastLookaheadLimiter *plugin_data = (FastLookaheadLimiter *)calloc(1, sizeof(FastLookaheadLimiter));
186 	float atten;
187 	float atten_lp;
188 	LADSPA_Data *buffer = NULL;
189 	unsigned int buffer_len;
190 	unsigned int buffer_pos;
191 	unsigned int chunk_num;
192 	unsigned int chunk_pos;
193 	unsigned int chunk_size;
194 	float *chunks = NULL;
195 	unsigned int delay;
196 	float delta;
197 	unsigned int fs;
198 	float peak;
199 
200 #line 31 "fast_lookahead_limiter_1913.xml"
201 	fs = s_rate;
202 	buffer_len = 128;
203 	buffer_pos = 0;
204 
205 	/* Find size for power-of-two interleaved delay buffer */
206 	while(buffer_len < fs * BUFFER_TIME * 2) {
207 	  buffer_len *= 2;
208 	}
209 	buffer = calloc(buffer_len, sizeof(float));
210 	delay = (int)(0.005 * fs);
211 
212 	chunk_pos = 0;
213 	chunk_num = 0;
214 
215 	/* find a chunk size (in smaples) thats roughly 0.5ms */
216 	chunk_size = s_rate / 2000;
217 	chunks = calloc(NUM_CHUNKS, sizeof(float));
218 
219 	peak = 0.0f;
220 	atten = 1.0f;
221 	atten_lp = 1.0f;
222 	delta = 0.0f;
223 
224 	plugin_data->atten = atten;
225 	plugin_data->atten_lp = atten_lp;
226 	plugin_data->buffer = buffer;
227 	plugin_data->buffer_len = buffer_len;
228 	plugin_data->buffer_pos = buffer_pos;
229 	plugin_data->chunk_num = chunk_num;
230 	plugin_data->chunk_pos = chunk_pos;
231 	plugin_data->chunk_size = chunk_size;
232 	plugin_data->chunks = chunks;
233 	plugin_data->delay = delay;
234 	plugin_data->delta = delta;
235 	plugin_data->fs = fs;
236 	plugin_data->peak = peak;
237 
238 	return (LADSPA_Handle)plugin_data;
239 }
240 
241 #undef buffer_write
242 #undef RUN_ADDING
243 #undef RUN_REPLACING
244 
245 #define buffer_write(b, v) (b = v)
246 #define RUN_ADDING    0
247 #define RUN_REPLACING 1
248 
runFastLookaheadLimiter(LADSPA_Handle instance,unsigned long sample_count)249 static void runFastLookaheadLimiter(LADSPA_Handle instance, unsigned long sample_count) {
250 	FastLookaheadLimiter *plugin_data = (FastLookaheadLimiter *)instance;
251 
252 	/* Input gain (dB) (float value) */
253 	const LADSPA_Data ingain = *(plugin_data->ingain);
254 
255 	/* Limit (dB) (float value) */
256 	const LADSPA_Data limit = *(plugin_data->limit);
257 
258 	/* Release time (s) (float value) */
259 	const LADSPA_Data release = *(plugin_data->release);
260 
261 	/* Input 1 (array of floats of length sample_count) */
262 	const LADSPA_Data * const in_1 = plugin_data->in_1;
263 
264 	/* Input 2 (array of floats of length sample_count) */
265 	const LADSPA_Data * const in_2 = plugin_data->in_2;
266 
267 	/* Output 1 (array of floats of length sample_count) */
268 	LADSPA_Data * const out_1 = plugin_data->out_1;
269 
270 	/* Output 2 (array of floats of length sample_count) */
271 	LADSPA_Data * const out_2 = plugin_data->out_2;
272 	float atten = plugin_data->atten;
273 	float atten_lp = plugin_data->atten_lp;
274 	LADSPA_Data * buffer = plugin_data->buffer;
275 	unsigned int buffer_len = plugin_data->buffer_len;
276 	unsigned int buffer_pos = plugin_data->buffer_pos;
277 	unsigned int chunk_num = plugin_data->chunk_num;
278 	unsigned int chunk_pos = plugin_data->chunk_pos;
279 	unsigned int chunk_size = plugin_data->chunk_size;
280 	float * chunks = plugin_data->chunks;
281 	unsigned int delay = plugin_data->delay;
282 	float delta = plugin_data->delta;
283 	unsigned int fs = plugin_data->fs;
284 	float peak = plugin_data->peak;
285 
286 #line 67 "fast_lookahead_limiter_1913.xml"
287 	unsigned long pos;
288 	const float max = DB_CO(limit);
289 	const float trim = DB_CO(ingain);
290 	float sig;
291 	unsigned int i;
292 
293 	#ifdef DEBUG
294 	float clip = 0.0, clipp = 0.0;
295 	int clipc = 0;
296 	#endif
297 
298 	for (pos = 0; pos < sample_count; pos++) {
299 	  if (chunk_pos++ == chunk_size) {
300 	    /* we've got a full chunk */
301 
302 	    delta = (1.0f - atten) / (fs * release);
303 	    round_to_zero(&delta);
304 	    for (i=0; i<10; i++) {
305 	      const int p = (chunk_num - 9 + i) & (NUM_CHUNKS - 1);
306 	      const float this_delta = (max / chunks[p] - atten) /
307 	                                ((float)(i+1) * fs * 0.0005f + 1.0f);
308 
309 	      if (this_delta < delta) {
310 	        delta = this_delta;
311 	      }
312 	    }
313 
314 	    chunks[chunk_num++ & (NUM_CHUNKS - 1)] = peak;
315 	    peak = 0.0f;
316 	    chunk_pos = 0;
317 	  }
318 
319 	  buffer[(buffer_pos * 2) & (buffer_len - 1)] =     in_1[pos] * trim
320 	                                                  + 1.0e-30;
321 	  buffer[(buffer_pos * 2 + 1) & (buffer_len - 1)] = in_2[pos] * trim
322 	                                                  + 1.0e-30;
323 
324 	  sig = fabs(in_1[pos]) > fabs(in_2[pos]) ? fabs(in_1[pos]) :
325 	          fabs(in_2[pos]);
326 	  sig += 1.0e-30;
327 	  if (sig * trim > peak) {
328 	    peak = sig * trim;
329 	  }
330 	  //round_to_zero(&peak);
331 	  //round_to_zero(&sig);
332 
333 	  atten += delta;
334 	  atten_lp = atten * 0.1f + atten_lp * 0.9f;
335 	  //round_to_zero(&atten_lp);
336 	  if (delta > 0.0f && atten > 1.0f) {
337 	    atten = 1.0f;
338 	    delta = 0.0f;
339 	  }
340 
341 	  buffer_write(out_1[pos], buffer[(buffer_pos * 2 - delay * 2) &
342 	                                  (buffer_len - 1)] * atten_lp);
343 	  buffer_write(out_2[pos], buffer[(buffer_pos * 2 - delay * 2 + 1) &
344 	                                  (buffer_len - 1)] * atten_lp);
345 	  round_to_zero(&out_1[pos]);
346 	  round_to_zero(&out_2[pos]);
347 
348 	  if (out_1[pos] < -max) {
349 	    #ifdef DEBUG
350 	    clip += 20.0*log10(out_1[pos] / -max);
351 	    clipc++;
352 	    if (fabs(out_1[pos] - max) > clipp) {
353 	      clipp = fabs(out_1[pos] / -max);
354 	    }
355 	    #endif
356 	    buffer_write(out_1[pos], -max);
357 	  } else if (out_1[pos] > max) {
358 	    #ifdef DEBUG
359 	    clip += 20.0*log10(out_1[pos] / max);
360 	    clipc++;
361 	    if (fabs(out_1[pos] - max) > clipp) {
362 	      clipp = fabs(out_1[pos] / max);
363 	    }
364 	    #endif
365 	    buffer_write(out_1[pos], max);
366 	  }
367 	  if (out_2[pos] < -max) {
368 	    #ifdef DEBUG
369 	    clip += 20.0*log10(out_2[pos] / -max);
370 	    clipc++;
371 	    if (fabs(out_2[pos] - max) > clipp) {
372 	      clipp = fabs(out_2[pos] / -max);
373 	    }
374 	    #endif
375 	    buffer_write(out_2[pos], -max);
376 	  } else if (out_2[pos] > max) {
377 	    #ifdef DEBUG
378 	    clip += 20.0*log10(out_2[pos] / max);
379 	    clipc++;
380 	    if (fabs(out_2[pos] - max) > clipp) {
381 	      clipp = fabs(out_2[pos] / max);
382 	    }
383 	    #endif
384 	    buffer_write(out_2[pos], max);
385 	  }
386 
387 	  buffer_pos++;
388 	}
389 
390 	#ifdef DEBUG
391 	if (clipc > 0) {
392 	  printf("%d overs: %fdB avg, %fdB peak\n", clipc, clip/(float)clipc, 20.0*log10(clipp));
393 	}
394 	#endif
395 
396 	plugin_data->buffer_pos = buffer_pos;
397 	plugin_data->peak = peak;
398 	plugin_data->atten = atten;
399 	plugin_data->atten_lp = atten_lp;
400 	plugin_data->chunk_pos = chunk_pos;
401 	plugin_data->chunk_num = chunk_num;
402 
403 	*(plugin_data->attenuation) = -CO_DB(atten);
404 	*(plugin_data->latency) = delay;
405 }
406 #undef buffer_write
407 #undef RUN_ADDING
408 #undef RUN_REPLACING
409 
410 #define buffer_write(b, v) (b += (v) * run_adding_gain)
411 #define RUN_ADDING    1
412 #define RUN_REPLACING 0
413 
setRunAddingGainFastLookaheadLimiter(LADSPA_Handle instance,LADSPA_Data gain)414 static void setRunAddingGainFastLookaheadLimiter(LADSPA_Handle instance, LADSPA_Data gain) {
415 	((FastLookaheadLimiter *)instance)->run_adding_gain = gain;
416 }
417 
runAddingFastLookaheadLimiter(LADSPA_Handle instance,unsigned long sample_count)418 static void runAddingFastLookaheadLimiter(LADSPA_Handle instance, unsigned long sample_count) {
419 	FastLookaheadLimiter *plugin_data = (FastLookaheadLimiter *)instance;
420 	LADSPA_Data run_adding_gain = plugin_data->run_adding_gain;
421 
422 	/* Input gain (dB) (float value) */
423 	const LADSPA_Data ingain = *(plugin_data->ingain);
424 
425 	/* Limit (dB) (float value) */
426 	const LADSPA_Data limit = *(plugin_data->limit);
427 
428 	/* Release time (s) (float value) */
429 	const LADSPA_Data release = *(plugin_data->release);
430 
431 	/* Input 1 (array of floats of length sample_count) */
432 	const LADSPA_Data * const in_1 = plugin_data->in_1;
433 
434 	/* Input 2 (array of floats of length sample_count) */
435 	const LADSPA_Data * const in_2 = plugin_data->in_2;
436 
437 	/* Output 1 (array of floats of length sample_count) */
438 	LADSPA_Data * const out_1 = plugin_data->out_1;
439 
440 	/* Output 2 (array of floats of length sample_count) */
441 	LADSPA_Data * const out_2 = plugin_data->out_2;
442 	float atten = plugin_data->atten;
443 	float atten_lp = plugin_data->atten_lp;
444 	LADSPA_Data * buffer = plugin_data->buffer;
445 	unsigned int buffer_len = plugin_data->buffer_len;
446 	unsigned int buffer_pos = plugin_data->buffer_pos;
447 	unsigned int chunk_num = plugin_data->chunk_num;
448 	unsigned int chunk_pos = plugin_data->chunk_pos;
449 	unsigned int chunk_size = plugin_data->chunk_size;
450 	float * chunks = plugin_data->chunks;
451 	unsigned int delay = plugin_data->delay;
452 	float delta = plugin_data->delta;
453 	unsigned int fs = plugin_data->fs;
454 	float peak = plugin_data->peak;
455 
456 #line 67 "fast_lookahead_limiter_1913.xml"
457 	unsigned long pos;
458 	const float max = DB_CO(limit);
459 	const float trim = DB_CO(ingain);
460 	float sig;
461 	unsigned int i;
462 
463 	#ifdef DEBUG
464 	float clip = 0.0, clipp = 0.0;
465 	int clipc = 0;
466 	#endif
467 
468 	for (pos = 0; pos < sample_count; pos++) {
469 	  if (chunk_pos++ == chunk_size) {
470 	    /* we've got a full chunk */
471 
472 	    delta = (1.0f - atten) / (fs * release);
473 	    round_to_zero(&delta);
474 	    for (i=0; i<10; i++) {
475 	      const int p = (chunk_num - 9 + i) & (NUM_CHUNKS - 1);
476 	      const float this_delta = (max / chunks[p] - atten) /
477 	                                ((float)(i+1) * fs * 0.0005f + 1.0f);
478 
479 	      if (this_delta < delta) {
480 	        delta = this_delta;
481 	      }
482 	    }
483 
484 	    chunks[chunk_num++ & (NUM_CHUNKS - 1)] = peak;
485 	    peak = 0.0f;
486 	    chunk_pos = 0;
487 	  }
488 
489 	  buffer[(buffer_pos * 2) & (buffer_len - 1)] =     in_1[pos] * trim
490 	                                                  + 1.0e-30;
491 	  buffer[(buffer_pos * 2 + 1) & (buffer_len - 1)] = in_2[pos] * trim
492 	                                                  + 1.0e-30;
493 
494 	  sig = fabs(in_1[pos]) > fabs(in_2[pos]) ? fabs(in_1[pos]) :
495 	          fabs(in_2[pos]);
496 	  sig += 1.0e-30;
497 	  if (sig * trim > peak) {
498 	    peak = sig * trim;
499 	  }
500 	  //round_to_zero(&peak);
501 	  //round_to_zero(&sig);
502 
503 	  atten += delta;
504 	  atten_lp = atten * 0.1f + atten_lp * 0.9f;
505 	  //round_to_zero(&atten_lp);
506 	  if (delta > 0.0f && atten > 1.0f) {
507 	    atten = 1.0f;
508 	    delta = 0.0f;
509 	  }
510 
511 	  buffer_write(out_1[pos], buffer[(buffer_pos * 2 - delay * 2) &
512 	                                  (buffer_len - 1)] * atten_lp);
513 	  buffer_write(out_2[pos], buffer[(buffer_pos * 2 - delay * 2 + 1) &
514 	                                  (buffer_len - 1)] * atten_lp);
515 	  round_to_zero(&out_1[pos]);
516 	  round_to_zero(&out_2[pos]);
517 
518 	  if (out_1[pos] < -max) {
519 	    #ifdef DEBUG
520 	    clip += 20.0*log10(out_1[pos] / -max);
521 	    clipc++;
522 	    if (fabs(out_1[pos] - max) > clipp) {
523 	      clipp = fabs(out_1[pos] / -max);
524 	    }
525 	    #endif
526 	    buffer_write(out_1[pos], -max);
527 	  } else if (out_1[pos] > max) {
528 	    #ifdef DEBUG
529 	    clip += 20.0*log10(out_1[pos] / max);
530 	    clipc++;
531 	    if (fabs(out_1[pos] - max) > clipp) {
532 	      clipp = fabs(out_1[pos] / max);
533 	    }
534 	    #endif
535 	    buffer_write(out_1[pos], max);
536 	  }
537 	  if (out_2[pos] < -max) {
538 	    #ifdef DEBUG
539 	    clip += 20.0*log10(out_2[pos] / -max);
540 	    clipc++;
541 	    if (fabs(out_2[pos] - max) > clipp) {
542 	      clipp = fabs(out_2[pos] / -max);
543 	    }
544 	    #endif
545 	    buffer_write(out_2[pos], -max);
546 	  } else if (out_2[pos] > max) {
547 	    #ifdef DEBUG
548 	    clip += 20.0*log10(out_2[pos] / max);
549 	    clipc++;
550 	    if (fabs(out_2[pos] - max) > clipp) {
551 	      clipp = fabs(out_2[pos] / max);
552 	    }
553 	    #endif
554 	    buffer_write(out_2[pos], max);
555 	  }
556 
557 	  buffer_pos++;
558 	}
559 
560 	#ifdef DEBUG
561 	if (clipc > 0) {
562 	  printf("%d overs: %fdB avg, %fdB peak\n", clipc, clip/(float)clipc, 20.0*log10(clipp));
563 	}
564 	#endif
565 
566 	plugin_data->buffer_pos = buffer_pos;
567 	plugin_data->peak = peak;
568 	plugin_data->atten = atten;
569 	plugin_data->atten_lp = atten_lp;
570 	plugin_data->chunk_pos = chunk_pos;
571 	plugin_data->chunk_num = chunk_num;
572 
573 	*(plugin_data->attenuation) = -CO_DB(atten);
574 	*(plugin_data->latency) = delay;
575 }
576 
swh_init()577 static void __attribute__((constructor)) swh_init() {
578 	char **port_names;
579 	LADSPA_PortDescriptor *port_descriptors;
580 	LADSPA_PortRangeHint *port_range_hints;
581 
582 #ifdef ENABLE_NLS
583 #define D_(s) dgettext(PACKAGE, s)
584 	bindtextdomain(PACKAGE, PACKAGE_LOCALE_DIR);
585 #else
586 #define D_(s) (s)
587 #endif
588 
589 
590 	fastLookaheadLimiterDescriptor =
591 	 (LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor));
592 
593 	if (fastLookaheadLimiterDescriptor) {
594 		fastLookaheadLimiterDescriptor->UniqueID = 1913;
595 		fastLookaheadLimiterDescriptor->Label = "fastLookaheadLimiter";
596 		fastLookaheadLimiterDescriptor->Properties =
597 		 LADSPA_PROPERTY_HARD_RT_CAPABLE;
598 		fastLookaheadLimiterDescriptor->Name =
599 		 D_("Fast Lookahead limiter");
600 		fastLookaheadLimiterDescriptor->Maker =
601 		 "Steve Harris <steve@plugin.org.uk>";
602 		fastLookaheadLimiterDescriptor->Copyright =
603 		 "GPL";
604 		fastLookaheadLimiterDescriptor->PortCount = 9;
605 
606 		port_descriptors = (LADSPA_PortDescriptor *)calloc(9,
607 		 sizeof(LADSPA_PortDescriptor));
608 		fastLookaheadLimiterDescriptor->PortDescriptors =
609 		 (const LADSPA_PortDescriptor *)port_descriptors;
610 
611 		port_range_hints = (LADSPA_PortRangeHint *)calloc(9,
612 		 sizeof(LADSPA_PortRangeHint));
613 		fastLookaheadLimiterDescriptor->PortRangeHints =
614 		 (const LADSPA_PortRangeHint *)port_range_hints;
615 
616 		port_names = (char **)calloc(9, sizeof(char*));
617 		fastLookaheadLimiterDescriptor->PortNames =
618 		 (const char **)port_names;
619 
620 		/* Parameters for Input gain (dB) */
621 		port_descriptors[FASTLOOKAHEADLIMITER_INGAIN] =
622 		 LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
623 		port_names[FASTLOOKAHEADLIMITER_INGAIN] =
624 		 D_("Input gain (dB)");
625 		port_range_hints[FASTLOOKAHEADLIMITER_INGAIN].HintDescriptor =
626 		 LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0;
627 		port_range_hints[FASTLOOKAHEADLIMITER_INGAIN].LowerBound = -20;
628 		port_range_hints[FASTLOOKAHEADLIMITER_INGAIN].UpperBound = 20;
629 
630 		/* Parameters for Limit (dB) */
631 		port_descriptors[FASTLOOKAHEADLIMITER_LIMIT] =
632 		 LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
633 		port_names[FASTLOOKAHEADLIMITER_LIMIT] =
634 		 D_("Limit (dB)");
635 		port_range_hints[FASTLOOKAHEADLIMITER_LIMIT].HintDescriptor =
636 		 LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0;
637 		port_range_hints[FASTLOOKAHEADLIMITER_LIMIT].LowerBound = -20;
638 		port_range_hints[FASTLOOKAHEADLIMITER_LIMIT].UpperBound = 0;
639 
640 		/* Parameters for Release time (s) */
641 		port_descriptors[FASTLOOKAHEADLIMITER_RELEASE] =
642 		 LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
643 		port_names[FASTLOOKAHEADLIMITER_RELEASE] =
644 		 D_("Release time (s)");
645 		port_range_hints[FASTLOOKAHEADLIMITER_RELEASE].HintDescriptor =
646 		 LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_LOW;
647 		port_range_hints[FASTLOOKAHEADLIMITER_RELEASE].LowerBound = 0.01;
648 		port_range_hints[FASTLOOKAHEADLIMITER_RELEASE].UpperBound = 2.0;
649 
650 		/* Parameters for Attenuation (dB) */
651 		port_descriptors[FASTLOOKAHEADLIMITER_ATTENUATION] =
652 		 LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL;
653 		port_names[FASTLOOKAHEADLIMITER_ATTENUATION] =
654 		 D_("Attenuation (dB)");
655 		port_range_hints[FASTLOOKAHEADLIMITER_ATTENUATION].HintDescriptor =
656 		 LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE;
657 		port_range_hints[FASTLOOKAHEADLIMITER_ATTENUATION].LowerBound = 0;
658 		port_range_hints[FASTLOOKAHEADLIMITER_ATTENUATION].UpperBound = 70;
659 
660 		/* Parameters for Input 1 */
661 		port_descriptors[FASTLOOKAHEADLIMITER_IN_1] =
662 		 LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
663 		port_names[FASTLOOKAHEADLIMITER_IN_1] =
664 		 D_("Input 1");
665 		port_range_hints[FASTLOOKAHEADLIMITER_IN_1].HintDescriptor = 0;
666 
667 		/* Parameters for Input 2 */
668 		port_descriptors[FASTLOOKAHEADLIMITER_IN_2] =
669 		 LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
670 		port_names[FASTLOOKAHEADLIMITER_IN_2] =
671 		 D_("Input 2");
672 		port_range_hints[FASTLOOKAHEADLIMITER_IN_2].HintDescriptor = 0;
673 
674 		/* Parameters for Output 1 */
675 		port_descriptors[FASTLOOKAHEADLIMITER_OUT_1] =
676 		 LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
677 		port_names[FASTLOOKAHEADLIMITER_OUT_1] =
678 		 D_("Output 1");
679 		port_range_hints[FASTLOOKAHEADLIMITER_OUT_1].HintDescriptor = 0;
680 
681 		/* Parameters for Output 2 */
682 		port_descriptors[FASTLOOKAHEADLIMITER_OUT_2] =
683 		 LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
684 		port_names[FASTLOOKAHEADLIMITER_OUT_2] =
685 		 D_("Output 2");
686 		port_range_hints[FASTLOOKAHEADLIMITER_OUT_2].HintDescriptor = 0;
687 
688 		/* Parameters for latency */
689 		port_descriptors[FASTLOOKAHEADLIMITER_LATENCY] =
690 		 LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL;
691 		port_names[FASTLOOKAHEADLIMITER_LATENCY] =
692 		 D_("latency");
693 		port_range_hints[FASTLOOKAHEADLIMITER_LATENCY].HintDescriptor = 0;
694 
695 		fastLookaheadLimiterDescriptor->activate = activateFastLookaheadLimiter;
696 		fastLookaheadLimiterDescriptor->cleanup = cleanupFastLookaheadLimiter;
697 		fastLookaheadLimiterDescriptor->connect_port = connectPortFastLookaheadLimiter;
698 		fastLookaheadLimiterDescriptor->deactivate = NULL;
699 		fastLookaheadLimiterDescriptor->instantiate = instantiateFastLookaheadLimiter;
700 		fastLookaheadLimiterDescriptor->run = runFastLookaheadLimiter;
701 		fastLookaheadLimiterDescriptor->run_adding = runAddingFastLookaheadLimiter;
702 		fastLookaheadLimiterDescriptor->set_run_adding_gain = setRunAddingGainFastLookaheadLimiter;
703 	}
704 }
705 
swh_fini()706 static void __attribute__((destructor)) swh_fini() {
707 	if (fastLookaheadLimiterDescriptor) {
708 		free((LADSPA_PortDescriptor *)fastLookaheadLimiterDescriptor->PortDescriptors);
709 		free((char **)fastLookaheadLimiterDescriptor->PortNames);
710 		free((LADSPA_PortRangeHint *)fastLookaheadLimiterDescriptor->PortRangeHints);
711 		free(fastLookaheadLimiterDescriptor);
712 	}
713 	fastLookaheadLimiterDescriptor = NULL;
714 
715 }
716