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_dynamics_st.c,v 1.2 2004/06/15 14:50:55 tszilagyi Exp $
19 */
20 
21 
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <inttypes.h>
25 #include <string.h>
26 #include <math.h>
27 
28 #include "ladspa.h"
29 #include "tap_utils.h"
30 
31 
32 /* ***** VERY IMPORTANT! *****
33  *
34  * If you enable this, the plugin will use float arithmetics in DSP
35  * calculations.  This usually yields lower average CPU usage, but
36  * occasionaly may result in high CPU peaks which cause trouble to you
37  * and your JACK server.  The default is to use fixpoint arithmetics
38  * (with the following #define commented out).  But (depending on the
39  * processor on which you run the code) you may find floating point
40  * mode usable.
41  */
42 /*#define DYN_CALC_FLOAT*/
43 
44 
45 typedef signed int sample;
46 
47 /* coefficient for float to sample (signed int) conversion */
48 /* this allows for about 60 dB headroom above 0dB, if 0 dB is equivalent to 1.0f */
49 /* As 2^31 equals more than 180 dB, about 120 dB dynamics remains below 0 dB */
50 #define F2S 2147483
51 
52 
53 #ifdef DYN_CALC_FLOAT
54 typedef LADSPA_Data dyn_t;
55 typedef float rms_t;
56 #else
57 typedef sample dyn_t;
58 typedef int64_t rms_t;
59 #endif
60 
61 
62 
63 /* The Unique ID of the plugin: */
64 
65 #define ID_STEREO         2153
66 
67 /* The port numbers for the plugin: */
68 
69 #define ATTACK          0
70 #define RELEASE         1
71 #define OFFSGAIN        2
72 #define MUGAIN          3
73 #define RMSENV_L        4
74 #define RMSENV_R        5
75 #define MODGAIN_L       6
76 #define MODGAIN_R       7
77 #define STEREO          8
78 #define MODE            9
79 #define INPUT_L         10
80 #define INPUT_R         11
81 #define OUTPUT_L        12
82 #define OUTPUT_R        13
83 
84 
85 /* Total number of ports */
86 
87 #define PORTCOUNT_STEREO   14
88 
89 
90 #define TABSIZE 256
91 #define RMSSIZE 64
92 
93 
94 typedef struct {
95         rms_t        buffer[RMSSIZE];
96         unsigned int pos;
97         rms_t        sum;
98 } rms_env;
99 
100 
101 /* max. number of breakpoints on in/out dB graph */
102 #define MAX_POINTS 20
103 
104 typedef struct {
105 	LADSPA_Data x;
106 	LADSPA_Data y;
107 } GRAPH_POINT;
108 
109 typedef struct {
110 	unsigned long num_points;
111 	GRAPH_POINT points[MAX_POINTS];
112 } DYNAMICS_DATA;
113 
114 #include "tap_dynamics_presets.h"
115 
116 
117 /* The structure used to hold port connection information and state */
118 
119 typedef struct {
120 	LADSPA_Data * attack;
121 	LADSPA_Data * release;
122 	LADSPA_Data * offsgain;
123 	LADSPA_Data * mugain;
124 	LADSPA_Data * rmsenv_L;
125 	LADSPA_Data * rmsenv_R;
126 	LADSPA_Data * modgain_L;
127 	LADSPA_Data * modgain_R;
128 	LADSPA_Data * stereo;
129 	LADSPA_Data * mode;
130 	LADSPA_Data * input_L;
131 	LADSPA_Data * output_L;
132 	LADSPA_Data * input_R;
133 	LADSPA_Data * output_R;
134 	unsigned long sample_rate;
135 
136 	float * as;
137 	unsigned long count;
138 	dyn_t amp_L;
139 	dyn_t amp_R;
140 	dyn_t env_L;
141 	dyn_t env_R;
142 	float gain_L;
143 	float gain_R;
144 	float gain_out_L;
145 	float gain_out_R;
146 	rms_env * rms_L;
147 	rms_env * rms_R;
148 	rms_t sum_L;
149 	rms_t sum_R;
150 
151 	DYNAMICS_DATA graph;
152 
153 	LADSPA_Data run_adding_gain;
154 } Dynamics;
155 
156 
157 
158 /* RMS envelope stuff, grabbed without a second thought from Steve Harris's swh-plugins, util/rms.c */
159 /* Adapted, though, to be able to use fixed-point arithmetics as well. */
160 
161 rms_env *
rms_env_new(void)162 rms_env_new(void) {
163 
164         rms_env * new = (rms_env *)calloc(1, sizeof(rms_env));
165 
166         return new;
167 }
168 
169 void
rms_env_reset(rms_env * r)170 rms_env_reset(rms_env *r) {
171 
172         unsigned int i;
173 
174         for (i = 0; i < RMSSIZE; i++) {
175                 r->buffer[i] = 0.0f;
176         }
177         r->pos = 0;
178         r->sum = 0.0f;
179 }
180 
181 inline static
182 dyn_t
rms_env_process(rms_env * r,const rms_t x)183 rms_env_process(rms_env *r, const rms_t x) {
184 
185         r->sum -= r->buffer[r->pos];
186         r->sum += x;
187         r->buffer[r->pos] = x;
188         r->pos = (r->pos + 1) & (RMSSIZE - 1);
189 
190 #ifdef DYN_CALC_FLOAT
191         return sqrt(r->sum / (float)RMSSIZE);
192 #else
193         return sqrt(r->sum / RMSSIZE);
194 #endif
195 }
196 
197 
198 
199 inline
200 LADSPA_Data
get_table_gain(int mode,LADSPA_Data level)201 get_table_gain(int mode, LADSPA_Data level) {
202 
203 	LADSPA_Data x1 = -80.0f;
204 	LADSPA_Data y1 = -80.0f;
205 	LADSPA_Data x2 = 0.0f;
206 	LADSPA_Data y2 = 0.0f;
207 	int i = 0;
208 
209 	if (level <= -80.0f)
210 		return get_table_gain(mode, -79.9f);
211 
212 	while (i < dyn_data[mode].num_points && dyn_data[mode].points[i].x < level) {
213 		x1 = dyn_data[mode].points[i].x;
214 		y1 = dyn_data[mode].points[i].y;
215 		i++;
216 	}
217 	if (i < dyn_data[mode].num_points) {
218 		x2 = dyn_data[mode].points[i].x;
219 		y2 = dyn_data[mode].points[i].y;
220 	} else
221 		return 0.0f;
222 
223 	return y1 + ((level - x1) * (y2 - y1) / (x2 - x1)) - level;
224 }
225 
226 
227 /* Construct a new plugin instance. */
228 LADSPA_Handle
instantiate_Dynamics(const LADSPA_Descriptor * Descriptor,unsigned long sample_rate)229 instantiate_Dynamics(const LADSPA_Descriptor * Descriptor, unsigned long sample_rate) {
230 
231 	LADSPA_Handle * ptr;
232 
233 	float * as = NULL;
234 	unsigned int count = 0;
235 	dyn_t amp_L = 0.0f;
236 	dyn_t amp_R = 0.0f;
237 	dyn_t env_L = 0.0f;
238 	dyn_t env_R = 0.0f;
239 	float gain_L = 0.0f;
240 	float gain_R = 0.0f;
241 	float gain_out_L = 0.0f;
242 	float gain_out_R = 0.0f;
243 	rms_env * rms_L = NULL;
244 	rms_env * rms_R = NULL;
245 	rms_t sum_L = 0.0f;
246 	rms_t sum_R = 0.0f;
247 	int i;
248 
249 	if ((ptr = malloc(sizeof(Dynamics))) == NULL)
250 		return NULL;
251 
252 	((Dynamics *)ptr)->sample_rate = sample_rate;
253 	((Dynamics *)ptr)->run_adding_gain = 1.0;
254 
255         if ((rms_L = rms_env_new()) == NULL)
256 		return NULL;
257         if ((rms_R = rms_env_new()) == NULL)
258 		return NULL;
259 
260         if ((as = malloc(TABSIZE * sizeof(float))) == NULL)
261 		return NULL;
262 
263         as[0] = 1.0f;
264         for (i = 1; i < TABSIZE; i++) {
265 		as[i] = expf(-1.0f / (sample_rate * (float)i / (float)TABSIZE));
266         }
267 
268         ((Dynamics *)ptr)->as = as;
269         ((Dynamics *)ptr)->count = count;
270         ((Dynamics *)ptr)->amp_L = amp_L;
271         ((Dynamics *)ptr)->amp_R = amp_R;
272         ((Dynamics *)ptr)->env_L = env_L;
273         ((Dynamics *)ptr)->env_R = env_R;
274         ((Dynamics *)ptr)->gain_L = gain_L;
275         ((Dynamics *)ptr)->gain_R = gain_R;
276         ((Dynamics *)ptr)->gain_out_L = gain_out_L;
277         ((Dynamics *)ptr)->gain_out_R = gain_out_R;
278         ((Dynamics *)ptr)->rms_L = rms_L;
279         ((Dynamics *)ptr)->rms_R = rms_R;
280         ((Dynamics *)ptr)->sum_L = sum_L;
281         ((Dynamics *)ptr)->sum_R = sum_R;
282 
283 	return ptr;
284 }
285 
286 
287 
288 /* Connect a port to a data location. */
289 void
connect_port_Dynamics(LADSPA_Handle Instance,unsigned long Port,LADSPA_Data * DataLocation)290 connect_port_Dynamics(LADSPA_Handle Instance,
291 		     unsigned long Port,
292 		     LADSPA_Data * DataLocation) {
293 
294 	Dynamics * ptr = (Dynamics *)Instance;
295 
296 	switch (Port) {
297 	case ATTACK:
298 		ptr->attack = DataLocation;
299 		break;
300 	case RELEASE:
301 		ptr->release = DataLocation;
302 		break;
303 	case OFFSGAIN:
304 		ptr->offsgain = DataLocation;
305 		break;
306 	case MUGAIN:
307 		ptr->mugain = DataLocation;
308 		break;
309 	case RMSENV_L:
310 		ptr->rmsenv_L = DataLocation;
311 		*(ptr->rmsenv_L) = -60.0f;
312 		break;
313 	case RMSENV_R:
314 		ptr->rmsenv_R = DataLocation;
315 		*(ptr->rmsenv_R) = -60.0f;
316 		break;
317 	case MODGAIN_L:
318 		ptr->modgain_L = DataLocation;
319 		*(ptr->modgain_L) = 0.0f;
320 		break;
321 	case MODGAIN_R:
322 		ptr->modgain_R = DataLocation;
323 		*(ptr->modgain_R) = 0.0f;
324 		break;
325 	case STEREO:
326 		ptr->stereo = DataLocation;
327 		break;
328 	case MODE:
329 		ptr->mode = DataLocation;
330 		break;
331 	case INPUT_L:
332 		ptr->input_L = DataLocation;
333 		break;
334 	case OUTPUT_L:
335 		ptr->output_L = DataLocation;
336 		break;
337 	case INPUT_R:
338 		ptr->input_R = DataLocation;
339 		break;
340 	case OUTPUT_R:
341 		ptr->output_R = DataLocation;
342 		break;
343 	}
344 }
345 
346 
347 
348 void
run_Dynamics(LADSPA_Handle Instance,unsigned long sample_count)349 run_Dynamics(LADSPA_Handle Instance,
350 	     unsigned long sample_count) {
351 
352 	Dynamics * ptr = (Dynamics *)Instance;
353 	LADSPA_Data * input_L = ptr->input_L;
354 	LADSPA_Data * output_L = ptr->output_L;
355 	LADSPA_Data * input_R = ptr->input_R;
356 	LADSPA_Data * output_R = ptr->output_R;
357         const float attack = LIMIT(*(ptr->attack), 4.0f, 500.0f);
358         const float release = LIMIT(*(ptr->release), 4.0f, 1000.0f);
359         const float offsgain = LIMIT(*(ptr->offsgain), -20.0f, 20.0f);
360         const float mugain = db2lin(LIMIT(*(ptr->mugain), -20.0f, 20.0f));
361 	const int stereo = LIMIT(*(ptr->stereo), 0, 2);
362 	const int mode = LIMIT(*(ptr->mode), 0, NUM_MODES-1);
363 	unsigned long sample_index;
364 
365         dyn_t amp_L = ptr->amp_L;
366         dyn_t amp_R = ptr->amp_R;
367         dyn_t env_L = ptr->env_L;
368         dyn_t env_R = ptr->env_R;
369         float * as = ptr->as;
370         unsigned int count = ptr->count;
371         float gain_L = ptr->gain_L;
372         float gain_R = ptr->gain_R;
373         float gain_out_L = ptr->gain_out_L;
374         float gain_out_R = ptr->gain_out_R;
375         rms_env * rms_L = ptr->rms_L;
376         rms_env * rms_R = ptr->rms_R;
377         rms_t sum_L = ptr->sum_L;
378         rms_t sum_R = ptr->sum_R;
379 
380         const float ga = as[(unsigned int)(attack * 0.001f * (LADSPA_Data)(TABSIZE-1))];
381         const float gr = as[(unsigned int)(release * 0.001f * (LADSPA_Data)(TABSIZE-1))];
382         const float ef_a = ga * 0.25f;
383         const float ef_ai = 1.0f - ef_a;
384 
385 	float level_L = 0.0f;
386 	float level_R = 0.0f;
387 	float adjust_L = 0.0f;
388 	float adjust_R = 0.0f;
389 
390         for (sample_index = 0; sample_index < sample_count; sample_index++) {
391 
392 #ifdef DYN_CALC_FLOAT
393                 sum_L += input_L[sample_index] * input_L[sample_index];
394                 sum_R += input_R[sample_index] * input_R[sample_index];
395 
396                 if (amp_L > env_L) {
397                         env_L = env_L * ga + amp_L * (1.0f - ga);
398                 } else {
399                         env_L = env_L * gr + amp_L * (1.0f - gr);
400                 }
401                 if (amp_R > env_R) {
402                         env_R = env_R * ga + amp_R * (1.0f - ga);
403                 } else {
404                         env_R = env_R * gr + amp_R * (1.0f - gr);
405                 }
406 #else
407 		sum_L += (rms_t)(input_L[sample_index] * F2S) * (rms_t)(input_L[sample_index] * F2S);
408 		sum_R += (rms_t)(input_R[sample_index] * F2S) * (rms_t)(input_R[sample_index] * F2S);
409 
410 		if (amp_L) {
411 			if (amp_L > env_L) {
412 				env_L = (double)env_L * ga + (double)amp_L * (1.0f - ga);
413 			} else {
414 				env_L = (double)env_L * gr + (double)amp_L * (1.0f - gr);
415 			}
416 		} else
417 			env_L = 0;
418 
419 		if (amp_R) {
420 			if (amp_R > env_R) {
421 				env_R = (double)env_R * ga + (double)amp_R * (1.0f - ga);
422 			} else {
423 				env_R = (double)env_R * gr + (double)amp_R * (1.0f - gr);
424 			}
425 		} else
426 			env_R = 0;
427 #endif
428 
429 		if (count++ % 4 == 3) {
430 #ifdef DYN_CALC_FLOAT
431 			amp_L = rms_env_process(rms_L, sum_L * 0.25f);
432 			amp_R = rms_env_process(rms_R, sum_R * 0.25f);
433 #else
434 			if (sum_L)
435 				amp_L = rms_env_process(rms_L, sum_L * 0.25f);
436 			else
437 				amp_L = 0;
438 
439 			if (sum_R)
440 				amp_R = rms_env_process(rms_R, sum_R * 0.25f);
441 			else
442 				amp_R = 0;
443 #endif
444 
445 
446 #ifdef DYN_CALC_FLOAT
447 			if (isnan(amp_L))
448 				amp_L = 0.0f;
449 			if (isnan(amp_R))
450 				amp_R = 0.0f;
451 #endif
452 			sum_L = sum_R = 0;
453 
454 			/* set gain_out according to the difference between
455 			   the envelope volume level (env) and the corresponding
456 			   output level (from graph) */
457 #ifdef DYN_CALC_FLOAT
458 			level_L = 20 * log10f(2 * env_L);
459 			level_R = 20 * log10f(2 * env_R);
460 #else
461                         level_L = 20 * log10f(2 * (double)env_L / (double)F2S);
462                         level_R = 20 * log10f(2 * (double)env_R / (double)F2S);
463 #endif
464 			adjust_L = get_table_gain(mode, level_L + offsgain);
465 			adjust_R = get_table_gain(mode, level_R + offsgain);
466 
467 			/* set gains according to stereo mode */
468 			switch (stereo) {
469 			case 0:
470 				gain_out_L = db2lin(adjust_L);
471 				gain_out_R = db2lin(adjust_R);
472 				break;
473 			case 1:
474 				adjust_L = adjust_R = (adjust_L + adjust_R) / 2.0f;
475 				gain_out_L = gain_out_R = db2lin(adjust_L);
476 				break;
477 			case 2:
478 				adjust_L = adjust_R = (adjust_L > adjust_R) ? adjust_L : adjust_R;
479 				gain_out_L = gain_out_R = db2lin(adjust_L);
480 				break;
481 			}
482 
483 		}
484 		gain_L = gain_L * ef_a + gain_out_L * ef_ai;
485 		gain_R = gain_R * ef_a + gain_out_R * ef_ai;
486 		output_L[sample_index] = input_L[sample_index] * gain_L * mugain;
487 		output_R[sample_index] = input_R[sample_index] * gain_R * mugain;
488         }
489         ptr->sum_L = sum_L;
490         ptr->sum_R = sum_R;
491         ptr->amp_L = amp_L;
492         ptr->amp_R = amp_R;
493         ptr->gain_L = gain_L;
494         ptr->gain_R = gain_R;
495         ptr->gain_out_L = gain_out_L;
496         ptr->gain_out_R = gain_out_R;
497         ptr->env_L = env_L;
498         ptr->env_R = env_R;
499         ptr->count = count;
500 
501 	*(ptr->rmsenv_L) = LIMIT(level_L, -60.0f, 20.0f);
502 	*(ptr->rmsenv_R) = LIMIT(level_R, -60.0f, 20.0f);
503 	*(ptr->modgain_L) = LIMIT(adjust_L, -60.0f, 20.0f);
504 	*(ptr->modgain_R) = LIMIT(adjust_R, -60.0f, 20.0f);
505 }
506 
507 
508 
509 void
set_run_adding_gain_Dynamics(LADSPA_Handle Instance,LADSPA_Data gain)510 set_run_adding_gain_Dynamics(LADSPA_Handle Instance, LADSPA_Data gain) {
511 
512 	Dynamics * ptr = (Dynamics *)Instance;
513 
514 	ptr->run_adding_gain = gain;
515 }
516 
517 
518 
519 void
run_adding_Dynamics(LADSPA_Handle Instance,unsigned long sample_count)520 run_adding_Dynamics(LADSPA_Handle Instance,
521 		    unsigned long sample_count) {
522 
523 	Dynamics * ptr = (Dynamics *)Instance;
524 	LADSPA_Data * input_L = ptr->input_L;
525 	LADSPA_Data * output_L = ptr->output_L;
526 	LADSPA_Data * input_R = ptr->input_R;
527 	LADSPA_Data * output_R = ptr->output_R;
528         const float attack = LIMIT(*(ptr->attack), 4.0f, 500.0f);
529         const float release = LIMIT(*(ptr->release), 4.0f, 1000.0f);
530         const float offsgain = LIMIT(*(ptr->offsgain), -20.0f, 20.0f);
531         const float mugain = db2lin(LIMIT(*(ptr->mugain), -20.0f, 20.0f));
532 	const int stereo = LIMIT(*(ptr->stereo), 0, 2);
533 	const int mode = LIMIT(*(ptr->mode), 0, NUM_MODES-1);
534 	unsigned long sample_index;
535 
536         dyn_t amp_L = ptr->amp_L;
537         dyn_t amp_R = ptr->amp_R;
538         dyn_t env_L = ptr->env_L;
539         dyn_t env_R = ptr->env_R;
540         float * as = ptr->as;
541         unsigned int count = ptr->count;
542         float gain_L = ptr->gain_L;
543         float gain_R = ptr->gain_R;
544         float gain_out_L = ptr->gain_out_L;
545         float gain_out_R = ptr->gain_out_R;
546         rms_env * rms_L = ptr->rms_L;
547         rms_env * rms_R = ptr->rms_R;
548         rms_t sum_L = ptr->sum_L;
549         rms_t sum_R = ptr->sum_R;
550 
551         const float ga = as[(unsigned int)(attack * 0.001f * (LADSPA_Data)(TABSIZE-1))];
552         const float gr = as[(unsigned int)(release * 0.001f * (LADSPA_Data)(TABSIZE-1))];
553         const float ef_a = ga * 0.25f;
554         const float ef_ai = 1.0f - ef_a;
555 
556 	float level_L = 0.0f;
557 	float level_R = 0.0f;
558 	float adjust_L = 0.0f;
559 	float adjust_R = 0.0f;
560 
561         for (sample_index = 0; sample_index < sample_count; sample_index++) {
562 
563 #ifdef DYN_CALC_FLOAT
564                 sum_L += input_L[sample_index] * input_L[sample_index];
565                 sum_R += input_R[sample_index] * input_R[sample_index];
566 
567                 if (amp_L > env_L) {
568                         env_L = env_L * ga + amp_L * (1.0f - ga);
569                 } else {
570                         env_L = env_L * gr + amp_L * (1.0f - gr);
571                 }
572                 if (amp_R > env_R) {
573                         env_R = env_R * ga + amp_R * (1.0f - ga);
574                 } else {
575                         env_R = env_R * gr + amp_R * (1.0f - gr);
576                 }
577 #else
578 		sum_L += (rms_t)(input_L[sample_index] * F2S) * (rms_t)(input_L[sample_index] * F2S);
579 		sum_R += (rms_t)(input_R[sample_index] * F2S) * (rms_t)(input_R[sample_index] * F2S);
580 
581 		if (amp_L) {
582 			if (amp_L > env_L) {
583 				env_L = (double)env_L * ga + (double)amp_L * (1.0f - ga);
584 			} else {
585 				env_L = (double)env_L * gr + (double)amp_L * (1.0f - gr);
586 			}
587 		} else
588 			env_L = 0;
589 
590 		if (amp_R) {
591 			if (amp_R > env_R) {
592 				env_R = (double)env_R * ga + (double)amp_R * (1.0f - ga);
593 			} else {
594 				env_R = (double)env_R * gr + (double)amp_R * (1.0f - gr);
595 			}
596 		} else
597 			env_R = 0;
598 #endif
599 
600 		if (count++ % 4 == 3) {
601 #ifdef DYN_CALC_FLOAT
602 			amp_L = rms_env_process(rms_L, sum_L * 0.25f);
603 			amp_R = rms_env_process(rms_R, sum_R * 0.25f);
604 #else
605 			if (sum_L)
606 				amp_L = rms_env_process(rms_L, sum_L * 0.25f);
607 			else
608 				amp_L = 0;
609 
610 			if (sum_R)
611 				amp_R = rms_env_process(rms_R, sum_R * 0.25f);
612 			else
613 				amp_R = 0;
614 #endif
615 
616 
617 #ifdef DYN_CALC_FLOAT
618 			if (isnan(amp_L))
619 				amp_L = 0.0f;
620 			if (isnan(amp_R))
621 				amp_R = 0.0f;
622 #endif
623 			sum_L = sum_R = 0;
624 
625 			/* set gain_out according to the difference between
626 			   the envelope volume level (env) and the corresponding
627 			   output level (from graph) */
628 #ifdef DYN_CALC_FLOAT
629 			level_L = 20 * log10f(2 * env_L);
630 			level_R = 20 * log10f(2 * env_R);
631 #else
632                         level_L = 20 * log10f(2 * (double)env_L / (double)F2S);
633                         level_R = 20 * log10f(2 * (double)env_R / (double)F2S);
634 #endif
635 			adjust_L = get_table_gain(mode, level_L + offsgain);
636 			adjust_R = get_table_gain(mode, level_R + offsgain);
637 
638 			/* set gains according to stereo mode */
639 			switch (stereo) {
640 			case 0:
641 				gain_out_L = db2lin(adjust_L);
642 				gain_out_R = db2lin(adjust_R);
643 				break;
644 			case 1:
645 				adjust_L = adjust_R = (adjust_L + adjust_R) / 2.0f;
646 				gain_out_L = gain_out_R = db2lin(adjust_L);
647 				break;
648 			case 2:
649 				adjust_L = adjust_R = (adjust_L > adjust_R) ? adjust_L : adjust_R;
650 				gain_out_L = gain_out_R = db2lin(adjust_L);
651 				break;
652 			}
653 
654 		}
655 		gain_L = gain_L * ef_a + gain_out_L * ef_ai;
656 		gain_R = gain_R * ef_a + gain_out_R * ef_ai;
657 		output_L[sample_index] += ptr->run_adding_gain * input_L[sample_index] * gain_L * mugain;
658 		output_R[sample_index] += ptr->run_adding_gain * input_R[sample_index] * gain_R * mugain;
659         }
660         ptr->sum_L = sum_L;
661         ptr->sum_R = sum_R;
662         ptr->amp_L = amp_L;
663         ptr->amp_R = amp_R;
664         ptr->gain_L = gain_L;
665         ptr->gain_R = gain_R;
666         ptr->gain_out_L = gain_out_L;
667         ptr->gain_out_R = gain_out_R;
668         ptr->env_L = env_L;
669         ptr->env_R = env_R;
670         ptr->count = count;
671 
672 	*(ptr->rmsenv_L) = LIMIT(level_L, -60.0f, 20.0f);
673 	*(ptr->rmsenv_R) = LIMIT(level_R, -60.0f, 20.0f);
674 	*(ptr->modgain_L) = LIMIT(adjust_L, -60.0f, 20.0f);
675 	*(ptr->modgain_R) = LIMIT(adjust_R, -60.0f, 20.0f);
676 }
677 
678 
679 
680 
681 /* Throw away a Dynamics effect instance. */
682 void
cleanup_Dynamics(LADSPA_Handle Instance)683 cleanup_Dynamics(LADSPA_Handle Instance) {
684 
685 	Dynamics * ptr = (Dynamics *)Instance;
686 
687 	free(ptr->rms_L);
688 	free(ptr->rms_R);
689 	free(ptr->as);
690 	free(Instance);
691 }
692 
693 
694 
695 LADSPA_Descriptor * stereo_descriptor = NULL;
696 
697 
698 
699 /* _init() is called automatically when the plugin library is first
700    loaded. */
701 void
_init()702 _init() {
703 
704 	char ** port_names;
705 	LADSPA_PortDescriptor * port_descriptors;
706 	LADSPA_PortRangeHint * port_range_hints;
707 
708 	if ((stereo_descriptor =
709 	     (LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor))) == NULL)
710 		exit(1);
711 
712 	stereo_descriptor->UniqueID = ID_STEREO;
713 	stereo_descriptor->Label = strdup("tap_dynamics_st");
714 	stereo_descriptor->Properties = 0;
715 	stereo_descriptor->Name = strdup("TAP Dynamics (St)");
716 	stereo_descriptor->Maker = strdup("Tom Szilagyi");
717 	stereo_descriptor->Copyright = strdup("GPL");
718 	stereo_descriptor->PortCount = PORTCOUNT_STEREO;
719 
720 	if ((port_descriptors =
721 	     (LADSPA_PortDescriptor *)calloc(PORTCOUNT_STEREO, sizeof(LADSPA_PortDescriptor))) == NULL)
722 		exit(1);
723 
724 	stereo_descriptor->PortDescriptors = (const LADSPA_PortDescriptor *)port_descriptors;
725 	port_descriptors[ATTACK] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
726 	port_descriptors[RELEASE] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
727 	port_descriptors[OFFSGAIN] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
728 	port_descriptors[MUGAIN] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
729 	port_descriptors[STEREO] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
730 	port_descriptors[MODE] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
731 	port_descriptors[RMSENV_L] = LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL;
732 	port_descriptors[RMSENV_R] = LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL;
733 	port_descriptors[MODGAIN_L] = LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL;
734 	port_descriptors[MODGAIN_R] = LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL;
735 	port_descriptors[INPUT_L] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
736 	port_descriptors[INPUT_R] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
737 	port_descriptors[OUTPUT_L] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
738 	port_descriptors[OUTPUT_R] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
739 
740 	if ((port_names =
741 	     (char **)calloc(PORTCOUNT_STEREO, sizeof(char *))) == NULL)
742 		exit(1);
743 
744 	stereo_descriptor->PortNames = (const char **)port_names;
745 	port_names[ATTACK] = strdup("Attack [ms]");
746 	port_names[RELEASE] = strdup("Release [ms]");
747 	port_names[OFFSGAIN] = strdup("Offset Gain [dB]");
748 	port_names[MUGAIN] = strdup("Makeup Gain [dB]");
749 	port_names[STEREO] = strdup("Stereo Mode");
750 	port_names[MODE] = strdup("Function");
751 	port_names[RMSENV_L] = strdup("Envelope Volume (L) [dB]");
752 	port_names[RMSENV_R] = strdup("Envelope Volume (R) [dB]");
753 	port_names[MODGAIN_L] = strdup("Gain Adjustment (L) [dB]");
754 	port_names[MODGAIN_R] = strdup("Gain Adjustment (R) [dB]");
755 	port_names[INPUT_L] = strdup("Input Left");
756 	port_names[INPUT_R] = strdup("Input Right");
757 	port_names[OUTPUT_L] = strdup("Output Left");
758 	port_names[OUTPUT_R] = strdup("Output Right");
759 
760 	if ((port_range_hints =
761 	     ((LADSPA_PortRangeHint *)calloc(PORTCOUNT_STEREO, sizeof(LADSPA_PortRangeHint)))) == NULL)
762 		exit(1);
763 
764 	stereo_descriptor->PortRangeHints = (const LADSPA_PortRangeHint *)port_range_hints;
765 	port_range_hints[ATTACK].HintDescriptor =
766 		(LADSPA_HINT_BOUNDED_BELOW |
767 		 LADSPA_HINT_BOUNDED_ABOVE |
768 		 LADSPA_HINT_DEFAULT_LOW);
769 	port_range_hints[RELEASE].HintDescriptor =
770 		(LADSPA_HINT_BOUNDED_BELOW |
771 		 LADSPA_HINT_BOUNDED_ABOVE |
772 		 LADSPA_HINT_DEFAULT_MIDDLE);
773 	port_range_hints[OFFSGAIN].HintDescriptor =
774 		(LADSPA_HINT_BOUNDED_BELOW |
775 		 LADSPA_HINT_BOUNDED_ABOVE |
776 		 LADSPA_HINT_DEFAULT_0);
777 	port_range_hints[MUGAIN].HintDescriptor =
778 		(LADSPA_HINT_BOUNDED_BELOW |
779 		 LADSPA_HINT_BOUNDED_ABOVE |
780 		 LADSPA_HINT_DEFAULT_0);
781 	port_range_hints[RMSENV_L].HintDescriptor =
782 		(LADSPA_HINT_BOUNDED_BELOW |
783 		 LADSPA_HINT_BOUNDED_ABOVE |
784 		 LADSPA_HINT_DEFAULT_0);
785 	port_range_hints[RMSENV_R].HintDescriptor =
786 		(LADSPA_HINT_BOUNDED_BELOW |
787 		 LADSPA_HINT_BOUNDED_ABOVE |
788 		 LADSPA_HINT_DEFAULT_0);
789 	port_range_hints[MODGAIN_L].HintDescriptor =
790 		(LADSPA_HINT_BOUNDED_BELOW |
791 		 LADSPA_HINT_BOUNDED_ABOVE |
792 		 LADSPA_HINT_DEFAULT_0);
793 	port_range_hints[MODGAIN_R].HintDescriptor =
794 		(LADSPA_HINT_BOUNDED_BELOW |
795 		 LADSPA_HINT_BOUNDED_ABOVE |
796 		 LADSPA_HINT_DEFAULT_0);
797 	port_range_hints[STEREO].HintDescriptor =
798 		(LADSPA_HINT_BOUNDED_BELOW |
799 		 LADSPA_HINT_BOUNDED_ABOVE |
800 		 LADSPA_HINT_INTEGER |
801 		 LADSPA_HINT_DEFAULT_0);
802 	port_range_hints[MODE].HintDescriptor =
803 		(LADSPA_HINT_BOUNDED_BELOW |
804 		 LADSPA_HINT_BOUNDED_ABOVE |
805 		 LADSPA_HINT_INTEGER |
806 		 LADSPA_HINT_DEFAULT_0);
807 	port_range_hints[ATTACK].LowerBound = 4.0f;
808 	port_range_hints[ATTACK].UpperBound = 500.0f;
809 	port_range_hints[RELEASE].LowerBound = 4.0f;
810 	port_range_hints[RELEASE].UpperBound = 1000.0f;
811 	port_range_hints[OFFSGAIN].LowerBound = -20.0f;
812 	port_range_hints[OFFSGAIN].UpperBound = 20.0f;
813 	port_range_hints[MUGAIN].LowerBound = -20.0f;
814 	port_range_hints[MUGAIN].UpperBound = 20.0f;
815 	port_range_hints[RMSENV_L].LowerBound = -60.0f;
816 	port_range_hints[RMSENV_L].UpperBound = 20.0f;
817 	port_range_hints[RMSENV_R].LowerBound = -60.0f;
818 	port_range_hints[RMSENV_R].UpperBound = 20.0f;
819 	port_range_hints[MODGAIN_L].LowerBound = -60.0f;
820 	port_range_hints[MODGAIN_L].UpperBound = 20.0f;
821 	port_range_hints[MODGAIN_R].LowerBound = -60.0f;
822 	port_range_hints[MODGAIN_R].UpperBound = 20.0f;
823 	port_range_hints[STEREO].LowerBound = 0;
824 	port_range_hints[STEREO].UpperBound = 2.1f;
825 	port_range_hints[MODE].LowerBound = 0;
826 	port_range_hints[MODE].UpperBound = NUM_MODES - 0.9f;
827 	port_range_hints[INPUT_L].HintDescriptor = 0;
828 	port_range_hints[INPUT_R].HintDescriptor = 0;
829 	port_range_hints[OUTPUT_L].HintDescriptor = 0;
830 	port_range_hints[OUTPUT_R].HintDescriptor = 0;
831 	stereo_descriptor->instantiate = instantiate_Dynamics;
832 	stereo_descriptor->connect_port = connect_port_Dynamics;
833 	stereo_descriptor->activate = NULL;
834 	stereo_descriptor->run = run_Dynamics;
835 	stereo_descriptor->run_adding = run_adding_Dynamics;
836 	stereo_descriptor->set_run_adding_gain = set_run_adding_gain_Dynamics;
837 	stereo_descriptor->deactivate = NULL;
838 	stereo_descriptor->cleanup = cleanup_Dynamics;
839 }
840 
841 
842 void
delete_descriptor(LADSPA_Descriptor * descriptor)843 delete_descriptor(LADSPA_Descriptor * descriptor) {
844 	unsigned long index;
845 	if (descriptor) {
846 		free((char *)descriptor->Label);
847 		free((char *)descriptor->Name);
848 		free((char *)descriptor->Maker);
849 		free((char *)descriptor->Copyright);
850 		free((LADSPA_PortDescriptor *)descriptor->PortDescriptors);
851 		for (index = 0; index < descriptor->PortCount; index++)
852 			free((char *)(descriptor->PortNames[index]));
853 		free((char **)descriptor->PortNames);
854 		free((LADSPA_PortRangeHint *)descriptor->PortRangeHints);
855 		free(descriptor);
856 	}
857 }
858 
859 
860 /* _fini() is called automatically when the library is unloaded. */
861 void
_fini()862 _fini() {
863 	delete_descriptor(stereo_descriptor);
864 }
865 
866 
867 /* Return a descriptor of the requested plugin type. */
868 const LADSPA_Descriptor *
ladspa_descriptor(unsigned long Index)869 ladspa_descriptor(unsigned long Index) {
870 
871 	switch (Index) {
872 	case 0:
873 		return stereo_descriptor;
874 	default:
875 		return NULL;
876 	}
877 }
878