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_sigmoid.c,v 1.3 2005/08/30 11:19:14 tszilagyi Exp $
19 */
20 
21 
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <math.h>
26 
27 #include "ladspa.h"
28 #include "tap_utils.h"
29 
30 
31 /* The Unique ID of the plugin: */
32 
33 #define ID_MONO         2157
34 
35 /* The port numbers for the plugin: */
36 
37 #define PREGAIN         0
38 #define POSTGAIN        1
39 #define INPUT           2
40 #define OUTPUT          3
41 
42 /* Total number of ports */
43 #define PORTCOUNT_MONO   4
44 
45 
46 /* The closer this is to 1.0, the slower the input parameter
47    interpolation will be. */
48 #define INTERP 0.99f
49 
50 
51 /* The structure used to hold port connection information and state */
52 
53 typedef struct {
54 	LADSPA_Data * pregain;
55 	LADSPA_Data * postgain;
56 	LADSPA_Data * input;
57 	LADSPA_Data * output;
58 
59 	LADSPA_Data pregain_i;
60 	LADSPA_Data postgain_i;
61 
62 	unsigned long sample_rate;
63 	LADSPA_Data run_adding_gain;
64 } Sigmoid;
65 
66 
67 /* Construct a new plugin instance. */
68 LADSPA_Handle
instantiate_Sigmoid(const LADSPA_Descriptor * Descriptor,unsigned long sample_rate)69 instantiate_Sigmoid(const LADSPA_Descriptor * Descriptor,
70 		    unsigned long             sample_rate) {
71 
72         LADSPA_Handle * ptr;
73 
74 	if ((ptr = malloc(sizeof(Sigmoid))) != NULL) {
75 		((Sigmoid *)ptr)->sample_rate = sample_rate;
76 		((Sigmoid *)ptr)->run_adding_gain = 1.0f;
77 
78 		return ptr;
79 	}
80        	return NULL;
81 }
82 
83 
84 /* Connect a port to a data location. */
85 void
connect_port_Sigmoid(LADSPA_Handle Instance,unsigned long Port,LADSPA_Data * DataLocation)86 connect_port_Sigmoid(LADSPA_Handle Instance,
87 		       unsigned long Port,
88 		       LADSPA_Data * DataLocation) {
89 
90 	Sigmoid * ptr = (Sigmoid *)Instance;
91 
92 	switch (Port) {
93 	case PREGAIN:
94 		ptr->pregain = DataLocation;
95 		ptr->pregain_i = db2lin(LIMIT(*DataLocation,-90.0f,20.0f));
96 		break;
97 	case POSTGAIN:
98 		ptr->postgain = DataLocation;
99 		ptr->postgain_i = db2lin(LIMIT(*DataLocation,-90.0f,20.0f));
100 		break;
101 	case INPUT:
102 		ptr->input = DataLocation;
103 		break;
104 	case OUTPUT:
105 		ptr->output = DataLocation;
106 		break;
107 	}
108 }
109 
110 
111 void
run_Sigmoid(LADSPA_Handle Instance,unsigned long SampleCount)112 run_Sigmoid(LADSPA_Handle Instance,
113 	    unsigned long SampleCount) {
114 
115 	Sigmoid * ptr = (Sigmoid *)Instance;
116 	LADSPA_Data * input = ptr->input;
117 	LADSPA_Data * output = ptr->output;
118 	LADSPA_Data pregain = db2lin(LIMIT(*(ptr->pregain),-90.0f,20.0f));
119 	LADSPA_Data postgain = db2lin(LIMIT(*(ptr->postgain),-90.0f,20.0f));
120 	LADSPA_Data pregain_i = ptr->pregain_i;
121 	LADSPA_Data postgain_i = ptr->postgain_i;
122 
123 	unsigned long sample_index;
124 	unsigned long sample_count = SampleCount;
125 
126 	LADSPA_Data in = 0.0f;
127 	LADSPA_Data out = 0.0f;
128 
129 	if ((pregain_i != pregain) || (postgain_i != postgain))	{
130 
131 		for (sample_index = 0; sample_index < sample_count; sample_index++) {
132 
133 			pregain_i = pregain_i * INTERP + pregain * (1.0f - INTERP);
134 			postgain_i = postgain_i * INTERP + postgain * (1.0f - INTERP);
135 
136 			in = *(input++) * pregain_i;
137 
138 			out = 2.0f / (1.0f + exp(-5.0*in)) - 1.0f;
139 
140 			*(output++) = out * postgain_i;
141 		}
142 
143 		ptr->pregain_i = pregain_i;
144 		ptr->postgain_i = postgain_i;
145 
146 	} else {
147 		for (sample_index = 0; sample_index < sample_count; sample_index++) {
148 
149 			in = *(input++) * pregain_i;
150 
151 			out = 2.0f / (1.0f + exp(-5.0*in)) - 1.0f;
152 
153 			*(output++) = out * postgain_i;
154 		}
155 
156 		ptr->pregain_i = pregain_i;
157 		ptr->postgain_i = postgain_i;
158 	}
159 }
160 
161 
162 void
set_run_adding_gain_Sigmoid(LADSPA_Handle Instance,LADSPA_Data gain)163 set_run_adding_gain_Sigmoid(LADSPA_Handle Instance, LADSPA_Data gain) {
164 
165 	Sigmoid * ptr = (Sigmoid *)Instance;
166 
167 	ptr->run_adding_gain = gain;
168 }
169 
170 
171 void
run_adding_Sigmoid(LADSPA_Handle Instance,unsigned long SampleCount)172 run_adding_Sigmoid(LADSPA_Handle Instance,
173 		   unsigned long SampleCount) {
174 
175 	Sigmoid * ptr = (Sigmoid *)Instance;
176 	LADSPA_Data * input = ptr->input;
177 	LADSPA_Data * output = ptr->output;
178 	LADSPA_Data pregain = db2lin(LIMIT(*(ptr->pregain),-90.0f,20.0f));
179 	LADSPA_Data postgain = db2lin(LIMIT(*(ptr->postgain),-90.0f,20.0f));
180 	LADSPA_Data pregain_i = ptr->pregain_i;
181 	LADSPA_Data postgain_i = ptr->postgain_i;
182 
183 	unsigned long sample_index;
184 	unsigned long sample_count = SampleCount;
185 
186 	LADSPA_Data in = 0.0f;
187 	LADSPA_Data out = 0.0f;
188 
189 
190 	if ((pregain_i != pregain) || (postgain_i != postgain))	{
191 
192 		for (sample_index = 0; sample_index < sample_count; sample_index++) {
193 
194 			pregain_i = pregain_i * INTERP + pregain * (1.0f - INTERP);
195 			postgain_i = postgain_i * INTERP + postgain * (1.0f - INTERP);
196 
197 			in = *(input++) * pregain_i;
198 
199 			out = 2.0f / (1.0f + exp(-5.0*in)) - 1.0f;
200 
201 			*(output++) = out * postgain_i * ptr->run_adding_gain;
202 		}
203 
204 		ptr->pregain_i = pregain_i;
205 		ptr->postgain_i = postgain_i;
206 
207 	} else {
208 		for (sample_index = 0; sample_index < sample_count; sample_index++) {
209 
210 			in = *(input++) * pregain_i;
211 
212 			out = 2.0f / (1.0f + exp(-5.0*in)) - 1.0f;
213 
214 			*(output++) = out * postgain_i * ptr->run_adding_gain;
215 		}
216 	}
217 }
218 
219 
220 /* Throw away a Sigmoid effect instance. */
221 void
cleanup_Sigmoid(LADSPA_Handle Instance)222 cleanup_Sigmoid(LADSPA_Handle Instance) {
223 
224 	free(Instance);
225 }
226 
227 
228 LADSPA_Descriptor * mono_descriptor = NULL;
229 
230 
231 /* _init() is called automatically when the plugin library is first
232    loaded. */
233 void
_init()234 _init() {
235 
236 	char ** port_names;
237 	LADSPA_PortDescriptor * port_descriptors;
238 	LADSPA_PortRangeHint * port_range_hints;
239 
240 	if ((mono_descriptor =
241 	     (LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor))) == NULL)
242 		exit(1);
243 
244 
245 	mono_descriptor->UniqueID = ID_MONO;
246 	mono_descriptor->Label = strdup("tap_sigmoid");
247 	mono_descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE;
248 	mono_descriptor->Name = strdup("TAP Sigmoid Booster");
249 	mono_descriptor->Maker = strdup("Tom Szilagyi");
250 	mono_descriptor->Copyright = strdup("GPL");
251 	mono_descriptor->PortCount = PORTCOUNT_MONO;
252 
253 	if ((port_descriptors =
254 	     (LADSPA_PortDescriptor *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortDescriptor))) == NULL)
255 		exit(1);
256 
257 	mono_descriptor->PortDescriptors = (const LADSPA_PortDescriptor *)port_descriptors;
258 	port_descriptors[PREGAIN] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
259 	port_descriptors[POSTGAIN] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
260 	port_descriptors[INPUT] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
261 	port_descriptors[OUTPUT] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
262 
263 	if ((port_names =
264 	     (char **)calloc(PORTCOUNT_MONO, sizeof(char *))) == NULL)
265 		exit(1);
266 
267 	mono_descriptor->PortNames = (const char **)port_names;
268 	port_names[PREGAIN] = strdup("Pre Gain [dB]");
269 	port_names[POSTGAIN] = strdup("Post Gain [dB]");
270 	port_names[INPUT] = strdup("Input");
271 	port_names[OUTPUT] = strdup("Output");
272 
273 	if ((port_range_hints =
274 	     ((LADSPA_PortRangeHint *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortRangeHint)))) == NULL)
275 		exit(1);
276 
277 	mono_descriptor->PortRangeHints	= (const LADSPA_PortRangeHint *)port_range_hints;
278 	port_range_hints[PREGAIN].HintDescriptor =
279 		(LADSPA_HINT_BOUNDED_BELOW |
280 		 LADSPA_HINT_BOUNDED_ABOVE |
281 		 LADSPA_HINT_DEFAULT_0);
282 	port_range_hints[POSTGAIN].HintDescriptor =
283 		(LADSPA_HINT_BOUNDED_BELOW |
284 		 LADSPA_HINT_BOUNDED_ABOVE |
285 		 LADSPA_HINT_DEFAULT_0);
286 	port_range_hints[PREGAIN].LowerBound = -90.0f;
287 	port_range_hints[PREGAIN].UpperBound = 20.0f;
288 	port_range_hints[POSTGAIN].LowerBound = -90.0f;
289 	port_range_hints[POSTGAIN].UpperBound = 20.0f;
290 	port_range_hints[INPUT].HintDescriptor = 0;
291 	port_range_hints[OUTPUT].HintDescriptor = 0;
292 	mono_descriptor->instantiate = instantiate_Sigmoid;
293 	mono_descriptor->connect_port = connect_port_Sigmoid;
294 	mono_descriptor->activate = NULL;
295 	mono_descriptor->run = run_Sigmoid;
296 	mono_descriptor->run_adding = run_adding_Sigmoid;
297 	mono_descriptor->set_run_adding_gain = set_run_adding_gain_Sigmoid;
298 	mono_descriptor->deactivate = NULL;
299 	mono_descriptor->cleanup = cleanup_Sigmoid;
300 }
301 
302 
303 void
delete_descriptor(LADSPA_Descriptor * descriptor)304 delete_descriptor(LADSPA_Descriptor * descriptor) {
305 	unsigned long index;
306 	if (descriptor) {
307 		free((char *)descriptor->Label);
308 		free((char *)descriptor->Name);
309 		free((char *)descriptor->Maker);
310 		free((char *)descriptor->Copyright);
311 		free((LADSPA_PortDescriptor *)descriptor->PortDescriptors);
312 		for (index = 0; index < descriptor->PortCount; index++)
313 			free((char *)(descriptor->PortNames[index]));
314 		free((char **)descriptor->PortNames);
315 		free((LADSPA_PortRangeHint *)descriptor->PortRangeHints);
316 		free(descriptor);
317 	}
318 }
319 
320 
321 /* _fini() is called automatically when the library is unloaded. */
322 void
_fini()323 _fini() {
324 	delete_descriptor(mono_descriptor);
325 }
326 
327 
328 /* Return a descriptor of the requested plugin type. */
329 const LADSPA_Descriptor *
ladspa_descriptor(unsigned long Index)330 ladspa_descriptor(unsigned long Index) {
331 
332 	switch (Index) {
333 	case 0:
334 		return mono_descriptor;
335 	default:
336 		return NULL;
337 	}
338 }
339