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