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_tremolo.c,v 1.6 2004/02/21 17:33:36 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 /* The Unique ID of the plugin: */
31
32 #define ID_MONO 2144
33
34 /* The port numbers for the plugin: */
35
36 #define CONTROL_FREQ 0
37 #define CONTROL_DEPTH 1
38 #define CONTROL_GAIN 2
39 #define INPUT_0 3
40 #define OUTPUT_0 4
41
42
43 /* Total number of ports */
44
45 #define PORTCOUNT_MONO 5
46
47
48 /* cosine table for fast computations */
49 LADSPA_Data cos_table[1024];
50
51
52 /* The structure used to hold port connection information and state */
53
54 typedef struct {
55 LADSPA_Data * Control_Freq;
56 LADSPA_Data * Control_Depth;
57 LADSPA_Data * Control_Gain;
58 LADSPA_Data * InputBuffer_1;
59 LADSPA_Data * OutputBuffer_1;
60 unsigned long SampleRate;
61 LADSPA_Data Phase;
62 LADSPA_Data run_adding_gain;
63 } Tremolo;
64
65
66
67 /* Construct a new plugin instance. */
68 LADSPA_Handle
instantiate_Tremolo(const LADSPA_Descriptor * Descriptor,unsigned long SampleRate)69 instantiate_Tremolo(const LADSPA_Descriptor * Descriptor,
70 unsigned long SampleRate) {
71
72 LADSPA_Handle * ptr;
73
74 if ((ptr = malloc(sizeof(Tremolo))) != NULL) {
75 ((Tremolo *)ptr)->SampleRate = SampleRate;
76 ((Tremolo *)ptr)->run_adding_gain = 1.0;
77 return ptr;
78 }
79
80 return NULL;
81 }
82
83 void
activate_Tremolo(LADSPA_Handle Instance)84 activate_Tremolo(LADSPA_Handle Instance) {
85
86 Tremolo * ptr;
87
88 ptr = (Tremolo *)Instance;
89 ptr->Phase = 0.0f;
90 }
91
92
93
94 /* Connect a port to a data location. */
95 void
connect_port_Tremolo(LADSPA_Handle Instance,unsigned long Port,LADSPA_Data * DataLocation)96 connect_port_Tremolo(LADSPA_Handle Instance,
97 unsigned long Port,
98 LADSPA_Data * DataLocation) {
99
100 Tremolo * ptr;
101
102 ptr = (Tremolo *)Instance;
103 switch (Port) {
104 case CONTROL_FREQ:
105 ptr->Control_Freq = DataLocation;
106 break;
107 case CONTROL_DEPTH:
108 ptr->Control_Depth = DataLocation;
109 break;
110 case CONTROL_GAIN:
111 ptr->Control_Gain = DataLocation;
112 break;
113 case INPUT_0:
114 ptr->InputBuffer_1 = DataLocation;
115 break;
116 case OUTPUT_0:
117 ptr->OutputBuffer_1 = DataLocation;
118 break;
119 }
120 }
121
122
123
124 void
run_Tremolo(LADSPA_Handle Instance,unsigned long SampleCount)125 run_Tremolo(LADSPA_Handle Instance,
126 unsigned long SampleCount) {
127
128 LADSPA_Data * input;
129 LADSPA_Data * output;
130 LADSPA_Data freq;
131 LADSPA_Data depth;
132 LADSPA_Data gain;
133 Tremolo * ptr;
134 unsigned long sample_index;
135 LADSPA_Data phase = 0.0f;
136
137 ptr = (Tremolo *)Instance;
138
139 input = ptr->InputBuffer_1;
140 output = ptr->OutputBuffer_1;
141 freq = LIMIT(*(ptr->Control_Freq),0.0f,20.0f);
142 depth = LIMIT(*(ptr->Control_Depth),0.0f,100.0f);
143 gain = db2lin(LIMIT(*(ptr->Control_Gain),-70.0f,20.0f));
144
145 for (sample_index = 0; sample_index < SampleCount; sample_index++) {
146 phase = 1024.0f * freq * sample_index / ptr->SampleRate + ptr->Phase;
147
148 while (phase >= 1024.0f)
149 phase -= 1024.0f;
150
151 *(output++) = *(input++) * gain *
152 (1 - 0.5*depth/100 + 0.5 * depth/100 * cos_table[(unsigned long) phase]);
153 }
154 ptr->Phase = phase;
155 while (ptr->Phase >= 1024.0f)
156 ptr->Phase -= 1024.0f;
157 }
158
159
160
161 void
set_run_adding_gain_Tremolo(LADSPA_Handle Instance,LADSPA_Data gain)162 set_run_adding_gain_Tremolo(LADSPA_Handle Instance, LADSPA_Data gain) {
163
164 Tremolo * ptr;
165
166 ptr = (Tremolo *)Instance;
167
168 ptr->run_adding_gain = gain;
169 }
170
171
172
173 void
run_adding_Tremolo(LADSPA_Handle Instance,unsigned long SampleCount)174 run_adding_Tremolo(LADSPA_Handle Instance,
175 unsigned long SampleCount) {
176
177 LADSPA_Data * input;
178 LADSPA_Data * output;
179 LADSPA_Data freq;
180 LADSPA_Data depth;
181 LADSPA_Data gain;
182 Tremolo * ptr;
183 unsigned long sample_index;
184 LADSPA_Data phase = 0.0f;
185
186 ptr = (Tremolo *)Instance;
187
188 input = ptr->InputBuffer_1;
189 output = ptr->OutputBuffer_1;
190 freq = LIMIT(*(ptr->Control_Freq),0.0f,20.0f);
191 depth = LIMIT(*(ptr->Control_Depth),0.0f,100.0f);
192 gain = db2lin(LIMIT(*(ptr->Control_Gain),-70.0f,20.0f));
193
194 for (sample_index = 0; sample_index < SampleCount; sample_index++) {
195 phase = 1024.0f * freq * sample_index / ptr->SampleRate + ptr->Phase;
196
197 while (phase >= 1024.0f)
198 phase -= 1024.0f;
199
200 *(output++) += *(input++) * ptr->run_adding_gain * gain *
201 (1 - 0.5*depth/100 + 0.5 * depth/100 * cos_table[(unsigned long) phase]);
202 }
203 ptr->Phase = phase;
204 while (ptr->Phase >= 1024.0f)
205 ptr->Phase -= 1024.0f;
206 }
207
208
209
210
211 /* Throw away a Tremolo effect instance. */
212 void
cleanup_Tremolo(LADSPA_Handle Instance)213 cleanup_Tremolo(LADSPA_Handle Instance) {
214 free(Instance);
215 }
216
217
218
219 LADSPA_Descriptor * mono_descriptor = NULL;
220
221
222
223 /* _init() is called automatically when the plugin library is first
224 loaded. */
225 void
_init()226 _init() {
227
228 char ** port_names;
229 LADSPA_PortDescriptor * port_descriptors;
230 LADSPA_PortRangeHint * port_range_hints;
231 int i;
232
233 if ((mono_descriptor =
234 (LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor))) == NULL)
235 exit(1);
236
237
238 for (i = 0; i < 1024; i++)
239 cos_table[i] = cosf(i * M_PI / 512.0f);
240
241
242 mono_descriptor->UniqueID = ID_MONO;
243 mono_descriptor->Label = strdup("tap_tremolo");
244 mono_descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE;
245 mono_descriptor->Name = strdup("TAP Tremolo");
246 mono_descriptor->Maker = strdup("Tom Szilagyi");
247 mono_descriptor->Copyright = strdup("GPL");
248 mono_descriptor->PortCount = PORTCOUNT_MONO;
249
250 if ((port_descriptors =
251 (LADSPA_PortDescriptor *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortDescriptor))) == NULL)
252 exit(1);
253
254 mono_descriptor->PortDescriptors = (const LADSPA_PortDescriptor *)port_descriptors;
255 port_descriptors[CONTROL_FREQ] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
256 port_descriptors[CONTROL_DEPTH] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
257 port_descriptors[CONTROL_GAIN] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
258 port_descriptors[INPUT_0] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
259 port_descriptors[OUTPUT_0] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
260
261 if ((port_names =
262 (char **)calloc(PORTCOUNT_MONO, sizeof(char *))) == NULL)
263 exit(1);
264
265 mono_descriptor->PortNames = (const char **)port_names;
266 port_names[CONTROL_FREQ] = strdup("Frequency [Hz]");
267 port_names[CONTROL_DEPTH] = strdup("Depth [%]");
268 port_names[CONTROL_GAIN] = strdup("Gain [dB]");
269 port_names[INPUT_0] = strdup("Input_0");
270 port_names[OUTPUT_0] = strdup("Output_0");
271
272 if ((port_range_hints =
273 ((LADSPA_PortRangeHint *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortRangeHint)))) == NULL)
274 exit(1);
275
276 mono_descriptor->PortRangeHints = (const LADSPA_PortRangeHint *)port_range_hints;
277 port_range_hints[CONTROL_FREQ].HintDescriptor =
278 (LADSPA_HINT_BOUNDED_BELOW |
279 LADSPA_HINT_BOUNDED_ABOVE |
280 LADSPA_HINT_DEFAULT_0);
281 port_range_hints[CONTROL_DEPTH].HintDescriptor =
282 (LADSPA_HINT_BOUNDED_BELOW |
283 LADSPA_HINT_BOUNDED_ABOVE |
284 LADSPA_HINT_DEFAULT_0);
285 port_range_hints[CONTROL_GAIN].HintDescriptor =
286 (LADSPA_HINT_BOUNDED_BELOW |
287 LADSPA_HINT_BOUNDED_ABOVE |
288 LADSPA_HINT_DEFAULT_0);
289 port_range_hints[CONTROL_FREQ].LowerBound = 0;
290 port_range_hints[CONTROL_FREQ].UpperBound = 20;
291 port_range_hints[CONTROL_DEPTH].LowerBound = 0;
292 port_range_hints[CONTROL_DEPTH].UpperBound = 100;
293 port_range_hints[CONTROL_GAIN].LowerBound = -70;
294 port_range_hints[CONTROL_GAIN].UpperBound = 20;
295 port_range_hints[INPUT_0].HintDescriptor = 0;
296 port_range_hints[OUTPUT_0].HintDescriptor = 0;
297 mono_descriptor->instantiate = instantiate_Tremolo;
298 mono_descriptor->connect_port = connect_port_Tremolo;
299 mono_descriptor->activate = activate_Tremolo;
300 mono_descriptor->run = run_Tremolo;
301 mono_descriptor->run_adding = run_adding_Tremolo;
302 mono_descriptor->set_run_adding_gain = set_run_adding_gain_Tremolo;
303 mono_descriptor->deactivate = NULL;
304 mono_descriptor->cleanup = cleanup_Tremolo;
305 }
306
307
308 void
delete_descriptor(LADSPA_Descriptor * descriptor)309 delete_descriptor(LADSPA_Descriptor * descriptor) {
310 unsigned long index;
311 if (descriptor) {
312 free((char *)descriptor->Label);
313 free((char *)descriptor->Name);
314 free((char *)descriptor->Maker);
315 free((char *)descriptor->Copyright);
316 free((LADSPA_PortDescriptor *)descriptor->PortDescriptors);
317 for (index = 0; index < descriptor->PortCount; index++)
318 free((char *)(descriptor->PortNames[index]));
319 free((char **)descriptor->PortNames);
320 free((LADSPA_PortRangeHint *)descriptor->PortRangeHints);
321 free(descriptor);
322 }
323 }
324
325
326 /* _fini() is called automatically when the library is unloaded. */
327 void
_fini()328 _fini() {
329 delete_descriptor(mono_descriptor);
330 }
331
332
333 /* Return a descriptor of the requested plugin type. */
334 const LADSPA_Descriptor *
ladspa_descriptor(unsigned long Index)335 ladspa_descriptor(unsigned long Index) {
336
337 switch (Index) {
338 case 0:
339 return mono_descriptor;
340 default:
341 return NULL;
342 }
343 }
344