1 /* amp.c
2 
3    Free software by Richard W.E. Furse. Do with as you will. No
4    warranty.
5 
6    This LADSPA plugin provides simple mono and stereo amplifiers.
7 
8    This file has poor memory protection. Failures during malloc() will
9    not recover nicely. */
10 
11 /*****************************************************************************/
12 
13 #include <stdlib.h>
14 #include <string.h>
15 
16 /*****************************************************************************/
17 
18 #include "ladspa.h"
19 #include "utils.h"
20 
21 /*****************************************************************************/
22 
23 /* The port numbers for the plugin: */
24 
25 #define AMP_CONTROL 0
26 #define AMP_INPUT1  1
27 #define AMP_OUTPUT1 2
28 #define AMP_INPUT2  3
29 #define AMP_OUTPUT2 4
30 
31 /*****************************************************************************/
32 
33 /* The structure used to hold port connection information and state
34    (actually gain controls require no further state). */
35 
36 typedef struct {
37 
38   /* Ports:
39      ------ */
40 
41   LADSPA_Data * m_pfControlValue;
42   LADSPA_Data * m_pfInputBuffer1;
43   LADSPA_Data * m_pfOutputBuffer1;
44   LADSPA_Data * m_pfInputBuffer2;  /* (Not used for mono) */
45   LADSPA_Data * m_pfOutputBuffer2; /* (Not used for mono) */
46 
47 } Amplifier;
48 
49 /*****************************************************************************/
50 
51 /* Construct a new plugin instance. */
52 static LADSPA_Handle
instantiateAmplifier(const LADSPA_Descriptor * Descriptor,unsigned long SampleRate)53 instantiateAmplifier(const LADSPA_Descriptor * Descriptor,
54 		     unsigned long             SampleRate) {
55   return malloc(sizeof(Amplifier));
56 }
57 
58 /*****************************************************************************/
59 
60 /* Connect a port to a data location. */
61 static void
connectPortToAmplifier(LADSPA_Handle Instance,unsigned long Port,LADSPA_Data * DataLocation)62 connectPortToAmplifier(LADSPA_Handle Instance,
63 		       unsigned long Port,
64 		       LADSPA_Data * DataLocation) {
65 
66   Amplifier * psAmplifier;
67 
68   psAmplifier = (Amplifier *)Instance;
69   switch (Port) {
70   case AMP_CONTROL:
71     psAmplifier->m_pfControlValue = DataLocation;
72     break;
73   case AMP_INPUT1:
74     psAmplifier->m_pfInputBuffer1 = DataLocation;
75     break;
76   case AMP_OUTPUT1:
77     psAmplifier->m_pfOutputBuffer1 = DataLocation;
78     break;
79   case AMP_INPUT2:
80     /* (This should only happen for stereo.) */
81     psAmplifier->m_pfInputBuffer2 = DataLocation;
82     break;
83   case AMP_OUTPUT2:
84     /* (This should only happen for stereo.) */
85     psAmplifier->m_pfOutputBuffer2 = DataLocation;
86     break;
87   }
88 }
89 
90 /*****************************************************************************/
91 
92 static void
runMonoAmplifier(LADSPA_Handle Instance,unsigned long SampleCount)93 runMonoAmplifier(LADSPA_Handle Instance,
94 		 unsigned long SampleCount) {
95 
96   LADSPA_Data * pfInput;
97   LADSPA_Data * pfOutput;
98   LADSPA_Data fGain;
99   Amplifier * psAmplifier;
100   unsigned long lSampleIndex;
101 
102   psAmplifier = (Amplifier *)Instance;
103 
104   pfInput = psAmplifier->m_pfInputBuffer1;
105   pfOutput = psAmplifier->m_pfOutputBuffer1;
106   fGain = *(psAmplifier->m_pfControlValue);
107 
108   for (lSampleIndex = 0; lSampleIndex < SampleCount; lSampleIndex++)
109     *(pfOutput++) = *(pfInput++) * fGain;
110 }
111 
112 /*****************************************************************************/
113 
114 static void
runStereoAmplifier(LADSPA_Handle Instance,unsigned long SampleCount)115 runStereoAmplifier(LADSPA_Handle Instance,
116 		   unsigned long SampleCount) {
117 
118   LADSPA_Data * pfInput;
119   LADSPA_Data * pfOutput;
120   LADSPA_Data fGain;
121   Amplifier * psAmplifier;
122   unsigned long lSampleIndex;
123 
124   psAmplifier = (Amplifier *)Instance;
125 
126   fGain = *(psAmplifier->m_pfControlValue);
127 
128   pfInput = psAmplifier->m_pfInputBuffer1;
129   pfOutput = psAmplifier->m_pfOutputBuffer1;
130   for (lSampleIndex = 0; lSampleIndex < SampleCount; lSampleIndex++)
131     *(pfOutput++) = *(pfInput++) * fGain;
132 
133   pfInput = psAmplifier->m_pfInputBuffer2;
134   pfOutput = psAmplifier->m_pfOutputBuffer2;
135   for (lSampleIndex = 0; lSampleIndex < SampleCount; lSampleIndex++)
136     *(pfOutput++) = *(pfInput++) * fGain;
137 }
138 
139 /*****************************************************************************/
140 
141 /* Throw away an amplifier. */
142 static void
cleanupAmplifier(LADSPA_Handle Instance)143 cleanupAmplifier(LADSPA_Handle Instance) {
144   free(Instance);
145 }
146 
147 /*****************************************************************************/
148 
149 LADSPA_Descriptor * g_psMonoDescriptor = NULL;
150 LADSPA_Descriptor * g_psStereoDescriptor = NULL;
151 
152 /*****************************************************************************/
153 
154 /* Called automatically when the plugin library is first loaded. */
155 ON_LOAD_ROUTINE {
156 
157   char ** pcPortNames;
158   LADSPA_PortDescriptor * piPortDescriptors;
159   LADSPA_PortRangeHint * psPortRangeHints;
160 
161   g_psMonoDescriptor
162     = (LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor));
163   g_psStereoDescriptor
164     = (LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor));
165 
166   if (g_psMonoDescriptor) {
167 
168     g_psMonoDescriptor->UniqueID
169       = 1048;
170     g_psMonoDescriptor->Label
171       = strdup("amp_mono");
172     g_psMonoDescriptor->Properties
173       = LADSPA_PROPERTY_HARD_RT_CAPABLE;
174     g_psMonoDescriptor->Name
175       = strdup("Mono Amplifier");
176     g_psMonoDescriptor->Maker
177       = strdup("Richard Furse (LADSPA example plugins)");
178     g_psMonoDescriptor->Copyright
179       = strdup("None");
180     g_psMonoDescriptor->PortCount
181       = 3;
182     piPortDescriptors
183       = (LADSPA_PortDescriptor *)calloc(3, sizeof(LADSPA_PortDescriptor));
184     g_psMonoDescriptor->PortDescriptors
185       = (const LADSPA_PortDescriptor *)piPortDescriptors;
186     piPortDescriptors[AMP_CONTROL]
187       = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
188     piPortDescriptors[AMP_INPUT1]
189       = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
190     piPortDescriptors[AMP_OUTPUT1]
191       = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
192     pcPortNames
193       = (char **)calloc(3, sizeof(char *));
194     g_psMonoDescriptor->PortNames
195       = (const char **)pcPortNames;
196     pcPortNames[AMP_CONTROL]
197       = strdup("Gain");
198     pcPortNames[AMP_INPUT1]
199       = strdup("Input");
200     pcPortNames[AMP_OUTPUT1]
201       = strdup("Output");
202     psPortRangeHints = ((LADSPA_PortRangeHint *)
203 			calloc(3, sizeof(LADSPA_PortRangeHint)));
204     g_psMonoDescriptor->PortRangeHints
205       = (const LADSPA_PortRangeHint *)psPortRangeHints;
206     psPortRangeHints[AMP_CONTROL].HintDescriptor
207       = (LADSPA_HINT_BOUNDED_BELOW
208 	 | LADSPA_HINT_LOGARITHMIC
209 	 | LADSPA_HINT_DEFAULT_1);
210     psPortRangeHints[AMP_CONTROL].LowerBound
211       = 0;
212     psPortRangeHints[AMP_INPUT1].HintDescriptor
213       = 0;
214     psPortRangeHints[AMP_OUTPUT1].HintDescriptor
215       = 0;
216     g_psMonoDescriptor->instantiate
217       = instantiateAmplifier;
218     g_psMonoDescriptor->connect_port
219       = connectPortToAmplifier;
220     g_psMonoDescriptor->activate
221       = NULL;
222     g_psMonoDescriptor->run
223       = runMonoAmplifier;
224     g_psMonoDescriptor->run_adding
225       = NULL;
226     g_psMonoDescriptor->set_run_adding_gain
227       = NULL;
228     g_psMonoDescriptor->deactivate
229       = NULL;
230     g_psMonoDescriptor->cleanup
231       = cleanupAmplifier;
232   }
233 
234   if (g_psStereoDescriptor) {
235 
236     g_psStereoDescriptor->UniqueID
237       = 1049;
238     g_psStereoDescriptor->Label
239       = strdup("amp_stereo");
240     g_psStereoDescriptor->Properties
241       = LADSPA_PROPERTY_HARD_RT_CAPABLE;
242     g_psStereoDescriptor->Name
243       = strdup("Stereo Amplifier");
244     g_psStereoDescriptor->Maker
245       = strdup("Richard Furse (LADSPA example plugins)");
246     g_psStereoDescriptor->Copyright
247       = strdup("None");
248     g_psStereoDescriptor->PortCount
249       = 5;
250     piPortDescriptors
251       = (LADSPA_PortDescriptor *)calloc(5, sizeof(LADSPA_PortDescriptor));
252     g_psStereoDescriptor->PortDescriptors
253       = (const LADSPA_PortDescriptor *)piPortDescriptors;
254     piPortDescriptors[AMP_CONTROL]
255       = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
256     piPortDescriptors[AMP_INPUT1]
257       = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
258     piPortDescriptors[AMP_OUTPUT1]
259       = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
260     piPortDescriptors[AMP_INPUT2]
261       = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
262     piPortDescriptors[AMP_OUTPUT2]
263       = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
264     pcPortNames
265       = (char **)calloc(5, sizeof(char *));
266     g_psStereoDescriptor->PortNames
267       = (const char **)pcPortNames;
268     pcPortNames[AMP_CONTROL]
269       = strdup("Gain");
270     pcPortNames[AMP_INPUT1]
271       = strdup("Input (Left)");
272     pcPortNames[AMP_OUTPUT1]
273       = strdup("Output (Left)");
274     pcPortNames[AMP_INPUT2]
275       = strdup("Input (Right)");
276     pcPortNames[AMP_OUTPUT2]
277       = strdup("Output (Right)");
278     psPortRangeHints = ((LADSPA_PortRangeHint *)
279 			calloc(5, sizeof(LADSPA_PortRangeHint)));
280     g_psStereoDescriptor->PortRangeHints
281       = (const LADSPA_PortRangeHint *)psPortRangeHints;
282     psPortRangeHints[AMP_CONTROL].HintDescriptor
283       = (LADSPA_HINT_BOUNDED_BELOW
284 	 | LADSPA_HINT_LOGARITHMIC
285 	 | LADSPA_HINT_DEFAULT_1);
286     psPortRangeHints[AMP_CONTROL].LowerBound
287       = 0;
288     psPortRangeHints[AMP_INPUT1].HintDescriptor
289       = 0;
290     psPortRangeHints[AMP_OUTPUT1].HintDescriptor
291       = 0;
292     psPortRangeHints[AMP_INPUT2].HintDescriptor
293       = 0;
294     psPortRangeHints[AMP_OUTPUT2].HintDescriptor
295       = 0;
296     g_psStereoDescriptor->instantiate
297       = instantiateAmplifier;
298     g_psStereoDescriptor->connect_port
299       = connectPortToAmplifier;
300     g_psStereoDescriptor->activate
301       = NULL;
302     g_psStereoDescriptor->run
303       = runStereoAmplifier;
304     g_psStereoDescriptor->run_adding
305       = NULL;
306     g_psStereoDescriptor->set_run_adding_gain
307       = NULL;
308     g_psStereoDescriptor->deactivate
309       = NULL;
310     g_psStereoDescriptor->cleanup
311       = cleanupAmplifier;
312   }
313 }
314 
315 /*****************************************************************************/
316 
317 static void
deleteDescriptor(LADSPA_Descriptor * psDescriptor)318 deleteDescriptor(LADSPA_Descriptor * psDescriptor) {
319   unsigned long lIndex;
320   if (psDescriptor) {
321     free((char *)psDescriptor->Label);
322     free((char *)psDescriptor->Name);
323     free((char *)psDescriptor->Maker);
324     free((char *)psDescriptor->Copyright);
325     free((LADSPA_PortDescriptor *)psDescriptor->PortDescriptors);
326     for (lIndex = 0; lIndex < psDescriptor->PortCount; lIndex++)
327       free((char *)(psDescriptor->PortNames[lIndex]));
328     free((char **)psDescriptor->PortNames);
329     free((LADSPA_PortRangeHint *)psDescriptor->PortRangeHints);
330     free(psDescriptor);
331   }
332 }
333 
334 /*****************************************************************************/
335 
336 /* Called automatically when the library is unloaded. */
337 ON_UNLOAD_ROUTINE {
338   deleteDescriptor(g_psMonoDescriptor);
339   deleteDescriptor(g_psStereoDescriptor);
340 }
341 
342 /*****************************************************************************/
343 
344 /* Return a descriptor of the requested plugin type. There are two
345    plugin types available in this library (mono and stereo). */
346 const LADSPA_Descriptor *
ladspa_descriptor(unsigned long Index)347 ladspa_descriptor(unsigned long Index) {
348   /* Return the requested descriptor or null if the index is out of
349      range. */
350   switch (Index) {
351   case 0:
352     return g_psMonoDescriptor;
353   case 1:
354     return g_psStereoDescriptor;
355   default:
356     return NULL;
357   }
358 }
359 
360 /*****************************************************************************/
361 
362 /* EOF */
363