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_reflector.c,v 1.1 2004/06/18 20:12:41 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 2154
34
35 /* The port numbers for the plugin: */
36
37 #define FRAGMENT 0
38 #define DRYLEVEL 1
39 #define WETLEVEL 2
40 #define INPUT 3
41 #define OUTPUT 4
42
43 /* Total number of ports */
44
45
46 #define PORTCOUNT_MONO 5
47
48
49 /* minimum & maximum fragment length [ms] */
50 #define MIN_FRAGMENT_LEN 20
51 #define MAX_FRAGMENT_LEN 1600
52
53 /* in kHz */
54 #define MAX_SAMPLE_RATE 192
55
56
57 #define COS_TABLE_SIZE 1024
58 LADSPA_Data cos_table[COS_TABLE_SIZE];
59
60
61
62 /* The structure used to hold port connection information and state */
63
64 typedef struct {
65 LADSPA_Data * fragment;
66 LADSPA_Data * drylevel;
67 LADSPA_Data * wetlevel;
68 LADSPA_Data * input;
69 LADSPA_Data * output;
70
71 LADSPA_Data * ring0;
72 unsigned long buflen0;
73 unsigned long pos0;
74 LADSPA_Data * ring1;
75 unsigned long buflen1;
76 unsigned long pos1;
77 LADSPA_Data * delay1;
78 unsigned long delay_buflen1;
79 unsigned long delay_pos1;
80 LADSPA_Data * ring2;
81 unsigned long buflen2;
82 unsigned long pos2;
83 LADSPA_Data * delay2;
84 unsigned long delay_buflen2;
85 unsigned long delay_pos2;
86
87 unsigned long fragment_pos;
88
89 unsigned long sample_rate;
90 LADSPA_Data run_adding_gain;
91 } Reflector;
92
93
94
95 /* Construct a new plugin instance. */
96 LADSPA_Handle
instantiate_Reflector(const LADSPA_Descriptor * Descriptor,unsigned long sample_rate)97 instantiate_Reflector(const LADSPA_Descriptor * Descriptor,
98 unsigned long sample_rate) {
99
100 LADSPA_Handle * ptr;
101
102 if ((ptr = malloc(sizeof(Reflector))) != NULL) {
103 ((Reflector *)ptr)->sample_rate = sample_rate;
104 ((Reflector *)ptr)->run_adding_gain = 1.0f;
105
106 if ((((Reflector *)ptr)->ring0 =
107 calloc(2 * MAX_FRAGMENT_LEN * MAX_SAMPLE_RATE, sizeof(LADSPA_Data))) == NULL)
108 return NULL;
109 ((Reflector *)ptr)->buflen0 = 2 * MAX_FRAGMENT_LEN * sample_rate / 1000;
110 ((Reflector *)ptr)->pos0 = 0;
111
112 if ((((Reflector *)ptr)->ring1 =
113 calloc(2 * MAX_FRAGMENT_LEN * MAX_SAMPLE_RATE, sizeof(LADSPA_Data))) == NULL)
114 return NULL;
115 ((Reflector *)ptr)->buflen1 = 2 * MAX_FRAGMENT_LEN * sample_rate / 1000;
116 ((Reflector *)ptr)->pos1 = 0;
117
118 if ((((Reflector *)ptr)->delay1 =
119 calloc(2 * MAX_FRAGMENT_LEN * MAX_SAMPLE_RATE, sizeof(LADSPA_Data))) == NULL)
120 return NULL;
121 ((Reflector *)ptr)->delay_buflen1 = 2 * MAX_FRAGMENT_LEN * sample_rate / 3000;
122 ((Reflector *)ptr)->pos1 = 0;
123
124 if ((((Reflector *)ptr)->ring2 =
125 calloc(2 * MAX_FRAGMENT_LEN * MAX_SAMPLE_RATE, sizeof(LADSPA_Data))) == NULL)
126 return NULL;
127 ((Reflector *)ptr)->buflen2 = 2 * MAX_FRAGMENT_LEN * sample_rate / 1000;
128 ((Reflector *)ptr)->pos2 = 0;
129
130 if ((((Reflector *)ptr)->delay2 =
131 calloc(2 * MAX_FRAGMENT_LEN * MAX_SAMPLE_RATE, sizeof(LADSPA_Data))) == NULL)
132 return NULL;
133 ((Reflector *)ptr)->delay_buflen2 = 4 * MAX_FRAGMENT_LEN * sample_rate / 3000;
134 ((Reflector *)ptr)->pos2 = 0;
135
136 return ptr;
137 }
138 return NULL;
139 }
140
141
142 void
activate_Reflector(LADSPA_Handle Instance)143 activate_Reflector(LADSPA_Handle Instance) {
144
145 Reflector * ptr = (Reflector *)Instance;
146 unsigned long i;
147
148 for (i = 0; i < ptr->buflen0; i++)
149 ptr->ring0[i] = 0.0f;
150 ptr->pos0 = 0;
151 for (i = 0; i < ptr->buflen1; i++)
152 ptr->ring1[i] = 0.0f;
153 ptr->pos1 = 0;
154 for (i = 0; i < ptr->buflen2; i++)
155 ptr->ring2[i] = 0.0f;
156 ptr->pos2 = 0;
157
158 for (i = 0; i < ptr->delay_buflen1; i++)
159 ptr->delay1[i] = 0.0f;
160 ptr->delay_pos1 = 0;
161 for (i = 0; i < ptr->delay_buflen2; i++)
162 ptr->delay2[i] = 0.0f;
163 ptr->delay_pos2 = 0;
164
165 ptr->fragment_pos = 0;
166 }
167
168
169
170
171
172 /* Connect a port to a data location. */
173 void
connect_port_Reflector(LADSPA_Handle Instance,unsigned long Port,LADSPA_Data * DataLocation)174 connect_port_Reflector(LADSPA_Handle Instance,
175 unsigned long Port,
176 LADSPA_Data * DataLocation) {
177
178 Reflector * ptr = (Reflector *)Instance;
179
180 switch (Port) {
181 case FRAGMENT:
182 ptr->fragment = DataLocation;
183 break;
184 case DRYLEVEL:
185 ptr->drylevel = DataLocation;
186 break;
187 case WETLEVEL:
188 ptr->wetlevel = DataLocation;
189 break;
190 case INPUT:
191 ptr->input = DataLocation;
192 break;
193 case OUTPUT:
194 ptr->output = DataLocation;
195 break;
196 }
197 }
198
199
200
201 void
run_Reflector(LADSPA_Handle Instance,unsigned long SampleCount)202 run_Reflector(LADSPA_Handle Instance,
203 unsigned long SampleCount) {
204
205 Reflector * ptr = (Reflector *)Instance;
206 LADSPA_Data * input = ptr->input;
207 LADSPA_Data * output = ptr->output;
208 LADSPA_Data drylevel = db2lin(LIMIT(*(ptr->drylevel),-90.0f,20.0f));
209 LADSPA_Data wetlevel = 0.333333f * db2lin(LIMIT(*(ptr->wetlevel),-90.0f,20.0f));
210 LADSPA_Data fragment = LIMIT(*(ptr->fragment),(float)MIN_FRAGMENT_LEN,(float)MAX_FRAGMENT_LEN);
211
212 unsigned long sample_index;
213 unsigned long sample_count = SampleCount;
214
215 LADSPA_Data in = 0.0f;
216 LADSPA_Data in1 = 0.0f;
217 LADSPA_Data in2 = 0.0f;
218 LADSPA_Data out_0 = 0.0f;
219 LADSPA_Data out_1 = 0.0f;
220 LADSPA_Data out_2 = 0.0f;
221
222 unsigned long fragment_pos1 = 0;
223 unsigned long fragment_pos2 = 0;
224
225 unsigned long arg_0 = 0;
226 LADSPA_Data am_0 = 0.0f;
227 unsigned long arg_1 = 0;
228 LADSPA_Data am_1 = 0.0f;
229 unsigned long arg_2 = 0;
230 LADSPA_Data am_2 = 0.0f;
231
232 ptr->buflen0 = 2 * fragment * ptr->sample_rate / 1000.0f;
233 ptr->buflen1 = ptr->buflen0;
234 ptr->buflen2 = ptr->buflen0;
235 ptr->delay_buflen1 = ptr->buflen0 / 3;
236 ptr->delay_buflen2 = 2 * ptr->buflen0 / 3;
237
238 for (sample_index = 0; sample_index < sample_count; sample_index++) {
239
240 in = *(input++);
241 in1 = push_buffer(in, ptr->delay1, ptr->delay_buflen1, &(ptr->delay_pos1));
242 in2 = push_buffer(in, ptr->delay2, ptr->delay_buflen2, &(ptr->delay_pos2));
243
244 push_buffer(in2, ptr->ring0, ptr->buflen0, &(ptr->pos0));
245 push_buffer(in1, ptr->ring1, ptr->buflen1, &(ptr->pos1));
246 push_buffer(in, ptr->ring2, ptr->buflen2, &(ptr->pos2));
247
248 fragment_pos1 = (ptr->fragment_pos + ptr->buflen0 / 3) % ptr->buflen0;
249 fragment_pos2 = (ptr->fragment_pos + 2 * ptr->buflen1 / 3) % ptr->buflen1;
250
251 out_0 = read_buffer(ptr->ring0, ptr->buflen0, ptr->pos0,
252 ptr->buflen0 - ptr->fragment_pos - 1);
253 out_1 = read_buffer(ptr->ring1, ptr->buflen1, ptr->pos1,
254 ptr->buflen1 - fragment_pos1 - 1);
255 out_2 = read_buffer(ptr->ring2, ptr->buflen2, ptr->pos2,
256 ptr->buflen2 - fragment_pos2 - 1);
257
258 ptr->fragment_pos += 2;
259 if (ptr->fragment_pos >= ptr->buflen0)
260 ptr->fragment_pos = 0;
261
262 arg_0 = (float)ptr->fragment_pos / (float)ptr->buflen0 * COS_TABLE_SIZE;
263 am_0 = 1.0f - cos_table[arg_0];
264 arg_1 = (float)fragment_pos1 / (float)ptr->buflen1 * COS_TABLE_SIZE;
265 am_1 = 1.0f - cos_table[arg_1];
266 arg_2 = (float)fragment_pos2 / (float)ptr->buflen2 * COS_TABLE_SIZE;
267 am_2 = 1.0f - cos_table[arg_2];
268
269 *(output++) = drylevel * in + wetlevel *
270 (am_0 * out_0 + am_1 * out_1 + am_2 * out_2);
271 }
272 }
273
274
275
276 void
set_run_adding_gain_Reflector(LADSPA_Handle Instance,LADSPA_Data gain)277 set_run_adding_gain_Reflector(LADSPA_Handle Instance, LADSPA_Data gain) {
278
279 Reflector * ptr = (Reflector *)Instance;
280
281 ptr->run_adding_gain = gain;
282 }
283
284
285
286 void
run_adding_Reflector(LADSPA_Handle Instance,unsigned long SampleCount)287 run_adding_Reflector(LADSPA_Handle Instance,
288 unsigned long SampleCount) {
289
290 Reflector * ptr = (Reflector *)Instance;
291 LADSPA_Data * input = ptr->input;
292 LADSPA_Data * output = ptr->output;
293 LADSPA_Data drylevel = db2lin(LIMIT(*(ptr->drylevel),-90.0f,20.0f));
294 LADSPA_Data wetlevel = 0.333333f * db2lin(LIMIT(*(ptr->wetlevel),-90.0f,20.0f));
295 LADSPA_Data fragment = LIMIT(*(ptr->fragment),(float)MIN_FRAGMENT_LEN,(float)MAX_FRAGMENT_LEN);
296
297 unsigned long sample_index;
298 unsigned long sample_count = SampleCount;
299
300 LADSPA_Data in = 0.0f;
301 LADSPA_Data in1 = 0.0f;
302 LADSPA_Data in2 = 0.0f;
303 LADSPA_Data out_0 = 0.0f;
304 LADSPA_Data out_1 = 0.0f;
305 LADSPA_Data out_2 = 0.0f;
306
307 unsigned long fragment_pos1 = 0;
308 unsigned long fragment_pos2 = 0;
309
310 unsigned long arg_0 = 0;
311 LADSPA_Data am_0 = 0.0f;
312 unsigned long arg_1 = 0;
313 LADSPA_Data am_1 = 0.0f;
314 unsigned long arg_2 = 0;
315 LADSPA_Data am_2 = 0.0f;
316
317 ptr->buflen0 = 2 * fragment * ptr->sample_rate / 1000.0f;
318 ptr->buflen1 = ptr->buflen0;
319 ptr->buflen2 = ptr->buflen0;
320 ptr->delay_buflen1 = ptr->buflen0 / 3;
321 ptr->delay_buflen2 = 2 * ptr->buflen0 / 3;
322
323 for (sample_index = 0; sample_index < sample_count; sample_index++) {
324
325 in = *(input++);
326 in1 = push_buffer(in, ptr->delay1, ptr->delay_buflen1, &(ptr->delay_pos1));
327 in2 = push_buffer(in, ptr->delay2, ptr->delay_buflen2, &(ptr->delay_pos2));
328
329 push_buffer(in2, ptr->ring0, ptr->buflen0, &(ptr->pos0));
330 push_buffer(in1, ptr->ring1, ptr->buflen1, &(ptr->pos1));
331 push_buffer(in, ptr->ring2, ptr->buflen2, &(ptr->pos2));
332
333 fragment_pos1 = (ptr->fragment_pos + ptr->buflen0 / 3) % ptr->buflen0;
334 fragment_pos2 = (ptr->fragment_pos + 2 * ptr->buflen1 / 3) % ptr->buflen1;
335
336 out_0 = read_buffer(ptr->ring0, ptr->buflen0, ptr->pos0,
337 ptr->buflen0 - ptr->fragment_pos - 1);
338 out_1 = read_buffer(ptr->ring1, ptr->buflen1, ptr->pos1,
339 ptr->buflen1 - fragment_pos1 - 1);
340 out_2 = read_buffer(ptr->ring2, ptr->buflen2, ptr->pos2,
341 ptr->buflen2 - fragment_pos2 - 1);
342
343 ptr->fragment_pos += 2;
344 if (ptr->fragment_pos >= ptr->buflen0)
345 ptr->fragment_pos = 0;
346
347 arg_0 = (float)ptr->fragment_pos / (float)ptr->buflen0 * COS_TABLE_SIZE;
348 am_0 = 1.0f - cos_table[arg_0];
349 arg_1 = (float)fragment_pos1 / (float)ptr->buflen1 * COS_TABLE_SIZE;
350 am_1 = 1.0f - cos_table[arg_1];
351 arg_2 = (float)fragment_pos2 / (float)ptr->buflen2 * COS_TABLE_SIZE;
352 am_2 = 1.0f - cos_table[arg_2];
353
354 *(output++) += ptr->run_adding_gain *
355 (drylevel * in + wetlevel * (am_0 * out_0 + am_1 * out_1 + am_2 * out_2));
356 }
357 }
358
359
360
361
362 /* Throw away a Reflector effect instance. */
363 void
cleanup_Reflector(LADSPA_Handle Instance)364 cleanup_Reflector(LADSPA_Handle Instance) {
365
366 Reflector * ptr = (Reflector *)Instance;
367 free(ptr->ring0);
368 free(ptr->ring1);
369 free(ptr->ring2);
370 free(ptr->delay1);
371 free(ptr->delay2);
372 free(Instance);
373 }
374
375
376
377 LADSPA_Descriptor * mono_descriptor = NULL;
378
379
380
381 /* _init() is called automatically when the plugin library is first
382 loaded. */
383 void
_init()384 _init() {
385
386 int i;
387 char ** port_names;
388 LADSPA_PortDescriptor * port_descriptors;
389 LADSPA_PortRangeHint * port_range_hints;
390
391 if ((mono_descriptor =
392 (LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor))) == NULL)
393 exit(1);
394
395 for (i = 0; i < COS_TABLE_SIZE; i++)
396 cos_table[i] = cosf(i * 2.0f * M_PI / COS_TABLE_SIZE);
397
398
399 mono_descriptor->UniqueID = ID_MONO;
400 mono_descriptor->Label = strdup("tap_reflector");
401 mono_descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE;
402 mono_descriptor->Name = strdup("TAP Reflector");
403 mono_descriptor->Maker = strdup("Tom Szilagyi");
404 mono_descriptor->Copyright = strdup("GPL");
405 mono_descriptor->PortCount = PORTCOUNT_MONO;
406
407 if ((port_descriptors =
408 (LADSPA_PortDescriptor *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortDescriptor))) == NULL)
409 exit(1);
410
411 mono_descriptor->PortDescriptors = (const LADSPA_PortDescriptor *)port_descriptors;
412 port_descriptors[FRAGMENT] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
413 port_descriptors[DRYLEVEL] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
414 port_descriptors[WETLEVEL] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
415 port_descriptors[INPUT] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
416 port_descriptors[OUTPUT] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
417
418 if ((port_names =
419 (char **)calloc(PORTCOUNT_MONO, sizeof(char *))) == NULL)
420 exit(1);
421
422 mono_descriptor->PortNames = (const char **)port_names;
423 port_names[FRAGMENT] = strdup("Fragment Length [ms]");
424 port_names[DRYLEVEL] = strdup("Dry Level [dB]");
425 port_names[WETLEVEL] = strdup("Wet Level [dB]");
426 port_names[INPUT] = strdup("Input");
427 port_names[OUTPUT] = strdup("Output");
428
429 if ((port_range_hints =
430 ((LADSPA_PortRangeHint *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortRangeHint)))) == NULL)
431 exit(1);
432
433 mono_descriptor->PortRangeHints = (const LADSPA_PortRangeHint *)port_range_hints;
434 port_range_hints[FRAGMENT].HintDescriptor =
435 (LADSPA_HINT_BOUNDED_BELOW |
436 LADSPA_HINT_BOUNDED_ABOVE |
437 LADSPA_HINT_DEFAULT_LOW);
438 port_range_hints[DRYLEVEL].HintDescriptor =
439 (LADSPA_HINT_BOUNDED_BELOW |
440 LADSPA_HINT_BOUNDED_ABOVE |
441 LADSPA_HINT_DEFAULT_MINIMUM);
442 port_range_hints[WETLEVEL].HintDescriptor =
443 (LADSPA_HINT_BOUNDED_BELOW |
444 LADSPA_HINT_BOUNDED_ABOVE |
445 LADSPA_HINT_DEFAULT_0);
446 port_range_hints[FRAGMENT].LowerBound = (float)MIN_FRAGMENT_LEN;
447 port_range_hints[FRAGMENT].UpperBound = (float)MAX_FRAGMENT_LEN;
448 port_range_hints[DRYLEVEL].LowerBound = -90.0f;
449 port_range_hints[DRYLEVEL].UpperBound = 20.0f;
450 port_range_hints[WETLEVEL].LowerBound = -90.0f;
451 port_range_hints[WETLEVEL].UpperBound = 20.0f;
452 port_range_hints[INPUT].HintDescriptor = 0;
453 port_range_hints[OUTPUT].HintDescriptor = 0;
454 mono_descriptor->instantiate = instantiate_Reflector;
455 mono_descriptor->connect_port = connect_port_Reflector;
456 mono_descriptor->activate = activate_Reflector;
457 mono_descriptor->run = run_Reflector;
458 mono_descriptor->run_adding = run_adding_Reflector;
459 mono_descriptor->set_run_adding_gain = set_run_adding_gain_Reflector;
460 mono_descriptor->deactivate = NULL;
461 mono_descriptor->cleanup = cleanup_Reflector;
462 }
463
464
465 void
delete_descriptor(LADSPA_Descriptor * descriptor)466 delete_descriptor(LADSPA_Descriptor * descriptor) {
467 unsigned long index;
468 if (descriptor) {
469 free((char *)descriptor->Label);
470 free((char *)descriptor->Name);
471 free((char *)descriptor->Maker);
472 free((char *)descriptor->Copyright);
473 free((LADSPA_PortDescriptor *)descriptor->PortDescriptors);
474 for (index = 0; index < descriptor->PortCount; index++)
475 free((char *)(descriptor->PortNames[index]));
476 free((char **)descriptor->PortNames);
477 free((LADSPA_PortRangeHint *)descriptor->PortRangeHints);
478 free(descriptor);
479 }
480 }
481
482
483 /* _fini() is called automatically when the library is unloaded. */
484 void
_fini()485 _fini() {
486 delete_descriptor(mono_descriptor);
487 }
488
489
490 /* Return a descriptor of the requested plugin type. */
491 const LADSPA_Descriptor *
ladspa_descriptor(unsigned long Index)492 ladspa_descriptor(unsigned long Index) {
493
494 switch (Index) {
495 case 0:
496 return mono_descriptor;
497 default:
498 return NULL;
499 }
500 }
501