1 /* B.Angr
2  * Dynamic distorted bandpass filter plugin
3  *
4  * Copyright (C) 2021 by Sven Jähnichen
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3, or (at your option)
9  * any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  */
20 
21 #include "BAngr.hpp"
22 
23 #include <cstdio>
24 #include <stdexcept>
25 #include "ControllerLimits.hpp"
26 
27 #define LIMIT(g , min, max) ((g) > (max) ? (max) : ((g) < (min) ? (min) : (g)))
28 
29 const float flexTime[NR_FLEX] = {1.0f, 0.05f, 0.05f, 0.05f, 0.05f};
30 
BAngr(double samplerate,const LV2_Feature * const * features)31 BAngr::BAngr (double samplerate, const LV2_Feature* const* features) :
32 	map(NULL),
33 	rate (samplerate),
34 	xcursor (0.5f),
35 	ycursor (0.5f),
36 	listen (false),
37 	rnd (time (0)),
38 	bidist (-1.0, 1.0),
39 	count (0),
40 	fader (0.0f),
41 	speed (0.0f),
42 	speedrand (0.0f),
43 	dspeedrand (0.0f),
44 	speedflex (0.0f),
45 	spin (0.0f),
46 	spinrand (0.0f),
47 	dspinrand (0.0f),
48 	spinflex (0.0f),
49 	spindir (1.0f),
50 	ang (2.0 * M_PI * bidist (rnd)),
51 	speedlevel (0.0f),
52 	speedmaxlevel (0.1f),
53 	spinlevel (0.0f),
54 	spinmaxlevel (0.1f),
55 	lowpassFilter (rate, 200.0, 8),
56 	highpassFilter (rate, 4000.0, 8),
57 	bandpassFilter (rate, 200.0, 4000.0, 8),
58 	controlPort (nullptr),
59 	notifyPort (nullptr),
60 	audioInput1 (nullptr),
61 	audioInput2 (nullptr),
62 	audioOutput1 (nullptr),
63 	audioOutput2 (nullptr),
64 	newControllers {nullptr},
65 	controllers {0.0f},
66 	xregion (samplerate)
67 
68 {
69 	//Scan host features for URID map
70 	LV2_URID_Map* m = NULL;
71 	for (int i = 0; features[i]; ++i)
72 	{
73 		if (strcmp(features[i]->URI, LV2_URID__map) == 0)
74 		{
75 			m = (LV2_URID_Map*) features[i]->data;
76 		}
77 	}
78 	if (!m) throw std::invalid_argument ("Host does not support urid:map");
79 
80 	//Map URIS
81 	map = m;
82 	getURIs (m, &urids);
83 
84 	// Initialize forge
85 	lv2_atom_forge_init (&forge, map);
86 
87 }
88 
~BAngr()89 BAngr::~BAngr () {}
90 
connect_port(uint32_t port,void * data)91 void BAngr::connect_port(uint32_t port, void *data)
92 {
93 	switch (port) {
94 	case CONTROL:
95 		controlPort = (LV2_Atom_Sequence*) data;
96 		break;
97 	case NOTIFY:
98 		notifyPort = (LV2_Atom_Sequence*) data;
99 		break;
100 	case AUDIO_IN_1:
101 		audioInput1 = (float*) data;
102 		break;
103 	case AUDIO_IN_2:
104 		audioInput2 = (float*) data;
105 		break;
106 	case AUDIO_OUT_1:
107 		audioOutput1 = (float*) data;
108 		break;
109 	case AUDIO_OUT_2:
110 		audioOutput2 = (float*) data;
111 		break;
112 	default:
113 		if ((port >= CONTROLLERS) && (port < CONTROLLERS + NR_CONTROLLERS)) newControllers[port - CONTROLLERS] = (float*) data;
114 	}
115 }
116 
run(uint32_t n_samples)117 void BAngr::run (uint32_t n_samples)
118 {
119 	// Check ports
120 	if ((!controlPort) || (!notifyPort) || (!audioInput1) || (!audioInput2) || (!audioOutput1) || (!audioOutput2)) return;
121 	for (int i = 0; i < NR_CONTROLLERS; ++i)
122 	{
123 		if (!newControllers[i]) return;
124 	}
125 
126 	// Update controller values
127 	for (int i = 0; i < NR_CONTROLLERS; ++i)
128 	{
129 		if (controllers[i] != *newControllers[i]) controllers[i] = controllerLimits[i].validate (*newControllers[i]);
130 	}
131 
132 	// Prepare forge buffer and initialize atom sequence
133 	const uint32_t space = notifyPort->atom.size;
134 	lv2_atom_forge_set_buffer(&forge, (uint8_t*) notifyPort, space);
135 	lv2_atom_forge_sequence_head(&forge, &frame, 0);
136 
137 	// Process GUI data
138 	uint32_t last_t =0;
139 	LV2_ATOM_SEQUENCE_FOREACH(controlPort, ev)
140 	{
141 		if (lv2_atom_forge_is_object_type(&forge, ev->body.type))
142 		{
143 			const LV2_Atom_Object* obj = (const LV2_Atom_Object*)&ev->body;
144 
145 			if (obj->body.otype == urids.bangr_cursorOn) listen = true;
146 			else if (obj->body.otype == urids.bangr_cursorOff) listen = false;
147 
148 			else if (obj->body.otype == urids.patch_Set)
149 			{
150 				const LV2_Atom* property = NULL;
151       			const LV2_Atom* value    = NULL;
152 				lv2_atom_object_get
153 				(
154 					obj,
155                     urids.patch_property, &property,
156                     urids.patch_value, &value,
157                     NULL
158 				);
159 
160 				if (property && (property->type == urids.atom_URID) && value)
161 				{
162 					const uint32_t key = ((const LV2_Atom_URID*)property)->body;
163 
164 					if ((key == urids.bangr_xcursor) && (value->type == urids.atom_Float)) xcursor = ((LV2_Atom_Float*)value)->body;
165 					else if ((key == urids.bangr_ycursor) && (value->type == urids.atom_Float)) ycursor = ((LV2_Atom_Float*)value)->body;
166 				}
167 			}
168 
169 			// Play samples
170 			uint32_t next_t = (ev->time.frames < n_samples ? ev->time.frames : n_samples);
171 			play (last_t, next_t);
172 			last_t = next_t;
173 		}
174 	}
175 
176 	// Play remaining samples
177 	if (last_t < n_samples) play (last_t, n_samples);
178 
179 	// Send collected data to GUI
180 	if (!listen) notifyCursor ();
181 
182 	// Close off sequence
183 	lv2_atom_forge_pop (&forge, &frame);
184 }
185 
play(const uint32_t start,const uint32_t end)186 void BAngr::play (const uint32_t start, const uint32_t end)
187 {
188 	for (uint32_t i = start; i < end; ++i)
189 	{
190 		// Update cursor
191 		if (!listen)
192 		{
193 			if (count >= rate)
194 			{
195 				dspeedrand = bidist (rnd) * controllers[SPEED_RANGE] - speedrand;
196 				dspinrand = bidist (rnd) * controllers[SPIN_RANGE] - spinrand;
197 				count = 0.0;
198 			}
199 
200 			else count++;
201 
202 			float dspeedflex;
203 			float dspinflex;
204 			const int speedtype = controllers[SPEED_TYPE];
205 			const int spintype = controllers[SPIN_TYPE];
206 
207 			// Filter lows, mids, highs for level calculation
208 			std::array<float, NR_FLEX> s;
209 			s.fill (0.5f * (audioInput1[i] + audioInput2[i]));
210 			if ((speedtype == LOWS) || (spintype == LOWS)) s[LOWS] = lowpassFilter.process (s[LOWS]);
211 			if ((speedtype == MIDS) || (spintype == MIDS)) s[MIDS] = bandpassFilter.process (s[MIDS]);
212 			if ((speedtype == HIGHS) || (spintype == HIGHS)) s[HIGHS] = highpassFilter.process (s[HIGHS]);
213 
214 			// Calculate change in speed flexibility
215 			if (speedtype == RANDOM) dspeedflex = dspeedrand * (1.0f / (flexTime[speedtype] * rate));
216 			else
217 			{
218 				// Calculate level
219 				const float coeff = fabsf (s[speedtype]);
220 				if (coeff >= speedmaxlevel) speedmaxlevel = coeff;
221 				else speedmaxlevel = (1.0 - 1.0 / (4.0 * rate)) * speedmaxlevel;
222 				if (speedmaxlevel < 0.0001f) speedmaxlevel = 0.0001f;	// Limit to -80 db to prevent div by zero
223 				speedlevel = (1.0 - 1.0 / (flexTime[LEVEL] * rate)) * speedlevel + 1.0 / (flexTime[LEVEL] * rate) * (2.0 * coeff / speedmaxlevel);
224 
225 				dspeedflex = (2.0f * LIMIT (speedlevel, 0.0f, 1.0f) - 1.0f) * controllers[SPEED_RANGE] - speedflex;
226 
227 				// Command line meter (for debugging)
228 				/*
229 				if (int(count) % 1000 == 0)
230 				{
231 					char s[41];
232 					memset (s, ' ', 40);
233 					int x = int (40 * LIMIT (speedlevel, 0.0f, 1.0f));
234 					memset (s, '.', x);
235 					s[40] = 0;
236 					fprintf (stderr, "\r%s", s);
237 				}
238 				*/
239 			}
240 
241 			// Calculate change in spin flexibility
242 			if (spintype == RANDOM) dspinflex =  dspinrand * (1.0f / (flexTime[spintype] * rate));
243 			else
244 			{
245 				// Calculate level
246 				const float coeff = fabsf (s[spintype]);
247 				if (coeff >= spinmaxlevel) spinmaxlevel = coeff;
248 				else spinmaxlevel = (1.0 - 1.0 / (4.0 * rate)) * spinmaxlevel;
249 				if (spinmaxlevel < 0.0001f) spinmaxlevel = 0.0001f;	// Limit to -80 db to prevent div by zero
250 				const float nspinlevel = (1.0 - 1.0 / (flexTime[LEVEL] * rate)) * spinlevel + 1.0 / (flexTime[LEVEL] * rate) * (2.0 * coeff / spinmaxlevel);
251 
252 				if ((spinlevel >= 0.2f) && (nspinlevel < 0.2f)) spindir = (bidist (rnd) >= 0.0f ? spindir : -spindir);
253 				spinlevel = nspinlevel;
254 				dspinflex = spindir * LIMIT (spinlevel, 0.0f, 1.0f) * controllers[SPIN_RANGE] - spinflex;
255 			};
256 
257 			// Update speed
258 			speedrand += (1.0f / rate) * dspeedrand;
259 			speedflex += dspeedflex;
260 			speed = controllers[SPEED] + controllers[SPEED_AMOUNT] * speedflex + (1.0f - controllers[SPEED_AMOUNT]) * speedrand;
261 			speed = LIMIT (speed, 0.0f, 1.0f);
262 
263 			// Update ang
264 			spinrand += (1.0f / rate) * dspinrand;
265 			spinflex += dspinflex;
266 			spin = controllers[SPIN] + controllers[SPIN_AMOUNT] * spinflex + (1.0f - controllers[SPIN_AMOUNT]) * spinrand;
267 			spin = LIMIT (spin, -1.0f, 1.0f);
268 			ang += 2.0 * M_PI * (10.0 / rate) * spin;
269 
270 			// Calulate new positions
271 			const float dx = sinf (ang);
272 			const float dy = cosf (ang);
273 			xcursor += dx * (1.0 / rate) * speed * speed;
274 			ycursor += dy * (1.0 / rate) * speed * speed;
275 
276 			// Reflections
277 			if (xcursor < 0.0f)
278 			{
279 				xcursor = 0.0f;
280 				if (dx < 0.0f) {ang = -ang; spin = 0.0f;}
281 			}
282 
283 			else if (xcursor > 1.0f)
284 			{
285 				xcursor = 1.0f;
286 				if (dx > 0.0f) {ang = -ang; spin = 0.0f;}
287 			}
288 
289 			if (ycursor < 0.0f)
290 			{
291 				ycursor = 0.0f;
292 				if (dy < 0.0f) {ang = -M_PI - ang; spin = 0.0f;}
293 			}
294 
295 			else if (ycursor > 1.0f)
296 			{
297 				ycursor = 1.0f;
298 				if (dy > 0.0f) {ang = -M_PI - ang; spin = 0.0f;}
299 			}
300 		}
301 
302 		// Calculate params for cursor position
303 		float params[NR_PARAMS] = {0};
304 		for (int i = 0; i < NR_PARAMS; ++i)
305 		{
306 			params[i] =
307 			(
308 				((1.0f - xcursor) * (1.0f - ycursor) * controllers[FX + 0 * NR_PARAMS + i]) +
309 				((1.0f - xcursor) * ycursor * controllers[FX + 1 * NR_PARAMS + i]) +
310 				(xcursor * ycursor * controllers[FX + 2 * NR_PARAMS + i]) +
311 				(xcursor * (1.0 - ycursor) * controllers[FX + 3 * NR_PARAMS + i])
312 			);
313 		}
314 
315 		// Update fader
316 		if (fader != (1.0f - controllers[BYPASS]))
317 		{
318 			fader += (fader < 1.0f - controllers[BYPASS] ? 100.0 / rate : -100.0 / rate);
319 			fader = LIMIT (fader, 0.0f, 1.0f);
320 		}
321 
322 		// Set params and process
323 		if (fader)
324 		{
325 			float out1 = audioOutput1[i];
326 			float out2 = audioOutput2[i];
327 			xregion.setParameters (params);
328 			xregion.process (&audioInput1[i], &audioInput2[i], &out1, &out2, 1);
329 
330 			// Dry/wet mix
331 			audioOutput1[i] = fader * controllers[DRY_WET] * out1 + (1.0f - fader * controllers[DRY_WET]) * audioInput1[i];
332 			audioOutput2[i] = fader * controllers[DRY_WET] * out2 + (1.0f - fader * controllers[DRY_WET]) * audioInput2[i];
333 		}
334 
335 		else
336 		{
337 			audioOutput1[i] = audioInput1[i];
338 			audioOutput2[i] = audioInput2[i];
339 
340 		}
341 	}
342 }
343 
notifyCursor()344 void BAngr::notifyCursor()
345 {
346 	LV2_Atom_Forge_Frame frame;
347 	lv2_atom_forge_frame_time(&forge, 0);
348 	lv2_atom_forge_object(&forge, &frame, 0, urids.patch_Set);
349 	lv2_atom_forge_key(&forge, urids.patch_property);
350 	lv2_atom_forge_urid(&forge, urids.bangr_xcursor);
351 	lv2_atom_forge_key(&forge, urids.patch_value);
352 	lv2_atom_forge_float(&forge, xcursor);
353 	lv2_atom_forge_pop(&forge, &frame);
354 
355 	lv2_atom_forge_frame_time(&forge, 0);
356 	lv2_atom_forge_object(&forge, &frame, 0, urids.patch_Set);
357 	lv2_atom_forge_key(&forge, urids.patch_property);
358 	lv2_atom_forge_urid(&forge, urids.bangr_ycursor);
359 	lv2_atom_forge_key(&forge, urids.patch_value);
360 	lv2_atom_forge_float(&forge, ycursor);
361 	lv2_atom_forge_pop(&forge, &frame);
362 }
363 
state_save(LV2_State_Store_Function store,LV2_State_Handle handle,uint32_t flags,const LV2_Feature * const * features)364 LV2_State_Status BAngr::state_save (LV2_State_Store_Function store, LV2_State_Handle handle, uint32_t flags,
365 			const LV2_Feature* const* features)
366 {
367 	store (handle, urids.bangr_xcursor, &xcursor, sizeof (float), urids.atom_Float, LV2_STATE_IS_POD);
368 	store (handle, urids.bangr_ycursor, &ycursor, sizeof (float), urids.atom_Float, LV2_STATE_IS_POD);
369 	return LV2_STATE_SUCCESS;
370 }
371 
state_restore(LV2_State_Retrieve_Function retrieve,LV2_State_Handle handle,uint32_t flags,const LV2_Feature * const * features)372 LV2_State_Status BAngr::state_restore (LV2_State_Retrieve_Function retrieve, LV2_State_Handle handle, uint32_t flags,
373 			const LV2_Feature* const* features)
374 {
375 	size_t   size;
376 	uint32_t type;
377 	uint32_t valflags;
378 
379 	const void* xcursorData = retrieve(handle, urids.bangr_xcursor, &size, &type, &valflags);
380 	if (xcursorData && (type == urids.atom_Float)) xcursor = LIMIT (*(const float*)xcursorData, 0.0f, 1.0f);
381 
382 	const void* ycursorData = retrieve(handle, urids.bangr_ycursor, &size, &type, &valflags);
383 	if (ycursorData && (type == urids.atom_Float)) ycursor = LIMIT (*(const float*)ycursorData, 0.0f, 1.0f);
384 
385 	return LV2_STATE_SUCCESS;
386 }
387 
instantiate(const LV2_Descriptor * descriptor,double samplerate,const char * bundle_path,const LV2_Feature * const * features)388 static LV2_Handle instantiate (const LV2_Descriptor* descriptor, double samplerate, const char* bundle_path, const LV2_Feature* const* features)
389 {
390 	// New instance
391 	BAngr* instance;
392 	try {instance = new BAngr(samplerate, features);}
393 	catch (std::exception& exc)
394 	{
395 		fprintf (stderr, "BAngr.lv2: Plugin instantiation failed. %s\n", exc.what ());
396 		return NULL;
397 	}
398 
399 	if (!instance->map)
400 	{
401 		fprintf(stderr, "BAngr.lv2: Host does not support urid:map.\n");
402 		delete (instance);
403 		return NULL;
404 	}
405 
406 	return (LV2_Handle)instance;
407 }
408 
connect_port(LV2_Handle instance,uint32_t port,void * data)409 static void connect_port (LV2_Handle instance, uint32_t port, void *data)
410 {
411 	BAngr* inst = (BAngr*) instance;
412 	if (inst) inst->connect_port (port, data);
413 }
414 
run(LV2_Handle instance,uint32_t n_samples)415 static void run (LV2_Handle instance, uint32_t n_samples)
416 {
417 	BAngr* inst = (BAngr*) instance;
418 	if (inst) inst->run (n_samples);
419 }
420 
cleanup(LV2_Handle instance)421 static void cleanup (LV2_Handle instance)
422 {
423 	BAngr* inst = (BAngr*) instance;
424 	if (inst) delete inst;
425 }
426 
state_save(LV2_Handle instance,LV2_State_Store_Function store,LV2_State_Handle handle,uint32_t flags,const LV2_Feature * const * features)427 static LV2_State_Status state_save(LV2_Handle instance, LV2_State_Store_Function store, LV2_State_Handle handle, uint32_t flags,
428            const LV2_Feature* const* features)
429 {
430 	BAngr* inst = (BAngr*)instance;
431 	if (!inst) return LV2_STATE_SUCCESS;
432 
433 	inst->state_save (store, handle, flags, features);
434 	return LV2_STATE_SUCCESS;
435 }
436 
state_restore(LV2_Handle instance,LV2_State_Retrieve_Function retrieve,LV2_State_Handle handle,uint32_t flags,const LV2_Feature * const * features)437 static LV2_State_Status state_restore(LV2_Handle instance, LV2_State_Retrieve_Function retrieve, LV2_State_Handle handle, uint32_t flags,
438            const LV2_Feature* const* features)
439 {
440 	BAngr* inst = (BAngr*)instance;
441 	if (inst) inst->state_restore (retrieve, handle, flags, features);
442 	return LV2_STATE_SUCCESS;
443 }
444 
extension_data(const char * uri)445 static const void* extension_data(const char* uri)
446 {
447 	static const LV2_State_Interface  state  = {state_save, state_restore};
448 	if (!strcmp(uri, LV2_STATE__interface)) return &state;
449 	return NULL;
450 }
451 
452 static const LV2_Descriptor descriptor =
453 {
454 		BANGR_URI,
455 		instantiate,
456 		connect_port,
457 		NULL, //activate,
458 		run,
459 		NULL, //deactivate,
460 		cleanup,
461 		extension_data
462 };
463 
464 // LV2 Symbol Export
lv2_descriptor(uint32_t index)465 LV2_SYMBOL_EXPORT const LV2_Descriptor* lv2_descriptor(uint32_t index)
466 {
467 	switch (index)
468 	{
469 	case 0: return &descriptor;
470 	default: return NULL;
471 	}
472 }
473