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_vibrato.c,v 1.3 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 
31 /* The Unique ID of the plugin: */
32 
33 #define ID_MONO         2148
34 
35 /* The port numbers for the plugin: */
36 
37 #define FREQ            0
38 #define DEPTH           1
39 #define DRYLEVEL        2
40 #define WETLEVEL        3
41 #define LATENCY         4
42 #define INPUT           5
43 #define OUTPUT          6
44 
45 /* Total number of ports */
46 
47 
48 #define PORTCOUNT_MONO   7
49 
50 
51 /*
52  * This has to be bigger than 0.2f * sample_rate / (2*PI) for any sample rate.
53  * At 192 kHz 6238 is needed so this should be enough.
54  */
55 #define PM_DEPTH 6300
56 
57 
58 #define PM_FREQ 30.0f
59 
60 
61 #define COS_TABLE_SIZE 1024
62 LADSPA_Data cos_table[COS_TABLE_SIZE];
63 
64 
65 /* The structure used to hold port connection information and state */
66 
67 typedef struct {
68 	LADSPA_Data * depth;
69 	LADSPA_Data * freq;
70 	LADSPA_Data * drylevel;
71 	LADSPA_Data * wetlevel;
72 	LADSPA_Data * latency;
73 	LADSPA_Data * input;
74 	LADSPA_Data * output;
75 
76 	LADSPA_Data * ringbuffer;
77 	unsigned long buflen;
78 	unsigned long pos;
79 	LADSPA_Data phase;
80 
81 	unsigned long sample_rate;
82 	LADSPA_Data run_adding_gain;
83 } Vibrato;
84 
85 
86 
87 /* Construct a new plugin instance. */
88 LADSPA_Handle
instantiate_Vibrato(const LADSPA_Descriptor * Descriptor,unsigned long sample_rate)89 instantiate_Vibrato(const LADSPA_Descriptor * Descriptor,
90 		    unsigned long             sample_rate) {
91 
92         LADSPA_Handle * ptr;
93 
94 	if ((ptr = malloc(sizeof(Vibrato))) != NULL) {
95 		((Vibrato *)ptr)->sample_rate = sample_rate;
96 		((Vibrato *)ptr)->run_adding_gain = 1.0f;
97 
98 		if ((((Vibrato *)ptr)->ringbuffer =
99 		     calloc(2 * PM_DEPTH, sizeof(LADSPA_Data))) == NULL)
100 			return NULL;
101 		((Vibrato *)ptr)->buflen = ceil(0.2f * sample_rate / M_PI);
102 		((Vibrato *)ptr)->pos = 0;
103 
104 		return ptr;
105 	}
106        	return NULL;
107 }
108 
109 
110 void
activate_Vibrato(LADSPA_Handle Instance)111 activate_Vibrato(LADSPA_Handle Instance) {
112 
113 	Vibrato * ptr = (Vibrato *)Instance;
114 	unsigned long i;
115 
116 	for (i = 0; i < 2 * PM_DEPTH; i++)
117 		ptr->ringbuffer[i] = 0.0f;
118 
119 	ptr->phase = 0.0f;
120 }
121 
122 
123 
124 
125 
126 /* Connect a port to a data location. */
127 void
connect_port_Vibrato(LADSPA_Handle Instance,unsigned long Port,LADSPA_Data * DataLocation)128 connect_port_Vibrato(LADSPA_Handle Instance,
129 		     unsigned long Port,
130 		     LADSPA_Data * DataLocation) {
131 
132 	Vibrato * ptr = (Vibrato *)Instance;
133 
134 	switch (Port) {
135 	case DEPTH:
136 		ptr->depth = DataLocation;
137 		break;
138 	case FREQ:
139 		ptr->freq = DataLocation;
140 		break;
141 	case DRYLEVEL:
142 		ptr->drylevel = DataLocation;
143 		break;
144 	case WETLEVEL:
145 		ptr->wetlevel = DataLocation;
146 		break;
147 	case LATENCY:
148 		ptr->latency = DataLocation;
149 		*(ptr->latency) = ptr->buflen / 2;  /* IS THIS LEGAL? */
150 		break;
151 	case INPUT:
152 		ptr->input = DataLocation;
153 		break;
154 	case OUTPUT:
155 		ptr->output = DataLocation;
156 		break;
157 	}
158 }
159 
160 
161 
162 void
run_Vibrato(LADSPA_Handle Instance,unsigned long SampleCount)163 run_Vibrato(LADSPA_Handle Instance,
164 	    unsigned long SampleCount) {
165 
166 	Vibrato * ptr = (Vibrato *)Instance;
167 
168 	LADSPA_Data freq = LIMIT(*(ptr->freq),0.0f,PM_FREQ);
169 	LADSPA_Data depth =
170 		LIMIT(LIMIT(*(ptr->depth),0.0f,20.0f) * ptr->sample_rate / 200.0f / M_PI / freq,
171 		      0, ptr->buflen / 2);
172 	LADSPA_Data drylevel = db2lin(LIMIT(*(ptr->drylevel),-90.0f,20.0f));
173 	LADSPA_Data wetlevel = db2lin(LIMIT(*(ptr->wetlevel),-90.0f,20.0f));
174 	LADSPA_Data * input = ptr->input;
175 	LADSPA_Data * output = ptr->output;
176 
177 	unsigned long sample_index;
178 	unsigned long sample_count = SampleCount;
179 
180 	LADSPA_Data in = 0.0f;
181 	LADSPA_Data phase = 0.0f;
182 	LADSPA_Data fpos = 0.0f;
183 	LADSPA_Data n = 0.0f;
184 	LADSPA_Data rem = 0.0f;
185 	LADSPA_Data s_a, s_b;
186 
187 
188 	if (freq == 0.0f)
189 		depth = 0.0f;
190 
191 	for (sample_index = 0; sample_index < sample_count; sample_index++) {
192 
193 		in = *(input++);
194 
195 		phase = COS_TABLE_SIZE * freq * sample_index / ptr->sample_rate + ptr->phase;
196 		while (phase >= COS_TABLE_SIZE)
197 		        phase -= COS_TABLE_SIZE;
198 
199 		push_buffer(in, ptr->ringbuffer, ptr->buflen, &(ptr->pos));
200 
201 		fpos = depth * (1.0f - cos_table[(unsigned long) phase]);
202 		n = floorf(fpos);
203 		rem = fpos - n;
204 
205 		s_a = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n);
206 		s_b = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n + 1);
207 
208 		*(output++) = wetlevel * ((1 - rem) * s_a + rem * s_b) +
209 			drylevel * read_buffer(ptr->ringbuffer, ptr->buflen,
210 					       ptr->pos, ptr->buflen / 2);
211 
212 	}
213 
214 	ptr->phase += COS_TABLE_SIZE * freq * sample_index / ptr->sample_rate;
215 	while (ptr->phase >= COS_TABLE_SIZE)
216 		ptr->phase -= COS_TABLE_SIZE;
217 
218 	*(ptr->latency) = ptr->buflen / 2;
219 }
220 
221 
222 void
set_run_adding_gain_Vibrato(LADSPA_Handle Instance,LADSPA_Data gain)223 set_run_adding_gain_Vibrato(LADSPA_Handle Instance, LADSPA_Data gain) {
224 
225 	Vibrato * ptr = (Vibrato *)Instance;
226 
227 	ptr->run_adding_gain = gain;
228 }
229 
230 
231 
232 void
run_adding_Vibrato(LADSPA_Handle Instance,unsigned long SampleCount)233 run_adding_Vibrato(LADSPA_Handle Instance,
234 		   unsigned long SampleCount) {
235 
236 	Vibrato * ptr = (Vibrato *)Instance;
237 
238 	LADSPA_Data freq = LIMIT(*(ptr->freq),0.0f,PM_FREQ);
239 	LADSPA_Data depth =
240 		LIMIT(LIMIT(*(ptr->depth),0.0f,20.0f) * ptr->sample_rate / 200.0f / M_PI / freq,
241 		      0, ptr->buflen / 2);
242 	LADSPA_Data drylevel = db2lin(LIMIT(*(ptr->drylevel),-90.0f,20.0f));
243 	LADSPA_Data wetlevel = db2lin(LIMIT(*(ptr->wetlevel),-90.0f,20.0f));
244 	LADSPA_Data * input = ptr->input;
245 	LADSPA_Data * output = ptr->output;
246 
247 	unsigned long sample_index;
248 	unsigned long sample_count = SampleCount;
249 
250 	LADSPA_Data in = 0.0f;
251 	LADSPA_Data phase = 0.0f;
252 	LADSPA_Data fpos = 0.0f;
253 	LADSPA_Data n = 0.0f;
254 	LADSPA_Data rem = 0.0f;
255 	LADSPA_Data s_a, s_b;
256 
257 
258 	if (freq == 0.0f)
259 		depth = 0.0f;
260 
261 	for (sample_index = 0; sample_index < sample_count; sample_index++) {
262 
263 		in = *(input++);
264 
265 		phase = COS_TABLE_SIZE * freq * sample_index / ptr->sample_rate + ptr->phase;
266 		while (phase >= COS_TABLE_SIZE)
267 		        phase -= COS_TABLE_SIZE;
268 
269 		push_buffer(in, ptr->ringbuffer, ptr->buflen, &(ptr->pos));
270 
271 		fpos = depth * (1.0f - cos_table[(unsigned long) phase]);
272 		n = floorf(fpos);
273 		rem = fpos - n;
274 
275 		s_a = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n);
276 		s_b = read_buffer(ptr->ringbuffer, ptr->buflen, ptr->pos, (unsigned long) n + 1);
277 
278 		*(output++) += ptr->run_adding_gain * wetlevel * ((1 - rem) * s_a + rem * s_b) +
279 			drylevel * read_buffer(ptr->ringbuffer, ptr->buflen,
280 					       ptr->pos, ptr->buflen / 2);
281 
282 	}
283 
284 	ptr->phase += COS_TABLE_SIZE * freq * sample_index / ptr->sample_rate;
285 	while (ptr->phase >= COS_TABLE_SIZE)
286 		ptr->phase -= COS_TABLE_SIZE;
287 
288 	*(ptr->latency) = ptr->buflen / 2;
289 }
290 
291 
292 
293 /* Throw away a Vibrato effect instance. */
294 void
cleanup_Vibrato(LADSPA_Handle Instance)295 cleanup_Vibrato(LADSPA_Handle Instance) {
296 
297   	Vibrato * ptr = (Vibrato *)Instance;
298 	free(ptr->ringbuffer);
299 	free(Instance);
300 }
301 
302 
303 
304 LADSPA_Descriptor * mono_descriptor = NULL;
305 
306 
307 
308 /* _init() is called automatically when the plugin library is first
309    loaded. */
310 void
_init()311 _init() {
312 
313 	int i;
314 	char ** port_names;
315 	LADSPA_PortDescriptor * port_descriptors;
316 	LADSPA_PortRangeHint * port_range_hints;
317 
318 	if ((mono_descriptor =
319 	     (LADSPA_Descriptor *)malloc(sizeof(LADSPA_Descriptor))) == NULL)
320 		exit(1);
321 
322 	for (i = 0; i < COS_TABLE_SIZE; i++)
323 		cos_table[i] = cosf(i * 2.0f * M_PI / COS_TABLE_SIZE);
324 
325 	mono_descriptor->UniqueID = ID_MONO;
326 	mono_descriptor->Label = strdup("tap_vibrato");
327 	mono_descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE;
328 	mono_descriptor->Name = strdup("TAP Vibrato");
329 	mono_descriptor->Maker = strdup("Tom Szilagyi");
330 	mono_descriptor->Copyright = strdup("GPL");
331 	mono_descriptor->PortCount = PORTCOUNT_MONO;
332 
333 	if ((port_descriptors =
334 	     (LADSPA_PortDescriptor *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortDescriptor))) == NULL)
335 		exit(1);
336 
337 	mono_descriptor->PortDescriptors = (const LADSPA_PortDescriptor *)port_descriptors;
338 	port_descriptors[DEPTH] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
339 	port_descriptors[FREQ] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
340 	port_descriptors[DRYLEVEL] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
341 	port_descriptors[WETLEVEL] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
342 	port_descriptors[LATENCY] = LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL;
343 	port_descriptors[INPUT] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
344 	port_descriptors[OUTPUT] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
345 
346 	if ((port_names =
347 	     (char **)calloc(PORTCOUNT_MONO, sizeof(char *))) == NULL)
348 		exit(1);
349 
350 	mono_descriptor->PortNames = (const char **)port_names;
351 	port_names[FREQ] = strdup("Frequency [Hz]");
352 	port_names[DEPTH] = strdup("Depth [%]");
353 	port_names[DRYLEVEL] = strdup("Dry Level [dB]");
354 	port_names[WETLEVEL] = strdup("Wet Level [dB]");
355 	port_names[LATENCY] = strdup("latency");
356 	port_names[INPUT] = strdup("Input");
357 	port_names[OUTPUT] = strdup("Output");
358 
359 	if ((port_range_hints =
360 	     ((LADSPA_PortRangeHint *)calloc(PORTCOUNT_MONO, sizeof(LADSPA_PortRangeHint)))) == NULL)
361 		exit(1);
362 
363 	mono_descriptor->PortRangeHints	= (const LADSPA_PortRangeHint *)port_range_hints;
364 	port_range_hints[DEPTH].HintDescriptor =
365 		(LADSPA_HINT_BOUNDED_BELOW |
366 		 LADSPA_HINT_BOUNDED_ABOVE |
367 		 LADSPA_HINT_DEFAULT_0);
368 	port_range_hints[FREQ].HintDescriptor =
369 		(LADSPA_HINT_BOUNDED_BELOW |
370 		 LADSPA_HINT_BOUNDED_ABOVE |
371 		 LADSPA_HINT_DEFAULT_0);
372 	port_range_hints[DRYLEVEL].HintDescriptor =
373 		(LADSPA_HINT_BOUNDED_BELOW |
374 		 LADSPA_HINT_BOUNDED_ABOVE |
375 		 LADSPA_HINT_DEFAULT_MINIMUM);
376 	port_range_hints[WETLEVEL].HintDescriptor =
377 		(LADSPA_HINT_BOUNDED_BELOW |
378 		 LADSPA_HINT_BOUNDED_ABOVE |
379 		 LADSPA_HINT_DEFAULT_0);
380 	port_range_hints[LATENCY].HintDescriptor =
381 		(LADSPA_HINT_BOUNDED_BELOW |
382 		 LADSPA_HINT_BOUNDED_ABOVE |
383 		 LADSPA_HINT_DEFAULT_MAXIMUM);
384 	port_range_hints[DEPTH].LowerBound = 0;
385 	port_range_hints[DEPTH].UpperBound = 20.0f;
386 	port_range_hints[FREQ].LowerBound = 0;
387 	port_range_hints[FREQ].UpperBound = PM_FREQ;
388 	port_range_hints[DRYLEVEL].LowerBound = -90.0f;
389 	port_range_hints[DRYLEVEL].UpperBound = +20.0f;
390 	port_range_hints[WETLEVEL].LowerBound = -90.0f;
391 	port_range_hints[WETLEVEL].UpperBound = +20.0f;
392 	port_range_hints[LATENCY].LowerBound = 0;
393 	port_range_hints[LATENCY].UpperBound = PM_DEPTH;
394 	port_range_hints[INPUT].HintDescriptor = 0;
395 	port_range_hints[OUTPUT].HintDescriptor = 0;
396 	mono_descriptor->instantiate = instantiate_Vibrato;
397 	mono_descriptor->connect_port = connect_port_Vibrato;
398 	mono_descriptor->activate = activate_Vibrato;
399 	mono_descriptor->run = run_Vibrato;
400 	mono_descriptor->run_adding = run_adding_Vibrato;
401 	mono_descriptor->set_run_adding_gain = set_run_adding_gain_Vibrato;
402 	mono_descriptor->deactivate = NULL;
403 	mono_descriptor->cleanup = cleanup_Vibrato;
404 }
405 
406 
407 void
delete_descriptor(LADSPA_Descriptor * descriptor)408 delete_descriptor(LADSPA_Descriptor * descriptor) {
409 	unsigned long index;
410 	if (descriptor) {
411 		free((char *)descriptor->Label);
412 		free((char *)descriptor->Name);
413 		free((char *)descriptor->Maker);
414 		free((char *)descriptor->Copyright);
415 		free((LADSPA_PortDescriptor *)descriptor->PortDescriptors);
416 		for (index = 0; index < descriptor->PortCount; index++)
417 			free((char *)(descriptor->PortNames[index]));
418 		free((char **)descriptor->PortNames);
419 		free((LADSPA_PortRangeHint *)descriptor->PortRangeHints);
420 		free(descriptor);
421 	}
422 }
423 
424 
425 /* _fini() is called automatically when the library is unloaded. */
426 void
_fini()427 _fini() {
428 	delete_descriptor(mono_descriptor);
429 }
430 
431 
432 /* Return a descriptor of the requested plugin type. */
433 const LADSPA_Descriptor *
ladspa_descriptor(unsigned long Index)434 ladspa_descriptor(unsigned long Index) {
435 
436 	switch (Index) {
437 	case 0:
438 		return mono_descriptor;
439 	default:
440 		return NULL;
441 	}
442 }
443