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 "valve_rect_1405.xml"
29 
30 #include "ladspa-util.h"
31 
32 #define VALVERECT_SAG                  0
33 #define VALVERECT_DIST_P               1
34 #define VALVERECT_INPUT                2
35 #define VALVERECT_OUTPUT               3
36 
37 static LADSPA_Descriptor *valveRectDescriptor = NULL;
38 
39 typedef struct {
40 	LADSPA_Data *sag;
41 	LADSPA_Data *dist_p;
42 	LADSPA_Data *input;
43 	LADSPA_Data *output;
44 	unsigned int apos;
45 	float *      avg;
46 	int          avg_size;
47 	float        avg_sizer;
48 	float        avgs;
49 	float        lp1tm1;
50 	float        lp2tm1;
51 	LADSPA_Data run_adding_gain;
52 } ValveRect;
53 
54 _WINDOWS_DLL_EXPORT_
ladspa_descriptor(unsigned long index)55 const LADSPA_Descriptor *ladspa_descriptor(unsigned long index) {
56 
57 #ifdef WIN32
58 	if (bIsFirstTime) {
59 		swh_init();
60 		bIsFirstTime = 0;
61 	}
62 #endif
63 	switch (index) {
64 	case 0:
65 		return valveRectDescriptor;
66 	default:
67 		return NULL;
68 	}
69 }
70 
activateValveRect(LADSPA_Handle instance)71 static void activateValveRect(LADSPA_Handle instance) {
72 	ValveRect *plugin_data = (ValveRect *)instance;
73 	unsigned int apos = plugin_data->apos;
74 	float *avg = plugin_data->avg;
75 	int avg_size = plugin_data->avg_size;
76 	float avg_sizer = plugin_data->avg_sizer;
77 	float avgs = plugin_data->avgs;
78 	float lp1tm1 = plugin_data->lp1tm1;
79 	float lp2tm1 = plugin_data->lp2tm1;
80 #line 36 "valve_rect_1405.xml"
81 	memset(avg, 0, avg_size * sizeof(float));
82 	avgs = 0.0f;
83 	apos = 0;
84 	lp1tm1 = 0.0f;
85 	lp2tm1 = 0.0f;
86 	plugin_data->apos = apos;
87 	plugin_data->avg = avg;
88 	plugin_data->avg_size = avg_size;
89 	plugin_data->avg_sizer = avg_sizer;
90 	plugin_data->avgs = avgs;
91 	plugin_data->lp1tm1 = lp1tm1;
92 	plugin_data->lp2tm1 = lp2tm1;
93 
94 }
95 
cleanupValveRect(LADSPA_Handle instance)96 static void cleanupValveRect(LADSPA_Handle instance) {
97 #line 44 "valve_rect_1405.xml"
98 	ValveRect *plugin_data = (ValveRect *)instance;
99 	free(plugin_data->avg);
100 	free(instance);
101 }
102 
connectPortValveRect(LADSPA_Handle instance,unsigned long port,LADSPA_Data * data)103 static void connectPortValveRect(
104  LADSPA_Handle instance,
105  unsigned long port,
106  LADSPA_Data *data) {
107 	ValveRect *plugin;
108 
109 	plugin = (ValveRect *)instance;
110 	switch (port) {
111 	case VALVERECT_SAG:
112 		plugin->sag = data;
113 		break;
114 	case VALVERECT_DIST_P:
115 		plugin->dist_p = data;
116 		break;
117 	case VALVERECT_INPUT:
118 		plugin->input = data;
119 		break;
120 	case VALVERECT_OUTPUT:
121 		plugin->output = data;
122 		break;
123 	}
124 }
125 
instantiateValveRect(const LADSPA_Descriptor * descriptor,unsigned long s_rate)126 static LADSPA_Handle instantiateValveRect(
127  const LADSPA_Descriptor *descriptor,
128  unsigned long s_rate) {
129 	ValveRect *plugin_data = (ValveRect *)calloc(1, sizeof(ValveRect));
130 	unsigned int apos;
131 	float *avg = NULL;
132 	int avg_size;
133 	float avg_sizer;
134 	float avgs;
135 	float lp1tm1;
136 	float lp2tm1;
137 
138 #line 19 "valve_rect_1405.xml"
139 	// Number of samples in averaging buffer
140 	avg_size = s_rate / 9;
141 	// Reciprocal of obove
142 	avg_sizer = 9.0f / (float)s_rate;
143 	// Averaging buffer
144 	avg = calloc(avg_size, sizeof(float));
145 	// Sum of samples in averaging buffer
146 	avgs = 0.0f;
147 	// Position in averaging buffer
148 	apos = 0;
149 	// Last value in lowpass 1
150 	lp1tm1 = 0.0f;
151 	// Last value in lowpass 2
152 	lp2tm1 = 0.0f;
153 
154 	plugin_data->apos = apos;
155 	plugin_data->avg = avg;
156 	plugin_data->avg_size = avg_size;
157 	plugin_data->avg_sizer = avg_sizer;
158 	plugin_data->avgs = avgs;
159 	plugin_data->lp1tm1 = lp1tm1;
160 	plugin_data->lp2tm1 = lp2tm1;
161 
162 	return (LADSPA_Handle)plugin_data;
163 }
164 
165 #undef buffer_write
166 #undef RUN_ADDING
167 #undef RUN_REPLACING
168 
169 #define buffer_write(b, v) (b = v)
170 #define RUN_ADDING    0
171 #define RUN_REPLACING 1
172 
runValveRect(LADSPA_Handle instance,unsigned long sample_count)173 static void runValveRect(LADSPA_Handle instance, unsigned long sample_count) {
174 	ValveRect *plugin_data = (ValveRect *)instance;
175 
176 	/* Sag level (float value) */
177 	const LADSPA_Data sag = *(plugin_data->sag);
178 
179 	/* Distortion (float value) */
180 	const LADSPA_Data dist_p = *(plugin_data->dist_p);
181 
182 	/* Input (array of floats of length sample_count) */
183 	const LADSPA_Data * const input = plugin_data->input;
184 
185 	/* Output (array of floats of length sample_count) */
186 	LADSPA_Data * const output = plugin_data->output;
187 	unsigned int apos = plugin_data->apos;
188 	float * avg = plugin_data->avg;
189 	int avg_size = plugin_data->avg_size;
190 	float avg_sizer = plugin_data->avg_sizer;
191 	float avgs = plugin_data->avgs;
192 	float lp1tm1 = plugin_data->lp1tm1;
193 	float lp2tm1 = plugin_data->lp2tm1;
194 
195 #line 48 "valve_rect_1405.xml"
196 	unsigned long pos;
197 	float q, x, fx;
198 	const float dist = dist_p * 40.0f + 0.1f;
199 
200 	for (pos = 0; pos < sample_count; pos++) {
201 	  x = fabs(input[pos]);
202 	  if (x > lp1tm1) {
203 	    lp1tm1 = x;
204 	  } else {
205 	    lp1tm1 = 0.9999f * lp1tm1 + 0.0001f * x;
206 	  }
207 
208 	  avgs -= avg[apos];
209 	  avgs += lp1tm1;
210 	  avg[apos++] = lp1tm1;
211 	  apos %= avg_size;
212 
213 	  lp2tm1 = 0.999f * lp2tm1 + avgs*avg_sizer * 0.001f;
214 	  q = lp1tm1 * sag - lp2tm1 * 1.02f - 1.0f;
215 	  if (q > -0.01f) {
216 	    q = -0.01f;
217 	  } else if (q < -1.0f) {
218 	    q = -1.0f;
219 	  }
220 
221 	  if (input[pos] == q) {
222 	    fx = 1.0f / dist + q / (1.0f - f_exp(dist * q));
223 	  } else {
224 	    fx = (input[pos] - q) /
225 	     (1.0f - f_exp(-dist * (input[pos] - q))) +
226 	     q / (1.0f - f_exp(dist * q));
227 	  }
228 
229 	  buffer_write(output[pos], fx);
230 	}
231 
232 	plugin_data->lp1tm1 = lp1tm1;
233 	plugin_data->lp2tm1 = lp2tm1;
234 	plugin_data->avgs = avgs;
235 	plugin_data->apos = apos;
236 }
237 #undef buffer_write
238 #undef RUN_ADDING
239 #undef RUN_REPLACING
240 
241 #define buffer_write(b, v) (b += (v) * run_adding_gain)
242 #define RUN_ADDING    1
243 #define RUN_REPLACING 0
244 
setRunAddingGainValveRect(LADSPA_Handle instance,LADSPA_Data gain)245 static void setRunAddingGainValveRect(LADSPA_Handle instance, LADSPA_Data gain) {
246 	((ValveRect *)instance)->run_adding_gain = gain;
247 }
248 
runAddingValveRect(LADSPA_Handle instance,unsigned long sample_count)249 static void runAddingValveRect(LADSPA_Handle instance, unsigned long sample_count) {
250 	ValveRect *plugin_data = (ValveRect *)instance;
251 	LADSPA_Data run_adding_gain = plugin_data->run_adding_gain;
252 
253 	/* Sag level (float value) */
254 	const LADSPA_Data sag = *(plugin_data->sag);
255 
256 	/* Distortion (float value) */
257 	const LADSPA_Data dist_p = *(plugin_data->dist_p);
258 
259 	/* Input (array of floats of length sample_count) */
260 	const LADSPA_Data * const input = plugin_data->input;
261 
262 	/* Output (array of floats of length sample_count) */
263 	LADSPA_Data * const output = plugin_data->output;
264 	unsigned int apos = plugin_data->apos;
265 	float * avg = plugin_data->avg;
266 	int avg_size = plugin_data->avg_size;
267 	float avg_sizer = plugin_data->avg_sizer;
268 	float avgs = plugin_data->avgs;
269 	float lp1tm1 = plugin_data->lp1tm1;
270 	float lp2tm1 = plugin_data->lp2tm1;
271 
272 #line 48 "valve_rect_1405.xml"
273 	unsigned long pos;
274 	float q, x, fx;
275 	const float dist = dist_p * 40.0f + 0.1f;
276 
277 	for (pos = 0; pos < sample_count; pos++) {
278 	  x = fabs(input[pos]);
279 	  if (x > lp1tm1) {
280 	    lp1tm1 = x;
281 	  } else {
282 	    lp1tm1 = 0.9999f * lp1tm1 + 0.0001f * x;
283 	  }
284 
285 	  avgs -= avg[apos];
286 	  avgs += lp1tm1;
287 	  avg[apos++] = lp1tm1;
288 	  apos %= avg_size;
289 
290 	  lp2tm1 = 0.999f * lp2tm1 + avgs*avg_sizer * 0.001f;
291 	  q = lp1tm1 * sag - lp2tm1 * 1.02f - 1.0f;
292 	  if (q > -0.01f) {
293 	    q = -0.01f;
294 	  } else if (q < -1.0f) {
295 	    q = -1.0f;
296 	  }
297 
298 	  if (input[pos] == q) {
299 	    fx = 1.0f / dist + q / (1.0f - f_exp(dist * q));
300 	  } else {
301 	    fx = (input[pos] - q) /
302 	     (1.0f - f_exp(-dist * (input[pos] - q))) +
303 	     q / (1.0f - f_exp(dist * q));
304 	  }
305 
306 	  buffer_write(output[pos], fx);
307 	}
308 
309 	plugin_data->lp1tm1 = lp1tm1;
310 	plugin_data->lp2tm1 = lp2tm1;
311 	plugin_data->avgs = avgs;
312 	plugin_data->apos = apos;
313 }
314 
swh_init()315 static void __attribute__((constructor)) swh_init() {
316 	char **port_names;
317 	LADSPA_PortDescriptor *port_descriptors;
318 	LADSPA_PortRangeHint *port_range_hints;
319 
320 #ifdef ENABLE_NLS
321 #define D_(s) dgettext(PACKAGE, s)
322 	bindtextdomain(PACKAGE, PACKAGE_LOCALE_DIR);
323 #else
324 #define D_(s) (s)
325 #endif
326 
327 
328 	valveRectDescriptor =
329 	 (LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor));
330 
331 	if (valveRectDescriptor) {
332 		valveRectDescriptor->UniqueID = 1405;
333 		valveRectDescriptor->Label = "valveRect";
334 		valveRectDescriptor->Properties =
335 		 LADSPA_PROPERTY_HARD_RT_CAPABLE;
336 		valveRectDescriptor->Name =
337 		 D_("Valve rectifier");
338 		valveRectDescriptor->Maker =
339 		 "Steve Harris <steve@plugin.org.uk>";
340 		valveRectDescriptor->Copyright =
341 		 "GPL";
342 		valveRectDescriptor->PortCount = 4;
343 
344 		port_descriptors = (LADSPA_PortDescriptor *)calloc(4,
345 		 sizeof(LADSPA_PortDescriptor));
346 		valveRectDescriptor->PortDescriptors =
347 		 (const LADSPA_PortDescriptor *)port_descriptors;
348 
349 		port_range_hints = (LADSPA_PortRangeHint *)calloc(4,
350 		 sizeof(LADSPA_PortRangeHint));
351 		valveRectDescriptor->PortRangeHints =
352 		 (const LADSPA_PortRangeHint *)port_range_hints;
353 
354 		port_names = (char **)calloc(4, sizeof(char*));
355 		valveRectDescriptor->PortNames =
356 		 (const char **)port_names;
357 
358 		/* Parameters for Sag level */
359 		port_descriptors[VALVERECT_SAG] =
360 		 LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
361 		port_names[VALVERECT_SAG] =
362 		 D_("Sag level");
363 		port_range_hints[VALVERECT_SAG].HintDescriptor =
364 		 LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0;
365 		port_range_hints[VALVERECT_SAG].LowerBound = 0;
366 		port_range_hints[VALVERECT_SAG].UpperBound = 1;
367 
368 		/* Parameters for Distortion */
369 		port_descriptors[VALVERECT_DIST_P] =
370 		 LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
371 		port_names[VALVERECT_DIST_P] =
372 		 D_("Distortion");
373 		port_range_hints[VALVERECT_DIST_P].HintDescriptor =
374 		 LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_0;
375 		port_range_hints[VALVERECT_DIST_P].LowerBound = 0;
376 		port_range_hints[VALVERECT_DIST_P].UpperBound = 1;
377 
378 		/* Parameters for Input */
379 		port_descriptors[VALVERECT_INPUT] =
380 		 LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
381 		port_names[VALVERECT_INPUT] =
382 		 D_("Input");
383 		port_range_hints[VALVERECT_INPUT].HintDescriptor = 0;
384 
385 		/* Parameters for Output */
386 		port_descriptors[VALVERECT_OUTPUT] =
387 		 LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
388 		port_names[VALVERECT_OUTPUT] =
389 		 D_("Output");
390 		port_range_hints[VALVERECT_OUTPUT].HintDescriptor = 0;
391 
392 		valveRectDescriptor->activate = activateValveRect;
393 		valveRectDescriptor->cleanup = cleanupValveRect;
394 		valveRectDescriptor->connect_port = connectPortValveRect;
395 		valveRectDescriptor->deactivate = NULL;
396 		valveRectDescriptor->instantiate = instantiateValveRect;
397 		valveRectDescriptor->run = runValveRect;
398 		valveRectDescriptor->run_adding = runAddingValveRect;
399 		valveRectDescriptor->set_run_adding_gain = setRunAddingGainValveRect;
400 	}
401 }
402 
swh_fini()403 static void __attribute__((destructor)) swh_fini() {
404 	if (valveRectDescriptor) {
405 		free((LADSPA_PortDescriptor *)valveRectDescriptor->PortDescriptors);
406 		free((char **)valveRectDescriptor->PortNames);
407 		free((LADSPA_PortRangeHint *)valveRectDescriptor->PortRangeHints);
408 		free(valveRectDescriptor);
409 	}
410 	valveRectDescriptor = NULL;
411 
412 }
413