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