2
Copyright (C) 2004 Tom Szilagyi
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.
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.
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.
18
$Id: tap_tubewarmth.c,v 1.1 2004/08/02 18:14:50 tszilagyi Exp $
28
#include "tap_utils.h"
31
/* The Unique ID of the plugin: */
35
/* The port numbers for the plugin: */
42
/* Total number of ports */
45
#define PORTCOUNT_MONO 4
48
/* The structure used to hold port connection information and state */
73
LADSPA_Data prev_drive;
74
LADSPA_Data prev_blend;
76
unsigned long sample_rate;
77
LADSPA_Data run_adding_gain;
82
/* Construct a new plugin instance. */
84
instantiate_TubeWarmth(const LADSPA_Descriptor * Descriptor,
85
unsigned long sample_rate) {
89
if ((ptr = malloc(sizeof(TubeWarmth))) != NULL) {
90
((TubeWarmth *)ptr)->sample_rate = sample_rate;
91
((TubeWarmth *)ptr)->run_adding_gain = 1.0f;
93
((TubeWarmth *)ptr)->prev_med = 0.0f;
94
((TubeWarmth *)ptr)->prev_out = 0.0f;
96
((TubeWarmth *)ptr)->rdrive = 0.0f;
97
((TubeWarmth *)ptr)->rbdr = 0.0f;
98
((TubeWarmth *)ptr)->kpa = 0.0f;
99
((TubeWarmth *)ptr)->kpb = 0.0f;
100
((TubeWarmth *)ptr)->kna = 0.0f;
101
((TubeWarmth *)ptr)->knb = 0.0f;
102
((TubeWarmth *)ptr)->ap = 0.0f;
103
((TubeWarmth *)ptr)->an = 0.0f;
104
((TubeWarmth *)ptr)->imr = 0.0f;
105
((TubeWarmth *)ptr)->kc = 0.0f;
106
((TubeWarmth *)ptr)->srct = 0.0f;
107
((TubeWarmth *)ptr)->sq = 0.0f;
108
((TubeWarmth *)ptr)->pwrq = 0.0f;
110
/* These are out of band to force param recalc upon first run() */
111
((TubeWarmth *)ptr)->prev_drive = -1.0f;
112
((TubeWarmth *)ptr)->prev_blend = -11.0f;
123
/* Connect a port to a data location. */
125
connect_port_TubeWarmth(LADSPA_Handle Instance,
127
LADSPA_Data * DataLocation) {
129
TubeWarmth * ptr = (TubeWarmth *)Instance;
133
ptr->drive = DataLocation;
136
ptr->blend = DataLocation;
139
ptr->input = DataLocation;
142
ptr->output = DataLocation;
148
#define EPS 0.000000001f
153
if ((x > EPS) || (x < -EPS))
171
run_TubeWarmth(LADSPA_Handle Instance,
172
unsigned long SampleCount) {
174
TubeWarmth * ptr = (TubeWarmth *)Instance;
175
LADSPA_Data * input = ptr->input;
176
LADSPA_Data * output = ptr->output;
177
LADSPA_Data drive = LIMIT(*(ptr->drive),0.1f,10.0f);
178
LADSPA_Data blend = LIMIT(*(ptr->blend),-10.0f,10.0f);
180
unsigned long sample_index;
181
unsigned long sample_count = SampleCount;
182
unsigned long sample_rate = ptr->sample_rate;
184
LADSPA_Data rdrive = ptr->rdrive;
185
LADSPA_Data rbdr = ptr->rbdr;
186
LADSPA_Data kpa = ptr->kpa;
187
LADSPA_Data kpb = ptr->kpb;
188
LADSPA_Data kna = ptr->kna;
189
LADSPA_Data knb = ptr->knb;
190
LADSPA_Data ap = ptr->ap;
191
LADSPA_Data an = ptr->an;
192
LADSPA_Data imr = ptr->imr;
193
LADSPA_Data kc = ptr->kc;
194
LADSPA_Data srct = ptr->srct;
195
LADSPA_Data sq = ptr->sq;
196
LADSPA_Data pwrq = ptr->pwrq;
198
LADSPA_Data prev_med;
199
LADSPA_Data prev_out;
204
if ((ptr->prev_drive != drive) || (ptr->prev_blend != blend)) {
206
rdrive = 12.0f / drive;
207
rbdr = rdrive / (10.5f - blend) * 780.0f / 33.0f;
208
kpa = D(2.0f * (rdrive*rdrive) - 1.0f) + 1.0f;
209
kpb = (2.0f - kpa) / 2.0f;
210
ap = ((rdrive*rdrive) - kpa + 1.0f) / 2.0f;
211
kc = kpa / D(2.0f * D(2.0f * (rdrive*rdrive) - 1.0f) - 2.0f * rdrive*rdrive);
213
srct = (0.1f * sample_rate) / (0.1f * sample_rate + 1.0f);
215
knb = -1.0f * rbdr / D(sq);
216
kna = 2.0f * kc * rbdr / D(sq);
218
imr = 2.0f * knb + D(2.0f * kna + 4.0f * an - 1.0f);
219
pwrq = 2.0f / (imr + 1.0f);
221
ptr->prev_drive = drive;
222
ptr->prev_blend = blend;
225
for (sample_index = 0; sample_index < sample_count; sample_index++) {
228
prev_med = ptr->prev_med;
229
prev_out = ptr->prev_out;
232
med = (D(ap + in * (kpa - in)) + kpb) * pwrq;
234
med = (D(an - in * (kna + in)) + knb) * pwrq * -1.0f;
237
out = srct * (med - prev_med + prev_out);
244
ptr->prev_med = M(med);
245
ptr->prev_out = M(out);
248
ptr->rdrive = rdrive;
266
set_run_adding_gain_TubeWarmth(LADSPA_Handle Instance, LADSPA_Data gain) {
268
TubeWarmth * ptr = (TubeWarmth *)Instance;
270
ptr->run_adding_gain = gain;
276
run_adding_TubeWarmth(LADSPA_Handle Instance,
277
unsigned long SampleCount) {
279
TubeWarmth * ptr = (TubeWarmth *)Instance;
280
LADSPA_Data * input = ptr->input;
281
LADSPA_Data * output = ptr->output;
282
LADSPA_Data drive = LIMIT(*(ptr->drive),0.1f,10.0f);
283
LADSPA_Data blend = LIMIT(*(ptr->blend),-10.0f,10.0f);
285
unsigned long sample_index;
286
unsigned long sample_count = SampleCount;
287
unsigned long sample_rate = ptr->sample_rate;
289
LADSPA_Data rdrive = ptr->rdrive;
290
LADSPA_Data rbdr = ptr->rbdr;
291
LADSPA_Data kpa = ptr->kpa;
292
LADSPA_Data kpb = ptr->kpb;
293
LADSPA_Data kna = ptr->kna;
294
LADSPA_Data knb = ptr->knb;
295
LADSPA_Data ap = ptr->ap;
296
LADSPA_Data an = ptr->an;
297
LADSPA_Data imr = ptr->imr;
298
LADSPA_Data kc = ptr->kc;
299
LADSPA_Data srct = ptr->srct;
300
LADSPA_Data sq = ptr->sq;
301
LADSPA_Data pwrq = ptr->pwrq;
303
LADSPA_Data prev_med;
304
LADSPA_Data prev_out;
309
if ((ptr->prev_drive != drive) || (ptr->prev_blend != blend)) {
311
rdrive = 12.0f / drive;
312
rbdr = rdrive / (10.5f - blend) * 780.0f / 33.0f;
313
kpa = D(2.0f * (rdrive*rdrive) - 1.0f) + 1.0f;
314
kpb = (2.0f - kpa) / 2.0f;
315
ap = ((rdrive*rdrive) - kpa + 1.0f) / 2.0f;
316
kc = kpa / D(2.0f * D(2.0f * (rdrive*rdrive) - 1.0f) - 2.0f * rdrive*rdrive);
318
srct = (0.1f * sample_rate) / (0.1f * sample_rate + 1.0f);
320
knb = -1.0f * rbdr / D(sq);
321
kna = 2.0f * kc * rbdr / D(sq);
323
imr = 2.0f * knb + D(2.0f * kna + 4.0f * an - 1.0f);
324
pwrq = 2.0f / (imr + 1.0f);
326
ptr->prev_drive = drive;
327
ptr->prev_blend = blend;
330
for (sample_index = 0; sample_index < sample_count; sample_index++) {
333
prev_med = ptr->prev_med;
334
prev_out = ptr->prev_out;
337
med = (D(ap + in * (kpa - in)) + kpb) * pwrq;
339
med = (D(an - in * (kna + in)) + knb) * pwrq * -1.0f;
342
out = srct * (med - prev_med + prev_out);
347
*(output++) += out * ptr->run_adding_gain;
349
ptr->prev_med = M(med);
350
ptr->prev_out = M(out);
353
ptr->rdrive = rdrive;
371
/* Throw away a TubeWarmth effect instance. */
373
cleanup_TubeWarmth(LADSPA_Handle Instance) {
380
LADSPA_Descriptor * mono_descriptor = NULL;
384
/* __attribute__((constructor)) _init() is called automatically when the plugin library is first
387
__attribute__((constructor)) _init() {
390
LADSPA_PortDescriptor * port_descriptors;
391
LADSPA_PortRangeHint * port_range_hints;
393
if ((mono_descriptor =
394
(LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor))) == NULL)
398
mono_descriptor->UniqueID = ID_MONO;
399
mono_descriptor->Label = strdup("tap_tubewarmth");
400
mono_descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE;
401
mono_descriptor->Name = strdup("TAP TubeWarmth");
402
mono_descriptor->Maker = strdup("Tom Szilagyi");
403
mono_descriptor->Copyright = strdup("GPL");
404
mono_descriptor->PortCount = PORTCOUNT_MONO;
406
if ((port_descriptors =
407
(LADSPA_PortDescriptor *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortDescriptor))) == NULL)
410
mono_descriptor->PortDescriptors = (const LADSPA_PortDescriptor *)port_descriptors;
411
port_descriptors[DRIVE] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
412
port_descriptors[BLEND] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
413
port_descriptors[INPUT] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
414
port_descriptors[OUTPUT] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
417
(char **)calloc(PORTCOUNT_MONO, sizeof(char *))) == NULL)
420
mono_descriptor->PortNames = (const char **)port_names;
421
port_names[DRIVE] = strdup("Drive");
422
port_names[BLEND] = strdup("Tape--Tube Blend");
423
port_names[INPUT] = strdup("Input");
424
port_names[OUTPUT] = strdup("Output");
426
if ((port_range_hints =
427
((LADSPA_PortRangeHint *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortRangeHint)))) == NULL)
430
mono_descriptor->PortRangeHints = (const LADSPA_PortRangeHint *)port_range_hints;
431
port_range_hints[DRIVE].HintDescriptor =
432
(LADSPA_HINT_BOUNDED_BELOW |
433
LADSPA_HINT_BOUNDED_ABOVE |
434
LADSPA_HINT_DEFAULT_LOW);
435
port_range_hints[BLEND].HintDescriptor =
436
(LADSPA_HINT_BOUNDED_BELOW |
437
LADSPA_HINT_BOUNDED_ABOVE |
438
LADSPA_HINT_DEFAULT_MAXIMUM);
439
port_range_hints[DRIVE].LowerBound = 0.1f;
440
port_range_hints[DRIVE].UpperBound = 10.0f;
441
port_range_hints[BLEND].LowerBound = -10.0f;
442
port_range_hints[BLEND].UpperBound = 10.0f;
443
port_range_hints[INPUT].HintDescriptor = 0;
444
port_range_hints[OUTPUT].HintDescriptor = 0;
445
mono_descriptor->instantiate = instantiate_TubeWarmth;
446
mono_descriptor->connect_port = connect_port_TubeWarmth;
447
mono_descriptor->activate = NULL;
448
mono_descriptor->run = run_TubeWarmth;
449
mono_descriptor->run_adding = run_adding_TubeWarmth;
450
mono_descriptor->set_run_adding_gain = set_run_adding_gain_TubeWarmth;
451
mono_descriptor->deactivate = NULL;
452
mono_descriptor->cleanup = cleanup_TubeWarmth;
457
delete_descriptor(LADSPA_Descriptor * descriptor) {
460
free((char *)descriptor->Label);
461
free((char *)descriptor->Name);
462
free((char *)descriptor->Maker);
463
free((char *)descriptor->Copyright);
464
free((LADSPA_PortDescriptor *)descriptor->PortDescriptors);
465
for (index = 0; index < descriptor->PortCount; index++)
466
free((char *)(descriptor->PortNames[index]));
467
free((char **)descriptor->PortNames);
468
free((LADSPA_PortRangeHint *)descriptor->PortRangeHints);
474
/* __attribute__((destructor)) _fini() is called automatically when the library is unloaded. */
476
__attribute__((destructor)) _fini() {
477
delete_descriptor(mono_descriptor);
481
/* Return a descriptor of the requested plugin type. */
482
const LADSPA_Descriptor *
483
ladspa_descriptor(unsigned long Index) {
487
return mono_descriptor;