1 /* B.Harvestr
2 * LV2 Plugin
3 *
4 * Copyright (C) 2018 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 "BHarvestr.hpp"
22 #include <ctime>
23 #include <stdexcept>
24 #include "BUtilities/stof.hpp"
25 #include "lv2/core/lv2_util.h"
26
27 #define LCG_RAND_MAX 0x7fff
28 static unsigned int g_seed;
lcg_srand(int seed)29 inline void lcg_srand (int seed) {g_seed = seed;}
lcg_rand()30 inline int lcg_rand ()
31 {
32 g_seed = (1103515245 * g_seed + 12345);
33 return (g_seed >> 16) & LCG_RAND_MAX;
34 }
35
framesToSeconds(const uint64_t frame,const double rate)36 inline double framesToSeconds (const uint64_t frame, const double rate) {return (double (frame)) / rate;}
framesToMilliseconds(const uint64_t frame,const double rate)37 inline double framesToMilliseconds (const uint64_t frame, const double rate) {return 1000.0 * (double (frame)) / rate;}
secondsToFrames(const double s,const double rate)38 inline uint64_t secondsToFrames (const double s, const double rate) {return rate * s;}
millisecondsToFrames(const double ms,const double rate)39 inline uint64_t millisecondsToFrames (const double ms, const double rate) {return rate * ms / 1000.0;}
noteToFrequency(const double note)40 inline double noteToFrequency (const double note) {return pow (2.0, (note - 69.0) / 12.0) * 440.0;}
modulatef(const float min,const float max,const float mod)41 inline float modulatef (const float min, const float max, const float mod) {return (min == max ? min : min + mod * (max - min));}
fracf(const float value)42 inline float fracf (const float value) {return value - floor (value);}
43
BHarvestr(double samplerate,const LV2_Feature * const * features)44 BHarvestr::BHarvestr (double samplerate, const LV2_Feature* const* features) :
45 map (NULL), unmap (NULL), workerSchedule (NULL),
46 controlPort (nullptr), notifyPort (nullptr),
47 audioOutput1 (nullptr), audioOutput2 (nullptr),
48 notifyForge (), notifyFrame (),
49 new_controllers {nullptr}, controllers {0},
50 pattern (), sample (nullptr), voices (),
51 lfo {Lfo()},
52 seq {Sequencer<NR_SEQ_STEPS>()},
53 shape {Shape<MAXNODES>()},
54 presetInfo {"", "", 0, "", "", "", ""},
55 rate (samplerate),
56 frame (0),
57 sampleFrame (0xFFFFFFFFFFFFFFFF), sampleSelectionFrame (0xFFFFFFFFFFFFFFFF),
58 ui_on (false),
59 activated (false),
60 notify {false, false, false, false, false, false, {false}, false, false},
61 message ("")
62
63 {
64 //Scan host features for URID map
65 LV2_URID_Map* m = NULL;
66 LV2_URID_Unmap* u = NULL;
67 for (int i = 0; features[i]; ++i)
68 {
69 if (strcmp (features[i]->URI, LV2_URID__map) == 0)
70 {
71 m = (LV2_URID_Map*) features[i]->data;
72 }
73
74 else if (strcmp (features[i]->URI, LV2_URID__unmap) == 0)
75 {
76 u = (LV2_URID_Unmap*) features[i]->data;
77 }
78
79 else if (!strcmp(features[i]->URI, LV2_WORKER__schedule))
80 {
81 workerSchedule = (LV2_Worker_Schedule*)features[i]->data;
82 }
83 }
84
85 if (!m) throw std::invalid_argument ("BHarvestr.lv2: Host does not support urid:map.");
86 if (!workerSchedule) throw std::invalid_argument ("BHarvestr.lv2: Host does not support work:schedule.");
87
88 //Map URIS
89 map = m;
90 unmap = u;
91 getURIs (m, &uris);
92
93 // Initialize notify
94 lv2_atom_forge_init (¬ifyForge, map);
95
96 // Init presetInfo
97 memset (&presetInfo, 0, sizeof (presetInfo));
98
99 // Init shapes
100 for (int i = 0; i < USER_SHAPES + NR_USER_SHAPES; ++i) shape[i].setDefaultShape ();
101 shape[SINE_SHAPE].insertNode ({CORNER_NODE, {0.001, 0.0}, {0.0, 0.0}, {0.1821, 0.0}});
102 shape[SINE_SHAPE].insertNode ({CORNER_NODE, {0.5, 1.0}, {-0.1821, 0.0}, {0.1821, 0.0}});
103 shape[SINE_SHAPE].insertNode ({CORNER_NODE, {0.999, 0.0}, {-0.1821, 0.0}, {0.0, 0.0}});
104 shape[HALF_SINE_SHAPE].insertNode ({CORNER_NODE, {0.001, 0.0}, {0.0, 0.0}, {0.1821, 0.5}});
105 shape[HALF_SINE_SHAPE].insertNode ({CORNER_NODE, {0.5, 1.0}, {-0.1821, 0.0}, {0.1821, 0.0}});
106 shape[HALF_SINE_SHAPE].insertNode ({CORNER_NODE, {0.999, 0.0}, {-0.1821, 0.5}, {0.0, 0.0}});
107 shape[TRIANGLE_SHAPE].insertNode ({POINT_NODE, {0.5, 1.0}, {0.0, 0.0}, {0.0, 0.0}});
108 shape[TRAPEZ_SHAPE].insertNode ({POINT_NODE, {0.25, 1.0}, {0.0, 0.0}, {0.0, 0.0}});
109 shape[TRAPEZ_SHAPE].insertNode ({POINT_NODE, {0.75, 1.0}, {0.0, 0.0}, {0.0, 0.0}});
110
111 // Init random engine
112 lcg_srand (time (0));
113
114 ui_on = false;
115 }
116
connect_port(uint32_t port,void * data)117 void BHarvestr::connect_port (uint32_t port, void *data)
118 {
119 switch (port)
120 {
121 case CONTROL:
122 controlPort = (LV2_Atom_Sequence*) data;
123 break;
124 case NOTIFY:
125 notifyPort = (LV2_Atom_Sequence*) data;
126 break;
127 case AUDIO_OUT_1:
128 audioOutput1 = (float*) data;
129 break;
130 case AUDIO_OUT_2:
131 audioOutput2 = (float*) data;
132 break;
133 default:
134 // Connect controllers
135 if ((port >= CONTROLLERS) && (port < CONTROLLERS + MAXCONTROLLERS)) new_controllers[port - CONTROLLERS] = (float*) data;
136 }
137 }
138
activate()139 void BHarvestr::activate() {activated = true;}
140
deactivate()141 void BHarvestr::deactivate() {activated = false;}
142
run(uint32_t n_samples)143 void BHarvestr::run (uint32_t n_samples)
144 {
145 uint32_t last_t = 0;
146
147 if ((!controlPort) || (!notifyPort) || (!audioOutput1) || (!audioOutput2)) return;
148
149 // Init notify port
150 uint32_t space = notifyPort->atom.size;
151 lv2_atom_forge_set_buffer(¬ifyForge, (uint8_t*) notifyPort, space);
152 lv2_atom_forge_sequence_head(¬ifyForge, ¬ifyFrame, 0);
153
154 // Validate controllers
155 for (int i = 0; i < MAXCONTROLLERS; ++i)
156 {
157 if (new_controllers[i])
158 {
159 float val = controllerLimits[i].validate (*(new_controllers[i]));
160 if (val != *(new_controllers[i]))
161 {
162 fprintf (stderr, "BHarvestr.lv2: Value out of range in run (): Controller#%i\n", i);
163 *(new_controllers[i]) = val;
164 // TODO update GUI controller
165 }
166
167 if (controllers[i] != val)
168 {
169 controllers[i] = val;
170
171 if (i == SAMPLE_START)
172 {
173 if (controllers[SAMPLE_END] < val) controllers[SAMPLE_END] = val;
174 notify.selectionDisplay = true;
175 }
176
177 else if (i == SAMPLE_END)
178 {
179 if (controllers[SAMPLE_START] > val) controllers[SAMPLE_START] = val;
180 notify.selectionDisplay = true;
181 }
182
183 else if (i == PATTERN_TYPE) pattern.setPattern (PatternIndex (int (val)));
184
185 else if (i == PATTERN_SIZE) pattern.setSteps (pattern.getRows() * val);
186
187 else if ((i >= LFOS) && (i < LFOS + LFO_SIZE * NR_LFOS))
188 {
189 int nr = (i - LFOS) / LFO_SIZE;
190 int param = (i - LFOS) % LFO_SIZE;
191
192 switch (param)
193 {
194 case LFO_TYPE: lfo[nr].setType (LfoIndex (int (val)));
195 break;
196
197 case LFO_FREQ: lfo[nr].setFrequency (val, framesToSeconds (frame, rate));
198 break;
199
200 case LFO_PHASE: lfo[nr].setPhase (val);
201 break;
202
203 default: break;
204 }
205 }
206
207 else if ((i >= SEQS) && (i < SEQS + SEQ_SIZE * NR_SEQS))
208 {
209 int nr = (i - SEQS) / SEQ_SIZE;
210 int param = (i - SEQS) % SEQ_SIZE;
211
212 switch (param)
213 {
214 case SEQ_CHS: seq[nr].setSize (val);
215 break;
216
217 case SEQ_FREQ: seq[nr].setFrequency (val, framesToSeconds (frame, rate));
218 break;
219
220 case SEQ_PHASE: seq[nr].setPhase (val);
221 break;
222
223 default: seq[nr].setStep (param - SEQ_STEPS, val);
224 }
225 }
226
227 // Recalculate pattern.rows_
228 if
229 (
230 (i == SAMPLE_START) ||
231 (i == SAMPLE_END) ||
232 (i == PROPERTIES + GRAIN_SIZE * PROPERTIES_SIZE + PROPERTY_VALUE_START) ||
233 (i == PROPERTIES + GRAIN_SIZE * PROPERTIES_SIZE + PROPERTY_VALUE_END)
234 )
235 {
236 if (!sample) pattern.setRows (1);
237 else
238 {
239 float grainSize =
240 (
241 controllers[PROPERTIES + GRAIN_SIZE * PROPERTIES_SIZE + PROPERTY_VALUE_START] +
242 controllers[PROPERTIES + GRAIN_SIZE * PROPERTIES_SIZE + PROPERTY_VALUE_END]
243 ) / 2.0f;
244
245 if (grainSize != 0.0f)
246 {
247 float selectionSize = (controllers[SAMPLE_END] - controllers[SAMPLE_START]) *
248 framesToSeconds(sample->info.frames, rate) * 1000.0f;
249 int grainsPerSelection = ceil (selectionSize / grainSize);
250 pattern.setRows (grainsPerSelection);
251 }
252 else pattern.setRows (1);
253 }
254 }
255 }
256 }
257 }
258
259 // Read CONTROL port (notifications from GUI and host)
260 LV2_ATOM_SEQUENCE_FOREACH (controlPort, ev)
261 {
262 if ((ev->body.type == uris.atom_Object) || (ev->body.type == uris.atom_Blank))
263 {
264 const LV2_Atom_Object* obj = (const LV2_Atom_Object*)&ev->body;
265
266 // GUI on
267 if (obj->body.otype == uris.bharvestr_uiOn)
268 {
269 ui_on = true;
270 notify.pattern = true;
271 notify.sampleDisplay = true;
272 notify.selectionDisplay = true;
273 notify.samplePath = true;
274 for (int i = 0; i < USER_SHAPES + NR_USER_SHAPES; ++i) notify.shape[i] = true;
275 notify.presetInfo = true;
276 }
277
278 // GUI off
279 else if (obj->body.otype == uris.bharvestr_uiOff) ui_on = false;
280
281 // Sample/Selection playback started/stopped
282 else if (obj->body.otype == uris.bharvestr_samplePlay) sampleFrame = 0;
283 else if (obj->body.otype == uris.bharvestr_sampleStop) sampleFrame = 0xFFFFFFFFFFFFFFFF;
284 else if (obj->body.otype == uris.bharvestr_selectionPlay) sampleSelectionFrame = 0;
285 else if (obj->body.otype == uris.bharvestr_selectionStop) sampleSelectionFrame = 0xFFFFFFFFFFFFFFFF;
286
287 // Pattern changed notifications
288 else if (obj->body.otype == uris.bharvestr_patternEvent)
289 {
290 LV2_Atom *oPr = NULL, *oPs = NULL, *oPat = NULL;
291 lv2_atom_object_get
292 (
293 obj,
294 uris.bharvestr_patternRows, &oPr,
295 uris.bharvestr_patternSteps, &oPs,
296 uris.bharvestr_pattern, &oPat,
297 NULL
298 );
299
300 if (oPr && (oPr->type == uris.atom_Int))
301 {
302 const int rows = ((const LV2_Atom_Int*)oPr)->body;
303 pattern.setRows (rows);
304 }
305
306 // Pattern notification
307 if (oPat && (oPat->type == uris.atom_Vector))
308 {
309 const LV2_Atom_Vector* vec = (const LV2_Atom_Vector*) oPat;
310 if (vec->body.child_type == uris.atom_Int)
311 {
312 const uint32_t size = (uint32_t) ((oPat->size - sizeof(LV2_Atom_Vector_Body)) / sizeof (int));
313 int* new_pattern = (int*) (&vec->body + 1);
314 pattern.setValues (new_pattern, size);
315 controllers[PATTERN_TYPE] = USER_PATTERN;
316 notify.pattern = true;
317 }
318 }
319
320 if (oPs && (oPs->type == uris.atom_Int))
321 {
322 const int steps = ((const LV2_Atom_Int*)oPs)->body;
323 pattern.setSteps (steps);
324 }
325 }
326
327 // Sample path notification -> forward to worker
328 else if (obj->body.otype == uris.bharvestr_sampleEvent)
329 {
330 LV2_Atom* oPath = NULL;
331 lv2_atom_object_get (obj, uris.bharvestr_samplePath, &oPath, NULL);
332
333 if (oPath && (oPath->type == uris.atom_Path))
334 {
335 workerSchedule->schedule_work (workerSchedule->handle, lv2_atom_total_size(&ev->body), &ev->body);
336 }
337 }
338
339 // Shape changed notifications
340 else if (obj->body.otype == uris.bharvestr_shapeEvent)
341 {
342 LV2_Atom *oId = NULL, *oData = NULL;
343 lv2_atom_object_get (obj,
344 uris.bharvestr_shapeIndex, &oId,
345 uris.bharvestr_shapeData, &oData,
346 NULL);
347
348 if (oId && (oId->type == uris.atom_Int) && oData && (oData->type == uris.atom_Vector))
349 {
350 const int index = ((const LV2_Atom_Int*)oId)->body;
351 if ((index >= USER_SHAPES) && (index < USER_SHAPES + NR_USER_SHAPES))
352 {
353 const LV2_Atom_Vector* vec = (const LV2_Atom_Vector*) oData;
354 if (vec->body.child_type == uris.atom_Float)
355 {
356 shape[index].clearShape ();
357 const uint32_t vecSize = (uint32_t) ((oData->size - sizeof(LV2_Atom_Vector_Body)) / (7 * sizeof (float)));
358 float* data = (float*) (&vec->body + 1);
359 for (unsigned int i = 0; (i < vecSize) && (i < MAXNODES); ++i)
360 {
361 Node node;
362 node.nodeType = NodeType (int (data[i * 7]));
363 node.point.x = data[i * 7 + 1];
364 node.point.y = data[i * 7 + 2];
365 node.handle1.x = data[i * 7 + 3];
366 node.handle1.y = data[i * 7 + 4];
367 node.handle2.x = data[i * 7 + 5];
368 node.handle2.y = data[i * 7 + 6];
369 shape[index].appendRawNode (node);
370 }
371 shape[index].validateShape();
372 }
373 }
374 }
375 }
376
377 // Preset info notification
378 else if (obj->body.otype ==uris.bharvestr_presetInfoEvent)
379 {
380 const LV2_Atom *oName = NULL, *oType = NULL, *oDate = NULL, *oCreator = NULL, *oUri = NULL, *oLicense = NULL, *oDescription = NULL ;
381 lv2_atom_object_get
382 (
383 obj,
384 uris.bharvestr_presetInfoName, &oName,
385 uris.bharvestr_presetInfoType, &oType,
386 uris.bharvestr_presetInfoDate, &oDate,
387 uris.bharvestr_presetInfoCreator, &oCreator,
388 uris.bharvestr_presetInfoURI, &oUri,
389 uris.bharvestr_presetInfoLicense, &oLicense,
390 uris.bharvestr_presetInfoDescription, &oDescription,
391 NULL
392 );
393
394 if (oName && (oName->type == uris.atom_String)) strncpy (presetInfo.name, (const char*)LV2_ATOM_BODY_CONST (oName), PRESETINFO_MAX_TXT_SIZE - 1);
395 if (oType && (oType->type == uris.atom_String)) strncpy (presetInfo.type, (const char*)LV2_ATOM_BODY_CONST (oType), PRESETINFO_MAX_TXT_SIZE - 1);
396 if (oDate && (oDate->type == uris.atom_Int)) presetInfo.date = ((const LV2_Atom_Int*)oDate)->body;
397 if (oCreator && (oCreator->type == uris.atom_String)) strncpy (presetInfo.creator, (const char*)LV2_ATOM_BODY_CONST (oCreator), PRESETINFO_MAX_TXT_SIZE - 1);
398 if (oUri && (oUri->type == uris.atom_String)) strncpy (presetInfo.uri, (const char*)LV2_ATOM_BODY_CONST (oUri), PRESETINFO_MAX_TXT_SIZE - 1);
399 if (oLicense && (oLicense->type == uris.atom_String)) strncpy (presetInfo.license, (const char*)LV2_ATOM_BODY_CONST (oLicense), PRESETINFO_MAX_TXT_SIZE - 1);
400 if (oDescription && (oDescription->type == uris.atom_String)) strncpy (presetInfo.description, (const char*)LV2_ATOM_BODY_CONST (oDescription), PRESETINFO_MAX_TXT_SIZE - 1);
401 }
402
403 // Keyboard
404 else if (obj->body.otype ==uris.bharvestr_keyboardEvent)
405 {
406 LV2_Atom *okOn = NULL, *okOff = NULL;
407 lv2_atom_object_get (obj,
408 uris.bharvestr_keyOn, &okOn,
409 uris.bharvestr_keyOff, &okOff,
410 NULL);
411
412 if (okOn && (okOn->type == uris.atom_Int))
413 {
414 const int note = ((const LV2_Atom_Int*)okOn)->body;
415 noteOn (note, 64, frame + ev->time.frames);
416 }
417
418 if (okOff && (okOff->type == uris.atom_Int))
419 {
420 const int note = ((const LV2_Atom_Int*)okOff)->body;
421 noteOff (note, frame + ev->time.frames);
422 }
423 }
424 }
425
426 // Read incoming MIDI_IN events
427 else if (ev->body.type == uris.midi_Event)
428 {
429 const uint8_t* const msg = (const uint8_t*)(ev + 1);
430 const uint8_t typ = lv2_midi_message_type(msg);
431 //uint8_t chn = msg[0] & 0x0F;
432
433 switch (typ)
434 {
435
436 case LV2_MIDI_MSG_NOTE_ON:
437 {
438 const uint8_t note = msg[1];
439 const uint8_t velocity = msg[2];
440 if (velocity != 0)
441 {
442 noteOn (note, velocity, frame + ev->time.frames);
443 break;
444 }
445 // Otherwise continue with note off
446 }
447 // No break here!
448
449 case LV2_MIDI_MSG_NOTE_OFF:
450 {
451 const uint8_t note = msg[1];
452 noteOff (note, frame + ev->time.frames);
453 }
454 break;
455
456 case LV2_MIDI_MSG_CONTROLLER:
457 {
458 const uint8_t cc = msg[1];
459
460 switch (cc)
461 {
462
463 // LV2_MIDI_CTL_SUSTAIN: Forward to all outputs
464 case LV2_MIDI_CTL_SUSTAIN:
465 break;
466
467 // LV2_MIDI_CTL_ALL_SOUNDS_OFF: Stop all outputs
468 case LV2_MIDI_CTL_ALL_SOUNDS_OFF:
469 allSoundsOff (frame + ev->time.frames);
470 break;
471
472 // LV2_MIDI_CTL_ALL_NOTES_OFF: Stop all voices
473 case LV2_MIDI_CTL_ALL_NOTES_OFF:
474 allNotesOff (frame + ev->time.frames);
475 break;
476
477 // All other MIDI signals
478 default: break;
479 }
480 }
481
482 default: break;
483 }
484 }
485
486 else fprintf (stderr, "BHarvestr.lv2: Ignored event in Control port (otype = %i, %s)\n", ev->body.type,
487 (unmap ? unmap->unmap (unmap->handle, ev->body.type) : NULL));
488
489 // Update for this iteration
490 uint32_t next_t = (ev->time.frames < n_samples ? ev->time.frames : n_samples);
491 play (last_t, next_t);
492 last_t = next_t;
493 }
494
495 // Update for the remainder of the cycle
496 if (last_t < n_samples) play (last_t, n_samples);
497
498 // Update position in case of no new barBeat submitted on next call
499 frame += n_samples;
500
501 if (ui_on)
502 {
503 notifyStatusToGui ();
504 if (notify.sampleStop) notifySampleStopToGui();
505 if (notify.selectionStop) notifySelectionStopToGui();
506 if (notify.pattern) notifyPatternToGui();
507 if (notify.sampleDisplay || notify.selectionDisplay) notifyDisplayToGui();
508 if (notify.samplePath) notifySamplePathToGui();
509 for (int i = 0; i < USER_SHAPES + NR_USER_SHAPES; ++i)
510 {
511 if (notify.shape[i]) notifyShapeToGui (ShapeIndex (i));
512 }
513 if (notify.presetInfo) notifyPresetInfoToGui();
514 if (notify.message) notifyMessageToGui();
515 }
516 lv2_atom_forge_pop(¬ifyForge, ¬ifyFrame);
517 }
518
state_save(LV2_State_Store_Function store,LV2_State_Handle handle,uint32_t flags,const LV2_Feature * const * features)519 LV2_State_Status BHarvestr::state_save (LV2_State_Store_Function store, LV2_State_Handle handle, uint32_t flags,
520 const LV2_Feature* const* features)
521 {
522 LV2_State_Map_Path* map_path = NULL;
523 for (int i = 0; features[i]; ++i)
524 {
525 if (!strcmp(features[i]->URI, LV2_STATE__mapPath))
526 {
527 map_path = (LV2_State_Map_Path*)features[i]->data;
528 break;
529 }
530 }
531
532 if (!map_path)
533 {
534 fprintf (stderr, "BHarvestr.lv2: Feature map_path not available! Can't save plugin status!\n" );
535 return LV2_STATE_ERR_NO_FEATURE;
536 }
537
538 // Save sample path
539 if (sample && sample->path)
540 {
541 char* abstrPath = map_path->abstract_path(map_path->handle, sample->path);
542 store(handle, uris.bharvestr_samplePath, abstrPath, strlen (sample->path) + 1, uris.atom_Path, LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE);
543 free (abstrPath);
544 }
545
546 // Save preset data
547 if (presetInfo.name[0] != '\0') store (handle, uris.bharvestr_presetInfoName, presetInfo.name, strlen (presetInfo.name) + 1, uris.atom_String, LV2_STATE_IS_POD);
548 if (presetInfo.type[0] != '\0') store (handle, uris.bharvestr_presetInfoType, presetInfo.type, strlen (presetInfo.type) + 1, uris.atom_String, LV2_STATE_IS_POD);
549 if (presetInfo.date != 0) store (handle, uris.bharvestr_presetInfoDate, &presetInfo.date, sizeof(presetInfo.date), uris.atom_Int, LV2_STATE_IS_POD);
550 if (presetInfo.creator[0] != '\0') store (handle, uris.bharvestr_presetInfoCreator, presetInfo.creator, strlen (presetInfo.creator) + 1, uris.atom_String, LV2_STATE_IS_POD);
551 if (presetInfo.uri[0] != '\0') store (handle, uris.bharvestr_presetInfoURI, presetInfo.uri, strlen (presetInfo.uri) + 1, uris.atom_String, LV2_STATE_IS_POD | LV2_STATE_IS_POD);
552 if (presetInfo.license[0] != '\0') store (handle, uris.bharvestr_presetInfoLicense, presetInfo.license, strlen (presetInfo.license) + 1, uris.atom_String, LV2_STATE_IS_POD);
553 if (presetInfo.description[0] != '\0') store (handle, uris.bharvestr_presetInfoDescription, presetInfo.description, strlen (presetInfo.description) + 1, uris.atom_String, LV2_STATE_IS_POD);
554
555
556 // Store pattern
557 if (controllers[PATTERN_TYPE] == USER_PATTERN)
558 {
559 char patternDataString[0x4010] = "\nPattern data:\n";
560 const int patternSteps = pattern.getSteps();
561 const int patternRows = pattern.getRows();
562
563 for (int s = 0; s < MAXPATTERNSTEPS; ++s)
564 {
565 char valueString[16];
566 int val = pattern.getValue (s);
567 snprintf (valueString, 14, "val:%d;", val);
568 if (s % 8 == 7) strcat (valueString, "\n");
569 else strcat (valueString, " ");
570 strcat (patternDataString, valueString);
571 }
572 store (handle, uris.bharvestr_patternRows, &patternRows, sizeof(patternRows), uris.atom_Int, LV2_STATE_IS_POD);
573 store (handle, uris.bharvestr_patternSteps, &patternSteps, sizeof(patternSteps), uris.atom_Int, LV2_STATE_IS_POD);
574 store (handle, uris.bharvestr_pattern, patternDataString, strlen (patternDataString) + 1, uris.atom_String, LV2_STATE_IS_POD);
575 }
576
577 // Store shapes
578 {
579 char shapesDataString[0x8010] = "Shape data:\n";
580
581 for (int sh = USER_SHAPES; sh < USER_SHAPES + NR_USER_SHAPES; ++sh)
582 {
583 for (unsigned int nd = 0; nd < shape[sh].size (); ++nd)
584 {
585 char valueString[160];
586 Node node = shape[sh].getNode (nd);
587 snprintf
588 (
589 valueString,
590 126,
591 "shp:%d; typ:%d; ptx:%f; pty:%f; h1x:%f; h1y:%f; h2x:%f; h2y:%f",
592 sh,
593 int (node.nodeType),
594 node.point.x,
595 node.point.y,
596 node.handle1.x,
597 node.handle1.y,
598 node.handle2.x,
599 node.handle2.y
600 );
601 if ((sh < USER_SHAPES + NR_USER_SHAPES - 1) || (nd < shape[sh].size ())) strcat (valueString, ";\n");
602 else strcat(valueString, "\n");
603 strcat (shapesDataString, valueString);
604 }
605 }
606 store (handle, uris.bharvestr_shapeData, shapesDataString, strlen (shapesDataString) + 1, uris.atom_String, LV2_STATE_IS_POD);
607 }
608
609 return LV2_STATE_SUCCESS;
610 }
611
state_restore(LV2_State_Retrieve_Function retrieve,LV2_State_Handle handle,uint32_t flags,const LV2_Feature * const * features)612 LV2_State_Status BHarvestr::state_restore (LV2_State_Retrieve_Function retrieve, LV2_State_Handle handle, uint32_t flags,
613 const LV2_Feature* const* features)
614 {
615 // Get host features
616 LV2_Worker_Schedule* schedule = nullptr;
617 LV2_State_Map_Path* mapPath = nullptr;
618 const char* missing = lv2_features_query
619 (
620 features,
621 LV2_STATE__mapPath, &mapPath, true,
622 LV2_WORKER__schedule, &schedule, false,
623 nullptr
624 );
625
626 if (missing)
627 {
628 fprintf (stderr, "BJumblr.lv2: Host doesn't support required features.\n");
629 return LV2_STATE_ERR_NO_FEATURE;
630 }
631
632 size_t size;
633 uint32_t type;
634 uint32_t valflags;
635
636 // Retireve sample data
637 {
638 char samplePath[PATH_MAX] = {0};
639
640 const void* pathData = retrieve (handle, uris.bharvestr_samplePath, &size, &type, &valflags);
641 if (pathData)
642 {
643 const char* absPath = mapPath->absolute_path (mapPath->handle, (char*)pathData);
644 if (absPath)
645 {
646 if (strlen (absPath) < PATH_MAX) strcpy (samplePath, absPath);
647 else fprintf (stderr, "BHarvestr.lv2: Sample path too long.\n");
648 }
649 }
650
651 if (activated && schedule)
652 {
653 LV2_Atom_Forge forge;
654 lv2_atom_forge_init(&forge, map);
655 uint8_t buf[1200];
656 lv2_atom_forge_set_buffer(&forge, buf, sizeof(buf));
657 LV2_Atom_Forge_Frame frame;
658 LV2_Atom* msg = (LV2_Atom*)forgeSamplePath (&forge, &frame, samplePath);
659 lv2_atom_forge_pop(&forge, &frame);
660 if (msg) schedule->schedule_work(schedule->handle, lv2_atom_total_size(msg), msg);
661 }
662
663 else
664 {
665 Sample* s = loadSample (samplePath);
666 if (s)
667 {
668 if (sample) delete sample;
669 installSample (s);
670 }
671 }
672 }
673
674 // Retrieve preset data
675 const void* presetNameData = retrieve (handle, uris.bharvestr_presetInfoName, &size, &type, &valflags);
676 if (presetNameData)
677 {
678 const char* str = (const char*)presetNameData;
679 strncpy (presetInfo.name, str, LIMIT (strlen (str) + 1, 0, PRESETINFO_MAX_TXT_SIZE - 1));
680 notify.presetInfo = true;
681 }
682
683 const void* presetTypeData = retrieve (handle, uris.bharvestr_presetInfoType, &size, &type, &valflags);
684 if (presetTypeData)
685 {
686 const char* str = (const char*)presetTypeData;
687 strncpy (presetInfo.type, str, LIMIT (strlen (str) + 1, 0, PRESETINFO_MAX_TXT_SIZE - 1));
688 notify.presetInfo = true;
689 }
690
691 const void* presetDateData = retrieve (handle, uris.bharvestr_presetInfoDate, &size, &type, &valflags);
692 if (presetDateData)
693 {
694 presetInfo.date = *(int*)presetDateData;
695 notify.presetInfo = true;
696 }
697
698 const void* presetCreatorData = retrieve (handle, uris.bharvestr_presetInfoCreator, &size, &type, &valflags);
699 if (presetNameData)
700 {
701 const char* str = (const char*)presetCreatorData;
702 strncpy (presetInfo.creator, str, LIMIT (strlen (str) + 1, 0, PRESETINFO_MAX_TXT_SIZE - 1));
703 notify.presetInfo = true;
704 }
705
706 const void* presetUriData = retrieve (handle, uris.bharvestr_presetInfoURI, &size, &type, &valflags);
707 if (presetUriData)
708 {
709 const char* str = (const char*)presetUriData;
710 strncpy (presetInfo.uri, str, LIMIT (strlen (str) + 1, 0, PRESETINFO_MAX_TXT_SIZE - 1));
711 notify.presetInfo = true;
712 }
713
714 const void* presetLicenseData = retrieve (handle, uris.bharvestr_presetInfoLicense, &size, &type, &valflags);
715 if (presetLicenseData)
716 {
717 const char* str = (const char*)presetLicenseData;
718 strncpy (presetInfo.license, str, LIMIT (strlen (str) + 1, 0, PRESETINFO_MAX_TXT_SIZE - 1));
719 notify.presetInfo = true;
720 }
721
722 const void* presetDescriptionData = retrieve (handle, uris.bharvestr_presetInfoDescription, &size, &type, &valflags);
723 if (presetDescriptionData)
724 {
725 const char* str = (const char*)presetDescriptionData;
726 strncpy (presetInfo.description, str, LIMIT (strlen (str) + 1, 0, PRESETINFO_MAX_TXT_SIZE - 1));
727 notify.presetInfo = true;
728 }
729
730 // Retrieve pattern data
731 const void* patternRowsData = retrieve (handle, uris.bharvestr_patternRows, &size, &type, &valflags);
732 if (patternRowsData)
733 {
734 const int rows = *(int*)patternRowsData;
735 pattern.setRows (rows);
736 }
737
738 const void* patternStepsData = retrieve (handle, uris.bharvestr_patternSteps, &size, &type, &valflags);
739 if (patternStepsData)
740 {
741 const int steps = *(int*)patternStepsData;
742 pattern.setSteps (steps);
743 }
744
745 const void* patternData = retrieve (handle, uris.bharvestr_pattern, &size, &type, &valflags);
746 if (patternData)
747 {
748 std::string str = (char*)patternData;
749
750 // Parse retrieved data
751 int step = 1;
752 std::vector<int> data = {};
753 while (!str.empty())
754 {
755 // Look for next "val:"
756 size_t strPos = str.find ("val:");
757 size_t nextPos = 0;
758 if (strPos == std::string::npos) break; // No "val:" found => end
759 if (strPos + 4 > str.length()) break; // Nothing more after "val:" => end
760 str.erase (0, strPos + 4);
761 if (step > MAXPATTERNSTEPS)
762 {
763 fprintf (stderr, "BHarvestr.lv2: Max. pattern size exceeded. Pattern data truncated at step %i.\n", step);
764 break;
765 }
766 int val;
767 try {val = BUtilities::stof (str, &nextPos);}
768 catch (const std::exception& e)
769 {
770 fprintf (stderr, "BHarvestr.lv2: Restore pattern incomplete. Can't parse step %i from \"%s...\"", step, str.substr (0, 63).c_str());
771 break;
772 }
773
774 if (nextPos > 0) str.erase (0, nextPos);
775 if ((val < 0) || (val >= MAXPATTERNSTEPS))
776 {
777 fprintf (stderr, "BHarvestr.lv2: Restore pattern incomplete. Invalid matrix data loaded for step %i.\n", step);
778 break;
779 }
780 data.push_back (val);
781 ++step;
782 }
783
784 // Set pattern
785 pattern.setPattern (USER_PATTERN);
786 pattern.setValues (data);
787 controllers[PATTERN_TYPE] = USER_PATTERN;
788 notify.pattern = true;
789 }
790
791 // Retrieve shapes
792 const void* shapesData = retrieve(handle, uris.bharvestr_shapeData, &size, &type, &valflags);
793 if (shapesData && (type == uris.atom_String))
794 {
795 // Clear old shapes first
796 for (int sh = USER_SHAPES; sh < USER_SHAPES + NR_USER_SHAPES; ++sh) shape[sh].clearShape();
797
798 // Parse retrieved data
799 std::string shapesDataString = (char*) shapesData;
800 const std::string keywords[8] = {"shp:", "typ:", "ptx:", "pty:", "h1x:", "h1y:", "h2x:", "h2y:"};
801 while (!shapesDataString.empty())
802 {
803 // Look for next "shp:"
804 size_t strPos = shapesDataString.find ("shp:");
805 size_t nextPos = 0;
806 if (strPos == std::string::npos) break; // No "shp:" found => end
807 if (strPos + 4 > shapesDataString.length()) break; // Nothing more after id => end
808 shapesDataString.erase (0, strPos + 4);
809
810 int sh;
811 try {sh = BUtilities::stof (shapesDataString, &nextPos);}
812 catch (const std::exception& e)
813 {
814 fprintf (stderr, "BHarvestr.lv2: Restore shape state incomplete. Can't parse shape number from \"%s...\"", shapesDataString.substr (0, 63).c_str());
815 break;
816 }
817
818 if (nextPos > 0) shapesDataString.erase (0, nextPos);
819 if ((sh < 0) || (sh >= USER_SHAPES + NR_USER_SHAPES))
820 {
821 fprintf (stderr, "BHarvestr.lv2: Restore shape state incomplete. Invalid matrix data block loaded for shape %i.\n", sh);
822 break;
823 }
824
825 // Look for shape data
826 Node node = {NodeType::POINT_NODE, {0, 0}, {0, 0}, {0, 0}};
827 bool isTypeDef = false;
828 for (int i = 1; i < 9; ++i)
829 {
830 strPos = shapesDataString.find (keywords[i]);
831 if (strPos == std::string::npos) continue; // Keyword not found => next keyword
832 if (strPos + 4 >= shapesDataString.length()) // Nothing more after keyword => end
833 {
834 shapesDataString ="";
835 break;
836 }
837 if (strPos > 0) shapesDataString.erase (0, strPos + 4);
838 float val;
839 try {val = BUtilities::stof (shapesDataString, &nextPos);}
840 catch (const std::exception& e)
841 {
842 fprintf (stderr, "Harvestr.lv2: Restore shape state incomplete. Can't parse %s from \"%s...\"",
843 keywords[i].substr(0,3).c_str(), shapesDataString.substr (0, 63).c_str());
844 break;
845 }
846
847 if (nextPos > 0) shapesDataString.erase (0, nextPos);
848 switch (i)
849 {
850 case 1: node.nodeType = (NodeType)((int)val);
851 isTypeDef = true;
852 break;
853 case 2: node.point.x = val;
854 break;
855 case 3: node.point.y = val;
856 break;
857 case 4: node.handle1.x = val;
858 break;
859 case 5: node.handle1.y = val;
860 break;
861 case 6: node.handle2.x = val;
862 break;
863 case 7: node.handle2.y = val;
864 break;
865 default:break;
866 }
867 }
868
869 // Set data
870 if (isTypeDef) shape[sh].appendNode (node);
871 }
872
873 // Validate all shapes
874 for (int sh = USER_SHAPES; sh < USER_SHAPES + NR_USER_SHAPES; ++sh)
875 {
876 if (shape[sh].size () < 2) shape[sh].setDefaultShape ();
877 else if (!shape[sh].validateShape ()) shape[sh].setDefaultShape ();
878 }
879
880 // Force GUI notification
881 for (int sh = USER_SHAPES; sh < USER_SHAPES + NR_USER_SHAPES; ++sh) notify.shape[sh] = true;
882 }
883
884 return LV2_STATE_SUCCESS;
885 }
886
work(LV2_Worker_Respond_Function respond,LV2_Worker_Respond_Handle handle,uint32_t size,const void * data)887 LV2_Worker_Status BHarvestr::work (LV2_Worker_Respond_Function respond, LV2_Worker_Respond_Handle handle, uint32_t size, const void* data)
888 {
889 const LV2_Atom* atom = (const LV2_Atom*)data;
890
891 // Free old sample
892 if (atom->type == uris.bharvestr_sampleFreeEvent)
893 {
894 const LV2_Atom_Ptr* workerMessage = (LV2_Atom_Ptr*) atom;
895 if (workerMessage && workerMessage->data) delete (Sample*)workerMessage->data;
896 }
897
898 // Load sample
899 else
900 {
901 const LV2_Atom_Object* obj = (const LV2_Atom_Object*)data;
902
903
904 // Sample path event
905 if (obj->body.otype == uris.bharvestr_sampleEvent)
906 {
907 const LV2_Atom* path = NULL;
908 lv2_atom_object_get(obj, uris.bharvestr_samplePath, &path, 0);
909
910 if (path && (path->type == uris.atom_Path))
911 {
912 Sample* s = loadSample ((const char*)LV2_ATOM_BODY_CONST(path));
913
914 if (s)
915 {
916 LV2_Atom_Ptr responseMessage = LV2_Atom_Ptr {{sizeof (Sample*), uris.bharvestr_sampleSetEvent}, s};
917 respond (handle, sizeof(responseMessage), &responseMessage);
918 }
919 }
920
921 else return LV2_WORKER_ERR_UNKNOWN;
922 }
923 }
924
925 return LV2_WORKER_SUCCESS;
926 }
927
work_response(uint32_t size,const void * data)928 LV2_Worker_Status BHarvestr::work_response (uint32_t size, const void* data)
929 {
930 const LV2_Atom* atom = (const LV2_Atom*)data;
931
932 // Set sample
933 if (atom->type == uris.bharvestr_sampleSetEvent)
934 {
935 // Schedule free old sample
936 LV2_Atom_Ptr workerMessage = LV2_Atom_Ptr {{sizeof (Sample*), uris.bharvestr_sampleFreeEvent}, sample};
937 workerSchedule->schedule_work (workerSchedule->handle, sizeof (workerMessage), &workerMessage);
938
939 // Install new sample from data
940 const LV2_Atom_Ptr* atom_ptr = (const LV2_Atom_Ptr*) atom;
941 installSample ((Sample*) atom_ptr->data);
942 }
943
944 else fprintf(stderr, "B.Harvestr.lv2: Worker response unknown.\n");
945 return LV2_WORKER_SUCCESS;
946 }
947
loadSample(const char * path)948 Sample* BHarvestr::loadSample (const char* path)
949 {
950 Sample* s = nullptr;
951 try {s = new Sample (path);}
952 catch (std::bad_alloc &ba)
953 {
954 fprintf (stderr, "BHarvestr.lv2: Can't allocate enough memory to open sample file.\n");
955 strcpy (message, "BHarvestr.lv2: Can't allocate enough memory to open sample file.");
956 notify.message = true;
957 }
958 catch (std::invalid_argument &ia)
959 {
960 fprintf (stderr, "%s\n", ia.what());
961 strcpy (message, ia.what());
962 notify.message = true;
963 }
964 return s;
965 }
966
installSample(Sample * s)967 void BHarvestr::installSample (Sample* s)
968 {
969 sample = s;
970 sampleFrame = 0xFFFFFFFFFFFFFFFF;
971 sampleSelectionFrame = 0xFFFFFFFFFFFFFFFF;
972 notify.sampleDisplay = true;
973 notify.selectionDisplay = true;
974 notify.sampleStop = true;
975 notify.selectionStop = true;
976
977 // Recalculate pattern.rows_
978 if (sample)
979 {
980 float grainSize =
981 (
982 controllers[PROPERTIES + GRAIN_SIZE * PROPERTIES_SIZE + PROPERTY_VALUE_START] +
983 controllers[PROPERTIES + GRAIN_SIZE * PROPERTIES_SIZE + PROPERTY_VALUE_END]
984 ) / 2.0f;
985
986 if (grainSize != 0.0f)
987 {
988 float selectionSize = (controllers[SAMPLE_END] - controllers[SAMPLE_START]) *
989 framesToSeconds(sample->info.frames, rate) * 1000.0f;
990 int grainsPerSelection = ceil (selectionSize / grainSize);
991 pattern.setRows (grainsPerSelection);
992 }
993 else pattern.setRows (1);
994 }
995 else pattern.setRows (1);
996 }
997
noteOn(const uint8_t note,const uint8_t velocity,const uint64_t frame)998 void BHarvestr::noteOn (const uint8_t note, const uint8_t velocity, const uint64_t frame)
999 {
1000 bool newNote = true;
1001
1002 // Scan if this is an additional midi message
1003 // (e.g., double note on, velocity changed)
1004 for (Voice** it = voices.begin(); it < voices.end(); ++it)
1005 {
1006 if (((**it).note == note) && (frame < (**it).endFrame))
1007 {
1008 (**it).velocity = velocity;
1009 newNote = false;
1010 break;
1011 }
1012 }
1013
1014 // New voice
1015 if (newNote && (voices.size < controllers[MAX_VOICES]))
1016 {
1017 // Copy envelope data from controllers
1018 Envelope env[NR_ENVS];
1019 for (int i = 0; i < NR_ENVS; ++i)
1020 {
1021 env[i] = Envelope
1022 (
1023 controllers[ENVS + i * ENV_SIZE + ENV_ATTACK],
1024 controllers[ENVS + i * ENV_SIZE + ENV_DECAY],
1025 controllers[ENVS + i * ENV_SIZE + ENV_SUSTAIN],
1026 controllers[ENVS + i * ENV_SIZE + ENV_RELEASE]
1027 );
1028 }
1029
1030 // Calculate release frames for each voice
1031 uint64_t releaseFrames = secondsToFrames (4.0, rate);
1032 for (int i = 0; i < NR_PROPERTY_MODULATORS; ++i)
1033 {
1034 int modNr = controllers[SYNTH + SYNTH_LEVEL * PROPERTIES_SIZE + PROPERTY_MODULATORS + i];
1035 if (modNr == MODULATOR_NONE) break;
1036 if ((modNr >= MODULATOR_ENV1) && (modNr <= MODULATOR_ENV4))
1037 {
1038 int envNr = modNr - MODULATOR_ENV1;
1039 double iReleaseSeconds = env[envNr].getRelease();
1040 uint64_t iReleaseFrames = secondsToFrames (iReleaseSeconds, rate);
1041 if (iReleaseFrames < releaseFrames) releaseFrames = iReleaseFrames;
1042 }
1043 }
1044
1045 // Add new voice
1046 Voice voice = Voice (note, velocity, frame, 0xFFFFFFFF00000000, releaseFrames, env);
1047 voice.grains.push_back (Grain {frame, 0xFFFFFFFF00000000, 0ul, 0l, 0.0, 0.0, 0.0});
1048 voices.push_back (voice);
1049 }
1050 }
1051
noteOff(const uint8_t note,const uint64_t frame)1052 void BHarvestr::noteOff (const uint8_t note, const uint64_t frame)
1053 {
1054 for (Voice** it = voices.begin(); it < voices.end(); ++it)
1055 {
1056 if (((**it).note == note) && (frame < (**it).endFrame))
1057 {
1058 (**it).endFrame = frame;
1059 const double pos = framesToSeconds (frame - (**it).startFrame, rate);
1060 for (int i = 0; i < NR_ENVS; ++i) (**it).envelope[i].releaseAt (pos);
1061 }
1062 }
1063 }
1064
allSoundsOff(const uint64_t frame)1065 void BHarvestr::allSoundsOff (const uint64_t frame)
1066 {
1067 // TODO
1068 voices.clear();
1069 }
1070
allNotesOff(const uint64_t frame)1071 void BHarvestr::allNotesOff (const uint64_t frame)
1072 {
1073 for (Voice** it = voices.begin(); it < voices.end(); ++it)
1074 {
1075 if (frame < (**it).endFrame)
1076 {
1077 (**it).endFrame = frame;
1078 const double pos = framesToSeconds (frame - (**it).startFrame, rate);
1079 for (int i = 0; i < NR_ENVS; ++i) (**it).envelope[i].releaseAt (pos);
1080 }
1081 }
1082 }
1083
play(const int start,const int end)1084 void BHarvestr::play (const int start, const int end)
1085 {
1086 if (end < start) return;
1087 if ((!sample) || (!sample->data))
1088 {
1089 memset (&audioOutput1[start], 0, (end - start) * sizeof (float));
1090 memset (&audioOutput2[start], 0, (end - start) * sizeof (float));
1091 return;
1092 }
1093
1094 for (int i = start; i < end; ++i)
1095 {
1096 uint64_t iframe = frame + i;
1097 float isample1 = 0.0f;
1098 float isample2 = 0.0f;
1099
1100 // Sample playback?
1101 if (sampleFrame != 0xFFFFFFFFFFFFFFFF)
1102 {
1103 if (sampleFrame >= uint64_t (sample->info.frames))
1104 {
1105 sampleFrame = 0xFFFFFFFFFFFFFFFF;
1106 notify.sampleStop = true;
1107 }
1108 else
1109 {
1110 isample1 += sample->data[sampleFrame * sample->info.channels];
1111 isample2 += sample->data[sampleFrame * sample->info.channels];
1112 ++sampleFrame;
1113 }
1114 }
1115
1116 // Selection playback?
1117 if (sampleSelectionFrame != 0xFFFFFFFFFFFFFFFF)
1118 {
1119 uint64_t start = controllers[SAMPLE_START] * sample->info.frames;
1120 uint64_t size = (controllers[SAMPLE_END] - controllers[SAMPLE_START]) * sample->info.frames;
1121 if ((sampleSelectionFrame >= size) || (start + sampleSelectionFrame >= uint64_t (sample->info.frames)))
1122 {
1123 sampleSelectionFrame = 0xFFFFFFFFFFFFFFFF;
1124 notify.selectionStop = true;
1125 }
1126 else
1127 {
1128 isample1 += sample->data[(start + sampleSelectionFrame) * sample->info.channels];
1129 isample2 += sample->data[(start + sampleSelectionFrame) * sample->info.channels];
1130 ++sampleSelectionFrame;
1131 }
1132 }
1133
1134 for (size_t v = 0; v < voices.size; ++v)
1135 {
1136 Voice& voice = voices[v];
1137
1138 // Play only active voices
1139 if ((iframe >= voice.startFrame) && (iframe <= voice.endFrame + voice.releaseFrames))
1140 {
1141
1142 float vsample1 = 0.0f;
1143 float vsample2 = 0.0f;
1144
1145 // Remove outtimed grains
1146 bool done;
1147 do
1148 {
1149 done = true;
1150 for (Grain** git = voice.grains.begin (); git < voice.grains.end(); ++git)
1151 {
1152 if ((**git).endFrame < iframe)
1153 {
1154 voice.grains.erase (git);
1155 done = false;
1156 break;
1157 }
1158 }
1159 } while (!done);
1160
1161
1162 // Seed new grains
1163 if ((voice.grains.size > 0) && (voice.grains.back().startFrame <= iframe))
1164 {
1165 Grain& grain = voice.grains.back();
1166
1167 // Calculate pattern position first
1168 uint64_t grainStartFrame;
1169 uint64_t selectionFrames = (controllers[SAMPLE_END] - controllers[SAMPLE_START]) * sample->info.frames;
1170 uint64_t patternFrames = double (selectionFrames) * controllers[PATTERN_SIZE];
1171 double grainMs = controllers[PROPERTIES + GRAIN_SIZE * PROPERTIES_SIZE + PROPERTY_VALUE_START];
1172 int64_t grainFrames = millisecondsToFrames (grainMs, rate);
1173
1174 if (iframe - voice.patternStartFrame > patternFrames) voice.patternStartFrame = iframe;
1175 if (grainFrames <= 0) grainStartFrame = controllers[SAMPLE_START] * sample->info.frames;
1176 else
1177 {
1178 int patternStep = double (iframe - voice.patternStartFrame) / double (grainFrames);
1179 patternStep = LIMIT (patternStep, 0, MAXPATTERNSTEPS - 1);
1180 int grainStep = pattern.getValue (patternStep);
1181 grainStartFrame = controllers[SAMPLE_START] * sample->info.frames + grainStep * grainFrames;
1182 }
1183
1184
1185 // Set modulated grain properties
1186 float graintune = getModulation (&voice, PROPERTIES + GRAIN_TUNE * PROPERTIES_SIZE, iframe);
1187 float grainfine = getModulation (&voice, PROPERTIES + GRAIN_FINE * PROPERTIES_SIZE, iframe);
1188 grain.speed = noteToFrequency(float (voice.note) + graintune + 0.01 * grainfine) / controllers[SAMPLE_FREQ];
1189
1190 float grainsize = getModulation (&voice, PROPERTIES + GRAIN_SIZE * PROPERTIES_SIZE, iframe);
1191 grain.endFrame = grain.startFrame + millisecondsToFrames (grainsize, rate) * grain.speed;
1192
1193 float phase = getModulation (&voice, PROPERTIES + GRAIN_PHASE * PROPERTIES_SIZE, iframe);
1194 grain.sampleStartFrame = grainStartFrame + grain.driveFrames - grainsize * phase;
1195
1196 grain.level = getModulation (&voice, PROPERTIES + GRAIN_LEVEL * PROPERTIES_SIZE, iframe);
1197 grain.pan = getModulation (&voice, PROPERTIES + GRAIN_PAN * PROPERTIES_SIZE, iframe);
1198
1199
1200 // Reserve next grain
1201 float grainrate = getModulation (&voice, PROPERTIES + GRAIN_RATE * PROPERTIES_SIZE, iframe);
1202 double diffframes = double (grain.endFrame - grain.startFrame) / grainrate;
1203 uint64_t nextframe = iframe + diffframes;
1204
1205 float graindrive = getModulation (&voice, PROPERTIES + GRAIN_DRIVE * PROPERTIES_SIZE, iframe);
1206 int64_t nextdriveframes = int64_t (grain.driveFrames + graindrive * diffframes) % grainFrames ;
1207
1208 voice.grains.push_back(Grain {nextframe , 0xFFFFFFFF00000000, 0ul, nextdriveframes, 0.0, 0.0, 0.0});
1209
1210 // Kick out first grain if grains full
1211 while (voice.grains.size > controllers[MAX_GRAINS_PER_VOICE]) voice.grains.pop_front();
1212 }
1213
1214
1215 // Render
1216 for (int g = 0; g < int (voice.grains.size); ++g)
1217 {
1218 Grain& grain = voice.grains[g];
1219
1220 if ((iframe >= grain.startFrame) && (iframe <= grain.endFrame))
1221 {
1222 double pos = grain.sampleStartFrame + double (iframe - grain.startFrame) * grain.speed;
1223 uint64_t p0 = pos;
1224 double pfrac = pos - p0;
1225
1226 if (int64_t (p0 + 1) < sample->info.frames)
1227 {
1228 double relpos =
1229 (
1230 grain.endFrame > grain.startFrame ?
1231 double (iframe - grain.startFrame) / double (grain.endFrame - grain.startFrame) :
1232 0
1233 );
1234 // Get raw sample
1235 float s0 = sample->data[p0 * sample->info.channels];
1236 float s1 = sample->data[(p0 + 1) * sample->info.channels];
1237 float psample = s0 + (s1 - s0) * pfrac;
1238 // Apply shape
1239 psample *= shape[int (controllers[GRAIN_SHAPE])].getMapRawValue (relpos);
1240 // Set level
1241 psample *= grain.level;
1242 // Set panning
1243 float psample1 = psample * (grain.pan < 0 ? grain.pan + 1 : 1);
1244 float psample2 = psample * (grain.pan < 0 ? 1 : 1 - grain.pan);
1245
1246 // Add to vsample
1247 vsample1 += psample1;
1248 vsample2 += psample2;
1249 }
1250 }
1251 }
1252
1253 // Apply envelope and add to isample
1254 float f = getModulation (&voice, SYNTH + SYNTH_LEVEL * PROPERTIES_SIZE, iframe);
1255 isample1 += vsample1 * f;
1256 isample2 += vsample2 * f;
1257 }
1258 }
1259
1260 // Write to audio out
1261 audioOutput1[i] = isample1;
1262 audioOutput2[i] = isample2;
1263 }
1264
1265 // Cleanup release-ended voices
1266 bool done;
1267 do
1268 {
1269 done = true;
1270 for (Voice** vit = voices.begin (); vit < voices.end(); ++vit)
1271 {
1272 if ((**vit).endFrame + (**vit).releaseFrames < frame + end)
1273 {
1274 voices.erase (vit);
1275 done = false;
1276 break;
1277 }
1278 }
1279 } while (!done);
1280 }
1281
getModulation(const Voice * voiceptr,const int property,const uint64_t frame) const1282 double BHarvestr::getModulation (const Voice* voiceptr, const int property, const uint64_t frame) const
1283 {
1284 float start = controllers[property + PROPERTY_VALUE_START];
1285 float end = controllers[property + PROPERTY_VALUE_END];
1286 float factor = (controllers[property + PROPERTY_MODULATORS] == 0.0f ? 0.0f : 1.0f);
1287
1288 for (int i = 0; i < NR_PROPERTY_MODULATORS; ++i)
1289 {
1290 int mod = controllers[property + PROPERTY_MODULATORS + i];
1291 if (mod == 0) break;
1292
1293 // Envelope
1294 if (mod <= MODULATOR_ENV4)
1295 {
1296 if (voiceptr)
1297 {
1298 const int nr = mod - MODULATOR_ENV1;
1299 if (frame < voiceptr->startFrame) factor = 0.0f;
1300 else factor *= voiceptr->envelope[nr].getValue (framesToSeconds (frame - voiceptr->startFrame, rate));
1301 }
1302 }
1303
1304 // LFO
1305 else if (mod <= MODULATOR_LFO4)
1306 {
1307 const int nr = mod - MODULATOR_LFO1;
1308 factor *= controllers[LFOS + nr * LFO_SIZE + LFO_AMP] * lfo[nr].getValue (framesToSeconds (frame, rate));
1309 }
1310
1311 // Sequencer
1312 else if (mod <= MODULATOR_SEQ4)
1313 {
1314 const int nr = mod - MODULATOR_SEQ1;
1315 factor *= seq[nr].getValue (framesToSeconds (frame, rate));
1316 }
1317
1318 // Random
1319 else
1320 {
1321 const int nr = mod - MODULATOR_RANDOM1;
1322 const double rnd = double (lcg_rand()) / double (LCG_RAND_MAX);
1323 factor *= controllers[RNDS + nr * RND_SIZE + RND_MIN] + rnd * (controllers[RNDS + nr * RND_SIZE + RND_MAX] - controllers[RNDS + nr * RND_SIZE + RND_MIN]);
1324 }
1325 }
1326
1327 return modulatef (start, end, factor);
1328 }
1329
notifyStatusToGui()1330 void BHarvestr::notifyStatusToGui ()
1331 {
1332 LV2_Atom_Forge_Frame forgeframe;
1333 lv2_atom_forge_frame_time(¬ifyForge, 0);
1334 lv2_atom_forge_object(¬ifyForge, &forgeframe, 0, uris.bharvestr_statusEvent);
1335
1336 // Time
1337 lv2_atom_forge_key(¬ifyForge, uris.bharvestr_statusTime);
1338 lv2_atom_forge_double(¬ifyForge, double (frame) / rate);
1339
1340 // LFO positions
1341 float lfoPositions[NR_LFOS];
1342 for (int i = 0; i < NR_LFOS; ++i) lfoPositions[i] = fracf (lfo[i].getPosition(double (frame) / rate) + lfo[i].getPhase());
1343 lv2_atom_forge_key(¬ifyForge, uris.bharvestr_statusLfoPositions);
1344 lv2_atom_forge_vector(¬ifyForge, sizeof(float), uris.atom_Float, NR_LFOS, (void*) lfoPositions);
1345
1346 // Seq positions
1347 float seqPositions[NR_SEQS];
1348 for (int i = 0; i < NR_SEQS; ++i) seqPositions[i] = fracf (seq[i].getPosition(double (frame) / rate) + seq[i].getPhase());
1349 lv2_atom_forge_key(¬ifyForge, uris.bharvestr_statusSeqPositions);
1350 lv2_atom_forge_vector(¬ifyForge, sizeof(float), uris.atom_Float, NR_LFOS, (void*) seqPositions);
1351
1352 // Env positions
1353 float envPositions[2 * MAXVOICES];
1354 int count = 0;
1355 for (unsigned int v = 0; v < voices.size; ++v)
1356 {
1357 if (frame >= voices[v].startFrame)
1358 {
1359 if (frame < voices[v].endFrame)
1360 {
1361 envPositions[count] = 0.0f;
1362 envPositions[count + 1] = framesToSeconds (frame - voices[v].startFrame, rate);
1363 }
1364 else
1365 {
1366 envPositions[count] = 1.0f;
1367 envPositions[count + 1] = framesToSeconds (frame - voices[v].endFrame, rate);
1368 }
1369
1370 count += 2;
1371 }
1372 }
1373 lv2_atom_forge_key(¬ifyForge, uris.bharvestr_statusEnvPositions);
1374 lv2_atom_forge_vector(¬ifyForge, sizeof(float), uris.atom_Float, count, (void*) envPositions);
1375
1376 // Grain properties
1377 float grainProperties[NR_GRAIN_PROPERTIES];
1378 for (int i = 0; i < NR_GRAIN_PROPERTIES; ++i)
1379 {
1380 grainProperties[i] = getModulation (nullptr, PROPERTIES + i * PROPERTIES_SIZE, frame);
1381 }
1382
1383 lv2_atom_forge_key(¬ifyForge, uris.bharvestr_statusGrainProperties);
1384 lv2_atom_forge_vector(¬ifyForge, sizeof(float), uris.atom_Float, NR_GRAIN_PROPERTIES, (void*) grainProperties);
1385
1386 // Pattern positions
1387 int patternPos[MAXVOICES] = {0};
1388 double grainMs = controllers[PROPERTIES + GRAIN_SIZE * PROPERTIES_SIZE + PROPERTY_VALUE_START];
1389 int64_t grainFrames = millisecondsToFrames (grainMs, rate);
1390 for (unsigned int v = 0; v < voices.size; ++v)
1391 {
1392 Voice& voice = voices[v];
1393 int patternStep = double (frame - voice.patternStartFrame) / double (grainFrames);
1394 patternPos[v] = LIMIT (patternStep, 0, MAXPATTERNSTEPS - 1);
1395 }
1396
1397 lv2_atom_forge_key(¬ifyForge, uris.bharvestr_statusPatternPositions);
1398 lv2_atom_forge_vector(¬ifyForge, sizeof(int), uris.atom_Int, voices.size, (void*) patternPos);
1399
1400 lv2_atom_forge_pop(¬ifyForge, &forgeframe);
1401 }
1402
forgeSamplePath(LV2_Atom_Forge * forge,LV2_Atom_Forge_Frame * frame,const char * path)1403 LV2_Atom_Forge_Ref BHarvestr::forgeSamplePath (LV2_Atom_Forge* forge, LV2_Atom_Forge_Frame* frame, const char* path)
1404 {
1405 const LV2_Atom_Forge_Ref msg = lv2_atom_forge_object (forge, frame, 0, uris.bharvestr_sampleEvent);
1406 if (msg)
1407 {
1408 lv2_atom_forge_key (forge, uris.bharvestr_samplePath);
1409 lv2_atom_forge_path (forge, path, strlen (path) + 1);
1410 }
1411 return msg;
1412 }
1413
notifySampleStopToGui()1414 void BHarvestr::notifySampleStopToGui ()
1415 {
1416 LV2_Atom_Forge_Frame forgeframe;
1417 lv2_atom_forge_frame_time(¬ifyForge, 0);
1418 lv2_atom_forge_object(¬ifyForge, &forgeframe, 0, uris.bharvestr_sampleStop);
1419 lv2_atom_forge_pop(¬ifyForge, &forgeframe);
1420
1421 notify.sampleStop = false;
1422 }
1423
notifySelectionStopToGui()1424 void BHarvestr::notifySelectionStopToGui ()
1425 {
1426 LV2_Atom_Forge_Frame forgeframe;
1427 lv2_atom_forge_frame_time(¬ifyForge, 0);
1428 lv2_atom_forge_object(¬ifyForge, &forgeframe, 0, uris.bharvestr_selectionStop);
1429 lv2_atom_forge_pop(¬ifyForge, &forgeframe);
1430
1431 notify.selectionStop = false;
1432 }
1433
notifyPatternToGui()1434 void BHarvestr::notifyPatternToGui ()
1435 {
1436 if (pattern.getPattern() == USER_PATTERN)
1437 {
1438 LV2_Atom_Forge_Frame frame;
1439 lv2_atom_forge_frame_time(¬ifyForge, 0);
1440 lv2_atom_forge_object(¬ifyForge, &frame, 0, uris.bharvestr_patternEvent);
1441 lv2_atom_forge_key(¬ifyForge, uris.bharvestr_patternRows);
1442 lv2_atom_forge_int(¬ifyForge, pattern.getRows());
1443 lv2_atom_forge_key(¬ifyForge, uris.bharvestr_patternSteps);
1444 lv2_atom_forge_int(¬ifyForge, pattern.getSteps());
1445 lv2_atom_forge_key(¬ifyForge, uris.bharvestr_pattern);
1446 lv2_atom_forge_vector(¬ifyForge, sizeof(int), uris.atom_Int, MAXPATTERNSTEPS, (void*) pattern.getValues());
1447 lv2_atom_forge_pop(¬ifyForge, &frame);
1448 }
1449 notify.pattern = false;
1450 }
1451
notifySamplePathToGui()1452 void BHarvestr::notifySamplePathToGui ()
1453 {
1454 if (sample && sample->path)
1455 {
1456 LV2_Atom_Forge_Frame frame;
1457 lv2_atom_forge_frame_time(¬ifyForge, 0);
1458 forgeSamplePath(¬ifyForge, &frame, sample->path);
1459 lv2_atom_forge_pop(¬ifyForge, &frame);
1460 }
1461
1462 notify.samplePath = false;
1463 }
1464
notifyDisplayToGui()1465 void BHarvestr::notifyDisplayToGui ()
1466 {
1467 LV2_Atom_Forge_Frame frame;
1468 lv2_atom_forge_frame_time(¬ifyForge, 0);
1469 lv2_atom_forge_object(¬ifyForge, &frame, 0, uris.bharvestr_displayEvent);
1470
1471 if (notify.sampleDisplay)
1472 {
1473 float sampleSize = 0.0f;
1474 float sampleDisplay[DISPLAYDATASIZE] {0.0f};
1475 if (sample && sample->info.frames)
1476 {
1477 sampleSize = double (sample->info.frames) / rate;
1478 for (int i = 0; i < DISPLAYDATASIZE; ++i)
1479 {
1480 sampleDisplay[i] = sample->data[size_t (i * sample->info.frames / DISPLAYDATASIZE) * sample->info.channels];
1481 }
1482 }
1483
1484 else memset (sampleDisplay, 0, DISPLAYDATASIZE * sizeof (float));
1485
1486 lv2_atom_forge_key(¬ifyForge, uris.bharvestr_sampleSize);
1487 lv2_atom_forge_float(¬ifyForge, sampleSize);
1488 lv2_atom_forge_key(¬ifyForge, uris.bharvestr_sampleDisplayData);
1489 lv2_atom_forge_vector(¬ifyForge, sizeof(float), uris.atom_Float, DISPLAYDATASIZE, (void*) sampleDisplay);
1490 notify.sampleDisplay = false;
1491 }
1492
1493 if (notify.selectionDisplay)
1494 {
1495 float selectionDisplay[DISPLAYDATASIZE] {0.0f};
1496 if (sample && sample->info.frames)
1497 {
1498 size_t s = controllers[SAMPLE_START] * sample->info.frames;
1499 size_t e = controllers[SAMPLE_END] * sample->info.frames;
1500
1501 for (int i = 0; i < DISPLAYDATASIZE; ++i)
1502 {
1503 selectionDisplay[i] = sample->data[(s + size_t (i * (e - s) / DISPLAYDATASIZE)) * sample->info.channels];
1504 }
1505 }
1506
1507 else memset (selectionDisplay, 0, DISPLAYDATASIZE * sizeof (float));
1508
1509 lv2_atom_forge_key(¬ifyForge, uris.bharvestr_selectionDisplayData);
1510 lv2_atom_forge_vector(¬ifyForge, sizeof(float), uris.atom_Float, DISPLAYDATASIZE, (void*) selectionDisplay);
1511 notify.selectionDisplay = false;
1512 }
1513
1514 lv2_atom_forge_pop(¬ifyForge, &frame);
1515 }
1516
notifyShapeToGui(ShapeIndex index)1517 void BHarvestr::notifyShapeToGui (ShapeIndex index)
1518 {
1519 unsigned int shapeNr = index;
1520 size_t size = shape[shapeNr].size ();
1521
1522 // Load shapeBuffer
1523 float shapeBuffer[MAXNODES * 7];
1524 for (unsigned int i = 0; i < size; ++i)
1525 {
1526 Node node = shape[shapeNr].getRawNode (i);
1527 shapeBuffer[i * 7] = (float)node.nodeType;
1528 shapeBuffer[i * 7 + 1] = (float)node.point.x;
1529 shapeBuffer[i * 7 + 2] = (float)node.point.y;
1530 shapeBuffer[i * 7 + 3] = (float)node.handle1.x;
1531 shapeBuffer[i * 7 + 4] = (float)node.handle1.y;
1532 shapeBuffer[i * 7 + 5] = (float)node.handle2.x;
1533 shapeBuffer[i * 7 + 6] = (float)node.handle2.y;
1534 }
1535
1536 // Notify shapeBuffer
1537 LV2_Atom_Forge_Frame frame;
1538 lv2_atom_forge_frame_time(¬ifyForge, 0);
1539 lv2_atom_forge_object(¬ifyForge, &frame, 0, uris.bharvestr_shapeEvent);
1540 lv2_atom_forge_key(¬ifyForge, uris.bharvestr_shapeIndex);
1541 lv2_atom_forge_int(¬ifyForge, shapeNr);
1542 lv2_atom_forge_key(¬ifyForge, uris.bharvestr_shapeData);
1543 lv2_atom_forge_vector(¬ifyForge, sizeof(float), uris.atom_Float, (uint32_t) (7 * size), &shapeBuffer);
1544 lv2_atom_forge_pop(¬ifyForge, &frame);
1545
1546 notify.shape[shapeNr] = false;
1547 }
1548
notifyPresetInfoToGui()1549 void BHarvestr::notifyPresetInfoToGui()
1550 {
1551 LV2_Atom_Forge_Frame frame;
1552 lv2_atom_forge_frame_time(¬ifyForge, 0);
1553 lv2_atom_forge_object(¬ifyForge, &frame, 0, uris.bharvestr_presetInfoEvent);
1554 lv2_atom_forge_key(¬ifyForge, uris.bharvestr_presetInfoName);
1555 lv2_atom_forge_string(¬ifyForge, presetInfo.name, strlen (presetInfo.name) + 1);
1556 lv2_atom_forge_key(¬ifyForge, uris.bharvestr_presetInfoType);
1557 lv2_atom_forge_string(¬ifyForge, presetInfo.type, strlen (presetInfo.type) + 1);
1558 lv2_atom_forge_key(¬ifyForge, uris.bharvestr_presetInfoDate);
1559 lv2_atom_forge_int(¬ifyForge, presetInfo.date);
1560 lv2_atom_forge_key(¬ifyForge, uris.bharvestr_presetInfoCreator);
1561 lv2_atom_forge_string(¬ifyForge, presetInfo.creator, strlen (presetInfo.creator) + 1);
1562 lv2_atom_forge_key(¬ifyForge, uris.bharvestr_presetInfoURI);
1563 lv2_atom_forge_string(¬ifyForge, presetInfo.uri, strlen (presetInfo.uri) + 1);
1564 lv2_atom_forge_key(¬ifyForge, uris.bharvestr_presetInfoLicense);
1565 lv2_atom_forge_string(¬ifyForge, presetInfo.license, strlen (presetInfo.license) + 1);
1566 lv2_atom_forge_key(¬ifyForge, uris.bharvestr_presetInfoDescription);
1567 lv2_atom_forge_string(¬ifyForge, presetInfo.description, strlen (presetInfo.description) + 1);
1568 lv2_atom_forge_pop(¬ifyForge, &frame);
1569
1570 notify.presetInfo = false;
1571 }
1572
notifyMessageToGui()1573 void BHarvestr::notifyMessageToGui()
1574 {
1575 LV2_Atom_Forge_Frame frame;
1576 lv2_atom_forge_frame_time(¬ifyForge, 0);
1577 lv2_atom_forge_object(¬ifyForge, &frame, 0, uris.bharvestr_messageEvent);
1578 lv2_atom_forge_key(¬ifyForge, uris.bharvestr_message);
1579 lv2_atom_forge_string(¬ifyForge, message, strlen (message) + 1);
1580 lv2_atom_forge_pop(¬ifyForge, &frame);
1581
1582 notify.message = false;
1583 }
1584
1585 /*
1586 *
1587 *
1588 ******************************************************************************
1589 * LV2 specific declarations
1590 */
1591
instantiate(const LV2_Descriptor * descriptor,double samplerate,const char * bundle_path,const LV2_Feature * const * features)1592 static LV2_Handle instantiate (const LV2_Descriptor* descriptor, double samplerate, const char* bundle_path, const LV2_Feature* const* features)
1593 {
1594 // New instance
1595 BHarvestr* instance;
1596 try {instance = new BHarvestr(samplerate, features);}
1597 catch (std::exception& exc)
1598 {
1599 fprintf (stderr, "BHarvestr.lv2: Plugin instantiation failed. %s\n", exc.what ());
1600 return NULL;
1601 }
1602
1603 return (LV2_Handle)instance;
1604 }
1605
connect_port(LV2_Handle instance,uint32_t port,void * data)1606 static void connect_port (LV2_Handle instance, uint32_t port, void *data)
1607 {
1608 BHarvestr* inst = (BHarvestr*) instance;
1609 inst->connect_port (port, data);
1610 }
1611
activate(LV2_Handle instance)1612 void activate (LV2_Handle instance)
1613 {
1614 BHarvestr* inst = (BHarvestr*) instance;
1615 if (inst) inst->activate();
1616 }
1617
run(LV2_Handle instance,uint32_t n_samples)1618 static void run (LV2_Handle instance, uint32_t n_samples)
1619 {
1620 BHarvestr* inst = (BHarvestr*) instance;
1621 if (inst) inst->run (n_samples);
1622 }
1623
deactivate(LV2_Handle instance)1624 void deactivate (LV2_Handle instance)
1625 {
1626 BHarvestr* inst = (BHarvestr*) instance;
1627 if (inst) inst->deactivate();
1628 }
1629
state_save(LV2_Handle instance,LV2_State_Store_Function store,LV2_State_Handle handle,uint32_t flags,const LV2_Feature * const * features)1630 static LV2_State_Status state_save(LV2_Handle instance, LV2_State_Store_Function store, LV2_State_Handle handle, uint32_t flags,
1631 const LV2_Feature* const* features)
1632 {
1633 BHarvestr* inst = (BHarvestr*)instance;
1634 if (!inst) return LV2_STATE_SUCCESS;
1635
1636 return inst->state_save (store, handle, flags, features);
1637 }
1638
state_restore(LV2_Handle instance,LV2_State_Retrieve_Function retrieve,LV2_State_Handle handle,uint32_t flags,const LV2_Feature * const * features)1639 static LV2_State_Status state_restore(LV2_Handle instance, LV2_State_Retrieve_Function retrieve, LV2_State_Handle handle, uint32_t flags,
1640 const LV2_Feature* const* features)
1641 {
1642 BHarvestr* inst = (BHarvestr*)instance;
1643 if (!inst) return LV2_STATE_SUCCESS;
1644
1645 return inst->state_restore (retrieve, handle, flags, features);
1646 }
1647
work(LV2_Handle instance,LV2_Worker_Respond_Function respond,LV2_Worker_Respond_Handle handle,uint32_t size,const void * data)1648 static LV2_Worker_Status work (LV2_Handle instance, LV2_Worker_Respond_Function respond, LV2_Worker_Respond_Handle handle,
1649 uint32_t size, const void* data)
1650 {
1651 BHarvestr* inst = (BHarvestr*)instance;
1652 if (!inst) return LV2_WORKER_SUCCESS;
1653
1654 return inst->work (respond, handle, size, data);
1655 }
1656
work_response(LV2_Handle instance,uint32_t size,const void * data)1657 static LV2_Worker_Status work_response (LV2_Handle instance, uint32_t size, const void* data)
1658 {
1659 BHarvestr* inst = (BHarvestr*)instance;
1660 if (!inst) return LV2_WORKER_SUCCESS;
1661
1662 return inst->work_response (size, data);
1663 }
1664
cleanup(LV2_Handle instance)1665 static void cleanup (LV2_Handle instance)
1666 {
1667 BHarvestr* inst = (BHarvestr*) instance;
1668 if (inst) delete inst;
1669 }
1670
1671
extension_data(const char * uri)1672 static const void* extension_data(const char* uri)
1673 {
1674 static const LV2_State_Interface state = {state_save, state_restore};
1675 static const LV2_Worker_Interface worker = {work, work_response, NULL};
1676 if (!strcmp(uri, LV2_STATE__interface)) return &state;
1677 if (!strcmp(uri, LV2_WORKER__interface)) return &worker;
1678 return NULL;
1679 }
1680
1681
1682 static const LV2_Descriptor descriptor =
1683 {
1684 BHARVESTR_URI,
1685 instantiate,
1686 connect_port,
1687 activate,
1688 run,
1689 deactivate,
1690 cleanup,
1691 extension_data
1692 };
1693
1694 // LV2 Symbol Export
lv2_descriptor(uint32_t index)1695 LV2_SYMBOL_EXPORT const LV2_Descriptor* lv2_descriptor (uint32_t index)
1696 {
1697 switch (index)
1698 {
1699 case 0: return &descriptor;
1700 default: return NULL;
1701 }
1702 }
1703
1704 /* End of LV2 specific declarations
1705 *
1706 * *****************************************************************************
1707 *
1708 *
1709 */
1710