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_doubler.c,v 1.4 2004/08/13 18:34:31 tszilagyi Exp $
19 */
20 
21 
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <math.h>
26 #include <time.h>
27 
28 #include <lv2.h>
29 #include "tap_utils.h"
30 
31 
32 /* The Unique ID of the plugin: */
33 
34 #define ID_STEREO       2156
35 
36 /* The port numbers for the plugin: */
37 
38 #define TIME            0
39 #define PITCH           1
40 #define DRYLEVEL        2
41 #define DRYPOSL         3
42 #define DRYPOSR         4
43 #define WETLEVEL        5
44 #define WETPOSL         6
45 #define WETPOSR         7
46 #define INPUT_L         8
47 #define INPUT_R         9
48 #define OUTPUT_L       10
49 #define OUTPUT_R       11
50 
51 /* Total number of ports */
52 
53 
54 #define PORTCOUNT_STEREO 12
55 
56 
57 /* Number of pink noise samples to be generated at once */
58 #define NOISE_LEN 1024
59 
60 /*
61  * Largest buffer length needed (at 192 kHz).
62  */
63 #define BUFLEN 11520
64 
65 
66 
67 /* The structure used to hold port connection information and state */
68 
69 typedef struct {
70 	float * time;
71 	float * pitch;
72 	float * drylevel;
73 	float smoothdrylevel;
74 	float * dryposl;
75 	float * dryposr;
76 	float * wetlevel;
77 	float smoothwetlevel;
78 	float * wetposl;
79 	float * wetposr;
80 	float * input_L;
81 	float * input_R;
82 	float * output_L;
83 	float * output_R;
84 
85 	float old_time;
86 	float old_pitch;
87 
88 	float * ring_L;
89 	unsigned long buflen_L;
90 	unsigned long pos_L;
91 
92 	float * ring_R;
93 	unsigned long buflen_R;
94 	unsigned long pos_R;
95 
96 	float * ring_pnoise;
97 	unsigned long buflen_pnoise;
98 	unsigned long pos_pnoise;
99 
100 	float * ring_dnoise;
101 	unsigned long buflen_dnoise;
102 	unsigned long pos_dnoise;
103 
104 	float delay;
105 	float d_delay;
106 	float p_delay;
107 	unsigned long n_delay;
108 
109 	float pitchmod;
110 	float d_pitch;
111 	float p_pitch;
112 	unsigned long n_pitch;
113 
114 	unsigned long p_stretch;
115 	unsigned long d_stretch;
116 
117 	double sample_rate;
118 } Doubler;
119 
120 
121 /* generate fractal pattern using Midpoint Displacement Method
122  * v: buffer of floats to output fractal pattern to
123  * N: length of v, MUST be integer power of 2 (ie 128, 256, ...)
124  * H: Hurst constant, between 0 and 0.9999 (fractal dimension)
125  */
126 void
fractal(float * v,int N,float H)127 fractal(float * v, int N, float H) {
128 
129         int l = N;
130         int k;
131         float r = 1.0f;
132         int c;
133 
134         v[0] = 0;
135         while (l > 1) {
136                 k = N / l;
137                 for (c = 0; c < k; c++) {
138                         v[c*l + l/2] = (v[c*l] + v[((c+1) * l) % N]) / 2.0f +
139                                 2.0f * r * (rand() - (float)RAND_MAX/2.0f) / (float)RAND_MAX;
140                         v[c*l + l/2] = LIMIT(v[c*l + l/2], -1.0f, 1.0f);
141                 }
142                 l /= 2;
143                 r /= powf(2, H);
144         }
145 }
146 
147 
148 
149 /* Construct a new plugin instance. */
150 LV2_Handle
instantiate_Doubler(const LV2_Descriptor * Descriptor,double sample_rate,const char * bundle_path,const LV2_Feature * const * features)151 instantiate_Doubler(const LV2_Descriptor * Descriptor, double sample_rate, const char* bundle_path, const LV2_Feature* const* features) {
152 
153         LV2_Handle * ptr;
154 
155 	if ((ptr = malloc(sizeof(Doubler))) != NULL) {
156 		((Doubler *)ptr)->sample_rate = sample_rate;
157 		((Doubler *)ptr)->smoothdrylevel = 0.0;
158 		((Doubler *)ptr)->smoothwetlevel = 0.0;
159 
160 		if ((((Doubler *)ptr)->ring_L =
161 		     calloc(BUFLEN * sample_rate / 192000, sizeof(float))) == NULL)
162 			return NULL;
163 		((Doubler *)ptr)->buflen_L = BUFLEN * sample_rate / 192000;
164 		((Doubler *)ptr)->pos_L = 0;
165 
166 		if ((((Doubler *)ptr)->ring_R =
167 		     calloc(BUFLEN * sample_rate / 192000, sizeof(float))) == NULL)
168 			return NULL;
169 		((Doubler *)ptr)->buflen_R = BUFLEN * sample_rate / 192000;
170 		((Doubler *)ptr)->pos_R = 0;
171 
172 		if ((((Doubler *)ptr)->ring_pnoise =
173 		     calloc(NOISE_LEN, sizeof(float))) == NULL)
174 			return NULL;
175 		((Doubler *)ptr)->buflen_pnoise = NOISE_LEN;
176 		((Doubler *)ptr)->pos_pnoise = 0;
177 
178 		if ((((Doubler *)ptr)->ring_dnoise =
179 		     calloc(NOISE_LEN, sizeof(float))) == NULL)
180 			return NULL;
181 		((Doubler *)ptr)->buflen_dnoise = NOISE_LEN;
182 		((Doubler *)ptr)->pos_dnoise = 0;
183 
184 		((Doubler *)ptr)->d_stretch = sample_rate / 10;
185 		((Doubler *)ptr)->p_stretch = sample_rate / 1000;
186 
187 		((Doubler *)ptr)->delay = 0.0f;
188 		((Doubler *)ptr)->d_delay = 0.0f;
189 		((Doubler *)ptr)->p_delay = 0.0f;
190 		((Doubler *)ptr)->n_delay = ((Doubler *)ptr)->d_stretch;
191 
192 		((Doubler *)ptr)->pitchmod = 0.0f;
193 		((Doubler *)ptr)->d_pitch = 0.0f;
194 		((Doubler *)ptr)->p_pitch = 0.0f;
195 		((Doubler *)ptr)->n_pitch = ((Doubler *)ptr)->p_stretch;
196 
197 		return ptr;
198 	}
199        	return NULL;
200 }
201 
202 
203 void
activate_Doubler(LV2_Handle Instance)204 activate_Doubler(LV2_Handle Instance) {
205 
206 	Doubler * ptr = (Doubler *)Instance;
207 	unsigned long i;
208 
209 	for (i = 0; i < BUFLEN * ptr->sample_rate / 192000; i++) {
210 		ptr->ring_L[i] = 0.0f;
211 		ptr->ring_R[i] = 0.0f;
212 	}
213 
214 	ptr->old_time = -1.0f;
215 	ptr->old_pitch = -1.0f;
216 }
217 
218 void
deactivate_Doubler(LV2_Handle Instance)219 deactivate_Doubler(LV2_Handle Instance) {
220 
221 }
222 
223 
224 
225 /* Connect a port to a data location. */
226 void
connect_port_Doubler(LV2_Handle Instance,uint32_t Port,void * data)227 connect_port_Doubler(LV2_Handle Instance,
228 		     uint32_t Port,
229 		     void * data) {
230 
231 	Doubler * ptr = (Doubler *)Instance;
232 
233 	switch (Port) {
234 	case TIME:
235 		ptr->time = (float*) data;
236 		break;
237 	case PITCH:
238 		ptr->pitch = (float*) data;
239 		break;
240 	case DRYLEVEL:
241 		ptr->drylevel = (float*) data;
242 		break;
243 	case DRYPOSL:
244 		ptr->dryposl = (float*) data;
245 		break;
246 	case DRYPOSR:
247 		ptr->dryposr = (float*) data;
248 		break;
249 	case WETLEVEL:
250 		ptr->wetlevel = (float*) data;
251 		break;
252 	case WETPOSL:
253 		ptr->wetposl = (float*) data;
254 		break;
255 	case WETPOSR:
256 		ptr->wetposr = (float*) data;
257 		break;
258 	case INPUT_L:
259 		ptr->input_L = (float*) data;
260 		break;
261 	case INPUT_R:
262 		ptr->input_R = (float*) data;
263 		break;
264 	case OUTPUT_L:
265 		ptr->output_L = (float*) data;
266 		break;
267 	case OUTPUT_R:
268 		ptr->output_R = (float*) data;
269 		break;
270 	}
271 }
272 
273 
274 
275 void
run_Doubler(LV2_Handle Instance,uint32_t SampleCount)276 run_Doubler(LV2_Handle Instance,
277 	    uint32_t SampleCount) {
278 
279 	Doubler * ptr = (Doubler *)Instance;
280 
281 	float pitch = LIMIT(*(ptr->pitch),0.0f,1.0f) + 0.75f;
282 	float depth = LIMIT(((1.0f - LIMIT(*(ptr->pitch),0.0f,1.0f)) * 1.75f + 0.25f) *
283 				  ptr->sample_rate / 6000.0f / M_PI,
284 				  0, ptr->buflen_L / 2);
285 	float time = LIMIT(*(ptr->time), 0.0f, 1.0f) + 0.5f;
286 
287 	float calcdry = (*(ptr->drylevel) +ptr->smoothdrylevel)*0.5;
288 	ptr->smoothdrylevel = calcdry;
289 	float drylevel = db2lin(LIMIT(calcdry,-90.0f,20.0f));
290 
291 	float calcwet = (*(ptr->wetlevel) +ptr->smoothwetlevel)*0.5;
292 	ptr->smoothwetlevel = calcwet;
293 	float wetlevel = db2lin(LIMIT(calcwet,-90.0f,20.0f));
294 
295 	float dryposl = 1.0f - LIMIT(*(ptr->dryposl), 0.0f, 1.0f);
296 	float dryposr = LIMIT(*(ptr->dryposr), 0.0f, 1.0f);
297 	float wetposl = 1.0f - LIMIT(*(ptr->wetposl), 0.0f, 1.0f);
298 	float wetposr = LIMIT(*(ptr->wetposr), 0.0f, 1.0f);
299 	float * input_L = ptr->input_L;
300 	float * input_R = ptr->input_R;
301 	float * output_L = ptr->output_L;
302 	float * output_R = ptr->output_R;
303 
304 	unsigned long sample_index;
305 	unsigned long sample_count = SampleCount;
306 
307 	float in_L = 0.0f;
308 	float in_R = 0.0f;
309 	float out_L = 0.0f;
310 	float out_R = 0.0f;
311 
312 	float fpos = 0.0f;
313 	float n = 0.0f;
314 	float rem = 0.0f;
315 	float s_a_L, s_a_R, s_b_L, s_b_R;
316 	float prev_p_pitch = 0.0f;
317 	float prev_p_delay = 0.0f;
318 	float delay;
319 
320 	float drystream_L = 0.0f;
321 	float drystream_R = 0.0f;
322 	float wetstream_L = 0.0f;
323 	float wetstream_R = 0.0f;
324 
325 	if (ptr->old_pitch != pitch) {
326 		ptr->pitchmod = ptr->p_pitch;
327 		prev_p_pitch = ptr->p_pitch;
328 		fractal(ptr->ring_pnoise, NOISE_LEN, pitch);
329 		ptr->pos_pnoise = 0;
330 		ptr->p_pitch = push_buffer(0.0f, ptr->ring_pnoise,
331 					   ptr->buflen_pnoise, &(ptr->pos_pnoise));
332 		ptr->d_pitch = (ptr->p_pitch - prev_p_pitch) / (float)(ptr->p_stretch);
333 		ptr->n_pitch = 0;
334 
335 		ptr->old_pitch = pitch;
336 	}
337 
338 	if (ptr->old_time != time) {
339 		ptr->delay = ptr->p_delay;
340 		prev_p_delay = ptr->p_delay;
341 		fractal(ptr->ring_dnoise, NOISE_LEN, time);
342 		ptr->pos_dnoise = 0;
343 		ptr->p_delay = push_buffer(0.0f, ptr->ring_dnoise,
344 					   ptr->buflen_dnoise, &(ptr->pos_dnoise));
345 		ptr->d_delay = (ptr->p_delay - prev_p_delay) / (float)(ptr->d_stretch);
346 		ptr->n_delay = 0;
347 
348 		ptr->old_time = time;
349 	}
350 
351 
352 	for (sample_index = 0; sample_index < sample_count; sample_index++) {
353 
354 		in_L = *(input_L++);
355 		in_R = *(input_R++);
356 
357 		push_buffer(in_L, ptr->ring_L, ptr->buflen_L, &(ptr->pos_L));
358 		push_buffer(in_R, ptr->ring_R, ptr->buflen_R, &(ptr->pos_R));
359 
360 		if (ptr->n_pitch < ptr->p_stretch) {
361 			ptr->pitchmod += ptr->d_pitch;
362 			ptr->n_pitch++;
363 		} else {
364 			ptr->pitchmod = ptr->p_pitch;
365 			prev_p_pitch = ptr->p_pitch;
366 			if (!ptr->pos_pnoise) {
367 				fractal(ptr->ring_pnoise, NOISE_LEN, pitch);
368 			}
369 			ptr->p_pitch = push_buffer(0.0f, ptr->ring_pnoise,
370 						   ptr->buflen_pnoise, &(ptr->pos_pnoise));
371 			ptr->d_pitch = (ptr->p_pitch - prev_p_pitch) / (float)(ptr->p_stretch);
372 			ptr->n_pitch = 0;
373 		}
374 
375 		if (ptr->n_delay < ptr->d_stretch) {
376 			ptr->delay += ptr->d_delay;
377 			ptr->n_delay++;
378 		} else {
379 			ptr->delay = ptr->p_delay;
380 			prev_p_delay = ptr->p_delay;
381 			if (!ptr->pos_dnoise) {
382 				fractal(ptr->ring_dnoise, NOISE_LEN, time);
383 			}
384 			ptr->p_delay = push_buffer(0.0f, ptr->ring_dnoise,
385 						   ptr->buflen_dnoise, &(ptr->pos_dnoise));
386 			ptr->d_delay = (ptr->p_delay - prev_p_delay) / (float)(ptr->d_stretch);
387 			ptr->n_delay = 0;
388 		}
389 
390 		delay = (12.5f * ptr->delay + 37.5f) * ptr->sample_rate / 1000.0f;
391 		fpos = ptr->buflen_L - depth * (1.0f - ptr->pitchmod) - delay - 1.0f;
392 		n = floorf(fpos);
393 		rem = fpos - n;
394 
395 		s_a_L = read_buffer(ptr->ring_L, ptr->buflen_L,
396 				    ptr->pos_L, (unsigned long) n);
397 		s_b_L = read_buffer(ptr->ring_L, ptr->buflen_L,
398 				    ptr->pos_L, (unsigned long) n + 1);
399 
400 		s_a_R = read_buffer(ptr->ring_R, ptr->buflen_R,
401 				    ptr->pos_R, (unsigned long) n);
402 		s_b_R = read_buffer(ptr->ring_R, ptr->buflen_R,
403 				    ptr->pos_R, (unsigned long) n + 1);
404 
405 		drystream_L = drylevel * in_L;
406 		drystream_R = drylevel * in_R;
407 		wetstream_L = wetlevel * ((1 - rem) * s_a_L + rem * s_b_L);
408 		wetstream_R = wetlevel * ((1 - rem) * s_a_R + rem * s_b_R);
409 
410 		out_L = dryposl * drystream_L + (1.0f - dryposr) * drystream_R +
411 			wetposl * wetstream_L + (1.0f - wetposr) * wetstream_R;
412 		out_R = (1.0f - dryposl) * drystream_L + dryposr * drystream_R +
413 			(1.0f - wetposl) * wetstream_L + wetposr * wetstream_R;
414 
415 		*(output_L++) = out_L;
416 		*(output_R++) = out_R;
417 	}
418 }
419 
420 
421 /* Throw away a Doubler effect instance. */
422 void
cleanup_Doubler(LV2_Handle Instance)423 cleanup_Doubler(LV2_Handle Instance) {
424 
425   	Doubler * ptr = (Doubler *)Instance;
426 	free(ptr->ring_L);
427 	free(ptr->ring_R);
428 	free(ptr->ring_pnoise);
429 	free(ptr->ring_dnoise);
430 	free(Instance);
431 }
432 
433 const void*
extension_data_Doubler(const char * uri)434 extension_data_Doubler(const char* uri)
435 {
436     return NULL;
437 }
438 
439 
440 static const
441 LV2_Descriptor Descriptor = {
442     "http://moddevices.com/plugins/tap/doubler",
443     instantiate_Doubler,
444     connect_port_Doubler,
445     activate_Doubler,
446     run_Doubler,
447     deactivate_Doubler,
448     cleanup_Doubler,
449     extension_data_Doubler
450 };
451 
452 LV2_SYMBOL_EXPORT
453 const LV2_Descriptor*
lv2_descriptor(uint32_t index)454 lv2_descriptor(uint32_t index)
455 {
456     if (index == 0) return &Descriptor;
457     else return NULL;
458 
459 }
460