1 /* ------------------------------------------------------------
2 name: "harm_trem"
3 Code generated with Faust 2.20.2 (https://faust.grame.fr)
4 Compilation options: -lang cpp -scal -ftz 0
5 ------------------------------------------------------------ */
6 
7 #ifndef  __harm_trem_H__
8 #define  __harm_trem_H__
9 
10 /************************************************************************
11  ************************************************************************
12     FAUST Architecture File
13     Copyright (C) 2009-2016 Albert Graef <aggraef@gmail.com>
14     ---------------------------------------------------------------------
15     This program is free software; you can redistribute it and/or modify
16     it under the terms of the GNU Lesser General Public License as
17     published by the Free Software Foundation; either version 3 of the
18     License, or (at your option) any later version.
19 
20     This program is distributed in the hope that it will be useful,
21     but WITHOUT ANY WARRANTY; without even the implied warranty of
22     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23     GNU Lesser General Public License for more details.
24 
25     You should have received a copy of the GNU Lesser General Public
26     License along with the GNU C Library; if not, write to the Free
27     Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28     02111-1307 USA.
29  ************************************************************************
30  ************************************************************************/
31 
32 /* LV2 architecture for Faust synths. */
33 
34 /* NOTE: This requires one of the Boost headers (boost/circular_buffer.hpp),
35    so to compile Faust programs created with this architecture you need to
36    have at least the Boost headers installed somewhere on your include path
37    (the Boost libraries aren't needed). */
38 
39 #include <stdlib.h>
40 #include <string.h>
41 #include <math.h>
42 #include <list>
43 #include <map>
44 #include <set>
45 
46 // generic Faust dsp and UI classes
47 /************************** BEGIN dsp.h **************************/
48 /************************************************************************
49  FAUST Architecture File
50  Copyright (C) 2003-2017 GRAME, Centre National de Creation Musicale
51  ---------------------------------------------------------------------
52  This Architecture section is free software; you can redistribute it
53  and/or modify it under the terms of the GNU General Public License
54  as published by the Free Software Foundation; either version 3 of
55  the License, or (at your option) any later version.
56 
57  This program is distributed in the hope that it will be useful,
58  but WITHOUT ANY WARRANTY; without even the implied warranty of
59  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
60  GNU General Public License for more details.
61 
62  You should have received a copy of the GNU General Public License
63  along with this program; If not, see <http://www.gnu.org/licenses/>.
64 
65  EXCEPTION : As a special exception, you may create a larger work
66  that contains this FAUST architecture section and distribute
67  that work under terms of your choice, so long as this FAUST
68  architecture section is not modified.
69  ************************************************************************/
70 
71 #ifndef __dsp__
72 #define __dsp__
73 
74 #include <string>
75 #include <vector>
76 
77 #ifndef FAUSTFLOAT
78 #define FAUSTFLOAT float
79 #endif
80 
81 class UI;
82 struct Meta;
83 
84 /**
85  * DSP memory manager.
86  */
87 
88 struct dsp_memory_manager {
89 
~dsp_memory_managerdsp_memory_manager90     virtual ~dsp_memory_manager() {}
91 
92     virtual void* allocate(size_t size) = 0;
93     virtual void destroy(void* ptr) = 0;
94 
95 };
96 
97 /**
98 * Signal processor definition.
99 */
100 
101 class dsp {
102 
103     public:
104 
dsp()105         dsp() {}
~dsp()106         virtual ~dsp() {}
107 
108         /* Return instance number of audio inputs */
109         virtual int getNumInputs() = 0;
110 
111         /* Return instance number of audio outputs */
112         virtual int getNumOutputs() = 0;
113 
114         /**
115          * Trigger the ui_interface parameter with instance specific calls
116          * to 'addBtton', 'addVerticalSlider'... in order to build the UI.
117          *
118          * @param ui_interface - the user interface builder
119          */
120         virtual void buildUserInterface(UI* ui_interface) = 0;
121 
122         /* Returns the sample rate currently used by the instance */
123         virtual int getSampleRate() = 0;
124 
125         /**
126          * Global init, calls the following methods:
127          * - static class 'classInit': static tables initialization
128          * - 'instanceInit': constants and instance state initialization
129          *
130          * @param sample_rate - the sampling rate in Hertz
131          */
132         virtual void init(int sample_rate) = 0;
133 
134         /**
135          * Init instance state
136          *
137          * @param sample_rate - the sampling rate in Hertz
138          */
139         virtual void instanceInit(int sample_rate) = 0;
140 
141         /**
142          * Init instance constant state
143          *
144          * @param sample_rate - the sampling rate in Hertz
145          */
146         virtual void instanceConstants(int sample_rate) = 0;
147 
148         /* Init default control parameters values */
149         virtual void instanceResetUserInterface() = 0;
150 
151         /* Init instance state (delay lines...) */
152         virtual void instanceClear() = 0;
153 
154         /**
155          * Return a clone of the instance.
156          *
157          * @return a copy of the instance on success, otherwise a null pointer.
158          */
159         virtual dsp* clone() = 0;
160 
161         /**
162          * Trigger the Meta* parameter with instance specific calls to 'declare' (key, value) metadata.
163          *
164          * @param m - the Meta* meta user
165          */
166         virtual void metadata(Meta* m) = 0;
167 
168         /**
169          * DSP instance computation, to be called with successive in/out audio buffers.
170          *
171          * @param count - the number of frames to compute
172          * @param inputs - the input audio buffers as an array of non-interleaved FAUSTFLOAT samples (eiher float, double or quad)
173          * @param outputs - the output audio buffers as an array of non-interleaved FAUSTFLOAT samples (eiher float, double or quad)
174          *
175          */
176         virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) = 0;
177 
178         /**
179          * DSP instance computation: alternative method to be used by subclasses.
180          *
181          * @param date_usec - the timestamp in microsec given by audio driver.
182          * @param count - the number of frames to compute
183          * @param inputs - the input audio buffers as an array of non-interleaved FAUSTFLOAT samples (either float, double or quad)
184          * @param outputs - the output audio buffers as an array of non-interleaved FAUSTFLOAT samples (either float, double or quad)
185          *
186          */
compute(double,int count,FAUSTFLOAT ** inputs,FAUSTFLOAT ** outputs)187         virtual void compute(double /*date_usec*/, int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { compute(count, inputs, outputs); }
188 
189 };
190 
191 /**
192  * Generic DSP decorator.
193  */
194 
195 class decorator_dsp : public dsp {
196 
197     protected:
198 
199         dsp* fDSP;
200 
201     public:
202 
decorator_dsp(dsp * dsp=nullptr)203         decorator_dsp(dsp* dsp = nullptr):fDSP(dsp) {}
~decorator_dsp()204         virtual ~decorator_dsp() { delete fDSP; }
205 
getNumInputs()206         virtual int getNumInputs() { return fDSP->getNumInputs(); }
getNumOutputs()207         virtual int getNumOutputs() { return fDSP->getNumOutputs(); }
buildUserInterface(UI * ui_interface)208         virtual void buildUserInterface(UI* ui_interface) { fDSP->buildUserInterface(ui_interface); }
getSampleRate()209         virtual int getSampleRate() { return fDSP->getSampleRate(); }
init(int sample_rate)210         virtual void init(int sample_rate) { fDSP->init(sample_rate); }
instanceInit(int sample_rate)211         virtual void instanceInit(int sample_rate) { fDSP->instanceInit(sample_rate); }
instanceConstants(int sample_rate)212         virtual void instanceConstants(int sample_rate) { fDSP->instanceConstants(sample_rate); }
instanceResetUserInterface()213         virtual void instanceResetUserInterface() { fDSP->instanceResetUserInterface(); }
instanceClear()214         virtual void instanceClear() { fDSP->instanceClear(); }
clone()215         virtual decorator_dsp* clone() { return new decorator_dsp(fDSP->clone()); }
metadata(Meta * m)216         virtual void metadata(Meta* m) { fDSP->metadata(m); }
217         // Beware: subclasses usually have to overload the two 'compute' methods
compute(int count,FAUSTFLOAT ** inputs,FAUSTFLOAT ** outputs)218         virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { fDSP->compute(count, inputs, outputs); }
compute(double date_usec,int count,FAUSTFLOAT ** inputs,FAUSTFLOAT ** outputs)219         virtual void compute(double date_usec, int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) { fDSP->compute(date_usec, count, inputs, outputs); }
220 
221 };
222 
223 /**
224  * DSP factory class.
225  */
226 
227 class dsp_factory {
228 
229     protected:
230 
231         // So that to force sub-classes to use deleteDSPFactory(dsp_factory* factory);
~dsp_factory()232         virtual ~dsp_factory() {}
233 
234     public:
235 
236         virtual std::string getName() = 0;
237         virtual std::string getSHAKey() = 0;
238         virtual std::string getDSPCode() = 0;
239         virtual std::string getCompileOptions() = 0;
240         virtual std::vector<std::string> getLibraryList() = 0;
241         virtual std::vector<std::string> getIncludePathnames() = 0;
242 
243         virtual dsp* createDSPInstance() = 0;
244 
245         virtual void setMemoryManager(dsp_memory_manager* manager) = 0;
246         virtual dsp_memory_manager* getMemoryManager() = 0;
247 
248 };
249 
250 /**
251  * On Intel set FZ (Flush to Zero) and DAZ (Denormals Are Zero)
252  * flags to avoid costly denormals.
253  */
254 
255 #ifdef __SSE__
256     #include <xmmintrin.h>
257     #ifdef __SSE2__
258         #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8040)
259     #else
260         #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8000)
261     #endif
262 #else
263     #define AVOIDDENORMALS
264 #endif
265 
266 #endif
267 /**************************  END  dsp.h **************************/
268 /************************** BEGIN UI.h **************************/
269 /************************************************************************
270  FAUST Architecture File
271  Copyright (C) 2003-2017 GRAME, Centre National de Creation Musicale
272  ---------------------------------------------------------------------
273  This Architecture section is free software; you can redistribute it
274  and/or modify it under the terms of the GNU General Public License
275  as published by the Free Software Foundation; either version 3 of
276  the License, or (at your option) any later version.
277 
278  This program is distributed in the hope that it will be useful,
279  but WITHOUT ANY WARRANTY; without even the implied warranty of
280  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
281  GNU General Public License for more details.
282 
283  You should have received a copy of the GNU General Public License
284  along with this program; If not, see <http://www.gnu.org/licenses/>.
285 
286  EXCEPTION : As a special exception, you may create a larger work
287  that contains this FAUST architecture section and distribute
288  that work under terms of your choice, so long as this FAUST
289  architecture section is not modified.
290  ************************************************************************/
291 
292 #ifndef __UI_H__
293 #define __UI_H__
294 
295 #ifndef FAUSTFLOAT
296 #define FAUSTFLOAT float
297 #endif
298 
299 /*******************************************************************************
300  * UI : Faust DSP User Interface
301  * User Interface as expected by the buildUserInterface() method of a DSP.
302  * This abstract class contains only the method that the Faust compiler can
303  * generate to describe a DSP user interface.
304  ******************************************************************************/
305 
306 struct Soundfile;
307 
308 template <typename REAL>
309 class UIReal
310 {
311 
312     public:
313 
UIReal()314         UIReal() {}
~UIReal()315         virtual ~UIReal() {}
316 
317         // -- widget's layouts
318 
319         virtual void openTabBox(const char* label) = 0;
320         virtual void openHorizontalBox(const char* label) = 0;
321         virtual void openVerticalBox(const char* label) = 0;
322         virtual void closeBox() = 0;
323 
324         // -- active widgets
325 
326         virtual void addButton(const char* label, REAL* zone) = 0;
327         virtual void addCheckButton(const char* label, REAL* zone) = 0;
328         virtual void addVerticalSlider(const char* label, REAL* zone, REAL init, REAL min, REAL max, REAL step) = 0;
329         virtual void addHorizontalSlider(const char* label, REAL* zone, REAL init, REAL min, REAL max, REAL step) = 0;
330         virtual void addNumEntry(const char* label, REAL* zone, REAL init, REAL min, REAL max, REAL step) = 0;
331 
332         // -- passive widgets
333 
334         virtual void addHorizontalBargraph(const char* label, REAL* zone, REAL min, REAL max) = 0;
335         virtual void addVerticalBargraph(const char* label, REAL* zone, REAL min, REAL max) = 0;
336 
337         // -- soundfiles
338 
339         virtual void addSoundfile(const char* label, const char* filename, Soundfile** sf_zone) = 0;
340 
341         // -- metadata declarations
342 
declare(REAL * zone,const char * key,const char * val)343         virtual void declare(REAL* zone, const char* key, const char* val) {}
344 };
345 
346 class UI : public UIReal<FAUSTFLOAT>
347 {
348 
349     public:
350 
UI()351         UI() {}
~UI()352         virtual ~UI() {}
353 };
354 
355 #endif
356 /**************************  END  UI.h **************************/
357 
358 using namespace std;
359 
360 typedef pair<const char*,const char*> strpair;
361 
362 struct Meta : std::map<const char*, const char*>
363 {
declareMeta364   void declare(const char *key, const char *value)
365   {
366     (*this)[key] = value;
367   }
getMeta368   const char* get(const char *key, const char *def)
369   {
370     if (this->find(key) != this->end())
371       return (*this)[key];
372     else
373       return def;
374   }
375 };
376 
377 /******************************************************************************
378 *******************************************************************************
379 
380 		       VECTOR INTRINSICS
381 
382 *******************************************************************************
383 *******************************************************************************/
384 
385 
386 /***************************************************************************
387    LV2 UI interface
388  ***************************************************************************/
389 
390 enum ui_elem_type_t {
391   UI_BUTTON, UI_CHECK_BUTTON,
392   UI_V_SLIDER, UI_H_SLIDER, UI_NUM_ENTRY,
393   UI_V_BARGRAPH, UI_H_BARGRAPH,
394   UI_END_GROUP, UI_V_GROUP, UI_H_GROUP, UI_T_GROUP
395 };
396 
397 struct ui_elem_t {
398   ui_elem_type_t type;
399   const char *label;
400   int port;
401   float *zone;
402   void *ref;
403   float init, min, max, step;
404 };
405 
406 class LV2UI : public UI
407 {
408 public:
409   bool is_instr;
410   int nelems, nports;
411   ui_elem_t *elems;
412   map< int, list<strpair> > metadata;
413 
414   LV2UI(int maxvoices = 0);
415   virtual ~LV2UI();
416 
417 protected:
418   void add_elem(ui_elem_type_t type, const char *label = NULL);
419   void add_elem(ui_elem_type_t type, const char *label, float *zone);
420   void add_elem(ui_elem_type_t type, const char *label, float *zone,
421 		float init, float min, float max, float step);
422   void add_elem(ui_elem_type_t type, const char *label, float *zone,
423 		float min, float max);
424 
425   bool have_freq, have_gain, have_gate;
426   bool is_voice_ctrl(const char *label);
427 
428 public:
429   virtual void addButton(const char* label, float* zone);
430   virtual void addCheckButton(const char* label, float* zone);
431   virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step);
432   virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step);
433   virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step);
434 
435   virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max);
436   virtual void addVerticalBargraph(const char* label, float* zone, float min, float max);
437 
addSoundfile(const char * label,const char * filename,Soundfile ** sf_zone)438   virtual void addSoundfile(const char* label, const char* filename, Soundfile** sf_zone) {}
439 
440   virtual void openTabBox(const char* label);
441   virtual void openHorizontalBox(const char* label);
442   virtual void openVerticalBox(const char* label);
443   virtual void closeBox();
444 
445   virtual void run();
446 
447   virtual void declare(float* zone, const char* key, const char* value);
448 };
449 
LV2UI(int maxvoices)450 LV2UI::LV2UI(int maxvoices)
451 {
452   is_instr = maxvoices>0;
453   have_freq = have_gain = have_gate = false;
454   nelems = nports = 0;
455   elems = NULL;
456 }
457 
~LV2UI()458 LV2UI::~LV2UI()
459 {
460   if (elems) free(elems);
461 }
462 
declare(float * zone,const char * key,const char * value)463 void LV2UI::declare(float* zone, const char* key, const char* value)
464 {
465   map< int, list<strpair> >::iterator it = metadata.find(nelems);
466   if (it != metadata.end())
467     it->second.push_back(strpair(key, value));
468   else
469     metadata[nelems] = list<strpair>(1, strpair(key, value));
470 }
471 
add_elem(ui_elem_type_t type,const char * label)472 inline void LV2UI::add_elem(ui_elem_type_t type, const char *label)
473 {
474   ui_elem_t *elems1 = (ui_elem_t*)realloc(elems, (nelems+1)*sizeof(ui_elem_t));
475   if (elems1)
476     elems = elems1;
477   else
478     return;
479   elems[nelems].type = type;
480   elems[nelems].label = label;
481   elems[nelems].port = -1;
482   elems[nelems].zone = NULL;
483   elems[nelems].ref = NULL;
484   elems[nelems].init = 0.0;
485   elems[nelems].min = 0.0;
486   elems[nelems].max = 0.0;
487   elems[nelems].step = 0.0;
488   nelems++;
489 }
490 
491 #define portno(label) (is_voice_ctrl(label)?-1:nports++)
492 
add_elem(ui_elem_type_t type,const char * label,float * zone)493 inline void LV2UI::add_elem(ui_elem_type_t type, const char *label, float *zone)
494 {
495   ui_elem_t *elems1 = (ui_elem_t*)realloc(elems, (nelems+1)*sizeof(ui_elem_t));
496   if (elems1)
497     elems = elems1;
498   else
499     return;
500   elems[nelems].type = type;
501   elems[nelems].label = label;
502   elems[nelems].port = portno(label);
503   elems[nelems].zone = zone;
504   elems[nelems].ref = NULL;
505   elems[nelems].init = 0.0;
506   elems[nelems].min = 0.0;
507   elems[nelems].max = 0.0;
508   elems[nelems].step = 0.0;
509   nelems++;
510 }
511 
add_elem(ui_elem_type_t type,const char * label,float * zone,float init,float min,float max,float step)512 inline void LV2UI::add_elem(ui_elem_type_t type, const char *label, float *zone,
513 			     float init, float min, float max, float step)
514 {
515   ui_elem_t *elems1 = (ui_elem_t*)realloc(elems, (nelems+1)*sizeof(ui_elem_t));
516   if (elems1)
517     elems = elems1;
518   else
519     return;
520   elems[nelems].type = type;
521   elems[nelems].label = label;
522   elems[nelems].port = portno(label);
523   elems[nelems].zone = zone;
524   elems[nelems].ref = NULL;
525   elems[nelems].init = init;
526   elems[nelems].min = min;
527   elems[nelems].max = max;
528   elems[nelems].step = step;
529   nelems++;
530 }
531 
add_elem(ui_elem_type_t type,const char * label,float * zone,float min,float max)532 inline void LV2UI::add_elem(ui_elem_type_t type, const char *label, float *zone,
533 			     float min, float max)
534 {
535   ui_elem_t *elems1 = (ui_elem_t*)realloc(elems, (nelems+1)*sizeof(ui_elem_t));
536   if (elems1)
537     elems = elems1;
538   else
539     return;
540   elems[nelems].type = type;
541   elems[nelems].label = label;
542   elems[nelems].port = portno(label);
543   elems[nelems].zone = zone;
544   elems[nelems].ref = NULL;
545   elems[nelems].init = 0.0;
546   elems[nelems].min = min;
547   elems[nelems].max = max;
548   elems[nelems].step = 0.0;
549   nelems++;
550 }
551 
is_voice_ctrl(const char * label)552 inline bool LV2UI::is_voice_ctrl(const char *label)
553 {
554   if (!is_instr)
555     return false;
556   else if (!have_freq && !strcmp(label, "freq"))
557     return (have_freq = true);
558   else if (!have_gain && !strcmp(label, "gain"))
559     return (have_gain = true);
560   else if (!have_gate && !strcmp(label, "gate"))
561     return (have_gate = true);
562   else
563     return false;
564 }
565 
addButton(const char * label,float * zone)566 void LV2UI::addButton(const char* label, float* zone)
567 { add_elem(UI_BUTTON, label, zone); }
addCheckButton(const char * label,float * zone)568 void LV2UI::addCheckButton(const char* label, float* zone)
569 { add_elem(UI_CHECK_BUTTON, label, zone); }
addVerticalSlider(const char * label,float * zone,float init,float min,float max,float step)570 void LV2UI::addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step)
571 { add_elem(UI_V_SLIDER, label, zone, init, min, max, step); }
addHorizontalSlider(const char * label,float * zone,float init,float min,float max,float step)572 void LV2UI::addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step)
573 { add_elem(UI_H_SLIDER, label, zone, init, min, max, step); }
addNumEntry(const char * label,float * zone,float init,float min,float max,float step)574 void LV2UI::addNumEntry(const char* label, float* zone, float init, float min, float max, float step)
575 { add_elem(UI_NUM_ENTRY, label, zone, init, min, max, step); }
576 
addHorizontalBargraph(const char * label,float * zone,float min,float max)577 void LV2UI::addHorizontalBargraph(const char* label, float* zone, float min, float max)
578 { add_elem(UI_H_BARGRAPH, label, zone, min, max); }
addVerticalBargraph(const char * label,float * zone,float min,float max)579 void LV2UI::addVerticalBargraph(const char* label, float* zone, float min, float max)
580 { add_elem(UI_V_BARGRAPH, label, zone, min, max); }
581 
openTabBox(const char * label)582 void LV2UI::openTabBox(const char* label)
583 { add_elem(UI_T_GROUP, label); }
openHorizontalBox(const char * label)584 void LV2UI::openHorizontalBox(const char* label)
585 { add_elem(UI_H_GROUP, label); }
openVerticalBox(const char * label)586 void LV2UI::openVerticalBox(const char* label)
587 { add_elem(UI_V_GROUP, label); }
closeBox()588 void LV2UI::closeBox()
589 { add_elem(UI_END_GROUP); }
590 
run()591 void LV2UI::run() {}
592 
593 //----------------------------------------------------------------------------
594 //  FAUST generated signal processor
595 //----------------------------------------------------------------------------
596 
597 #ifndef FAUSTFLOAT
598 #define FAUSTFLOAT float
599 #endif
600 
601 #include <algorithm>
602 #include <cmath>
603 #include <math.h>
604 
605 class harm_tremSIG0 {
606 
607   private:
608 
609 	int iRec4[2];
610 
611   public:
612 
getNumInputsharm_tremSIG0()613 	int getNumInputsharm_tremSIG0() {
614 		return 0;
615 	}
getNumOutputsharm_tremSIG0()616 	int getNumOutputsharm_tremSIG0() {
617 		return 1;
618 	}
getInputRateharm_tremSIG0(int channel)619 	int getInputRateharm_tremSIG0(int channel) {
620 		int rate;
621 		switch ((channel)) {
622 			default: {
623 				rate = -1;
624 				break;
625 			}
626 		}
627 		return rate;
628 	}
getOutputRateharm_tremSIG0(int channel)629 	int getOutputRateharm_tremSIG0(int channel) {
630 		int rate;
631 		switch ((channel)) {
632 			case 0: {
633 				rate = 0;
634 				break;
635 			}
636 			default: {
637 				rate = -1;
638 				break;
639 			}
640 		}
641 		return rate;
642 	}
643 
instanceInitharm_tremSIG0(int sample_rate)644 	void instanceInitharm_tremSIG0(int sample_rate) {
645 		for (int l5 = 0; (l5 < 2); l5 = (l5 + 1)) {
646 			iRec4[l5] = 0;
647 		}
648 	}
649 
fillharm_tremSIG0(int count,float * table)650 	void fillharm_tremSIG0(int count, float* table) {
651 		for (int i = 0; (i < count); i = (i + 1)) {
652 			iRec4[0] = (iRec4[1] + 1);
653 			table[i] = std::sin((9.58738019e-05f * float((iRec4[0] + -1))));
654 			iRec4[1] = iRec4[0];
655 		}
656 	}
657 
658 };
659 
newharm_tremSIG0()660 static harm_tremSIG0* newharm_tremSIG0() { return (harm_tremSIG0*)new harm_tremSIG0(); }
deleteharm_tremSIG0(harm_tremSIG0 * dsp)661 static void deleteharm_tremSIG0(harm_tremSIG0* dsp) { delete dsp; }
662 
harm_trem_faustpower2_f(float value)663 static float harm_trem_faustpower2_f(float value) {
664 	return (value * value);
665 }
666 static float ftbl0harm_tremSIG0[65536];
667 
668 #ifndef FAUSTCLASS
669 #define FAUSTCLASS harm_trem
670 #endif
671 
672 #ifdef __APPLE__
673 #define exp10f __exp10f
674 #define exp10 __exp10
675 #endif
676 
677 class harm_trem : public dsp {
678 
679  private:
680 
681 	float fVec0[2];
682 	int fSampleRate;
683 	float fConst0;
684 	float fConst1;
685 	FAUSTFLOAT fVslider0;
686 	float fRec2[2];
687 	float fRec1[2];
688 	float fRec0[3];
689 	FAUSTFLOAT fHslider0;
690 	float fRec3[2];
691 	float fConst2;
692 	FAUSTFLOAT fVslider1;
693 	float fRec6[2];
694 	float fRec5[2];
695 	float fRec8[2];
696 	float fRec7[3];
697 
698  public:
699 
metadata(Meta * m)700 	void metadata(Meta* m) {
701 		m->declare("analyzers.lib/name", "Faust Analyzer Library");
702 		m->declare("analyzers.lib/version", "0.0");
703 		m->declare("basics.lib/name", "Faust Basic Element Library");
704 		m->declare("basics.lib/version", "0.1");
705 		m->declare("filename", "harm_trem.dsp");
706 		m->declare("filters.lib/filterbank:author", "Julius O. Smith III");
707 		m->declare("filters.lib/filterbank:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
708 		m->declare("filters.lib/filterbank:license", "MIT-style STK-4.3 license");
709 		m->declare("filters.lib/fir:author", "Julius O. Smith III");
710 		m->declare("filters.lib/fir:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
711 		m->declare("filters.lib/fir:license", "MIT-style STK-4.3 license");
712 		m->declare("filters.lib/highpass:author", "Julius O. Smith III");
713 		m->declare("filters.lib/highpass:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
714 		m->declare("filters.lib/iir:author", "Julius O. Smith III");
715 		m->declare("filters.lib/iir:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
716 		m->declare("filters.lib/iir:license", "MIT-style STK-4.3 license");
717 		m->declare("filters.lib/lowpass0_highpass1", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
718 		m->declare("filters.lib/lowpass0_highpass1:author", "Julius O. Smith III");
719 		m->declare("filters.lib/lowpass:author", "Julius O. Smith III");
720 		m->declare("filters.lib/lowpass:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
721 		m->declare("filters.lib/lowpass:license", "MIT-style STK-4.3 license");
722 		m->declare("filters.lib/name", "Faust Filters Library");
723 		m->declare("filters.lib/tf1:author", "Julius O. Smith III");
724 		m->declare("filters.lib/tf1:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
725 		m->declare("filters.lib/tf1:license", "MIT-style STK-4.3 license");
726 		m->declare("filters.lib/tf1s:author", "Julius O. Smith III");
727 		m->declare("filters.lib/tf1s:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
728 		m->declare("filters.lib/tf1s:license", "MIT-style STK-4.3 license");
729 		m->declare("filters.lib/tf2:author", "Julius O. Smith III");
730 		m->declare("filters.lib/tf2:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
731 		m->declare("filters.lib/tf2:license", "MIT-style STK-4.3 license");
732 		m->declare("filters.lib/tf2s:author", "Julius O. Smith III");
733 		m->declare("filters.lib/tf2s:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
734 		m->declare("filters.lib/tf2s:license", "MIT-style STK-4.3 license");
735 		m->declare("maths.lib/author", "GRAME");
736 		m->declare("maths.lib/copyright", "GRAME");
737 		m->declare("maths.lib/license", "LGPL with exception");
738 		m->declare("maths.lib/name", "Faust Math Library");
739 		m->declare("maths.lib/version", "2.1");
740 		m->declare("name", "harm_trem");
741 		m->declare("oscillators.lib/name", "Faust Oscillator Library");
742 		m->declare("oscillators.lib/version", "0.0");
743 		m->declare("signals.lib/name", "Faust Signal Routing Library");
744 		m->declare("signals.lib/version", "0.0");
745 	}
746 
getNumInputs()747 	virtual int getNumInputs() {
748 		return 1;
749 	}
getNumOutputs()750 	virtual int getNumOutputs() {
751 		return 1;
752 	}
getInputRate(int channel)753 	virtual int getInputRate(int channel) {
754 		int rate;
755 		switch ((channel)) {
756 			case 0: {
757 				rate = 1;
758 				break;
759 			}
760 			default: {
761 				rate = -1;
762 				break;
763 			}
764 		}
765 		return rate;
766 	}
getOutputRate(int channel)767 	virtual int getOutputRate(int channel) {
768 		int rate;
769 		switch ((channel)) {
770 			case 0: {
771 				rate = 1;
772 				break;
773 			}
774 			default: {
775 				rate = -1;
776 				break;
777 			}
778 		}
779 		return rate;
780 	}
781 
classInit(int sample_rate)782 	static void classInit(int sample_rate) {
783 		harm_tremSIG0* sig0 = newharm_tremSIG0();
784 		sig0->instanceInitharm_tremSIG0(sample_rate);
785 		sig0->fillharm_tremSIG0(65536, ftbl0harm_tremSIG0);
786 		deleteharm_tremSIG0(sig0);
787 	}
788 
instanceConstants(int sample_rate)789 	virtual void instanceConstants(int sample_rate) {
790 		fSampleRate = sample_rate;
791 		fConst0 = std::min<float>(192000.0f, std::max<float>(1.0f, float(fSampleRate)));
792 		fConst1 = (3.14159274f / fConst0);
793 		fConst2 = (0.0166666675f / fConst0);
794 	}
795 
instanceResetUserInterface()796 	virtual void instanceResetUserInterface() {
797 		fVslider0 = FAUSTFLOAT(800.0f);
798 		fHslider0 = FAUSTFLOAT(0.0f);
799 		fVslider1 = FAUSTFLOAT(120.0f);
800 	}
801 
instanceClear()802 	virtual void instanceClear() {
803 		for (int l0 = 0; (l0 < 2); l0 = (l0 + 1)) {
804 			fVec0[l0] = 0.0f;
805 		}
806 		for (int l1 = 0; (l1 < 2); l1 = (l1 + 1)) {
807 			fRec2[l1] = 0.0f;
808 		}
809 		for (int l2 = 0; (l2 < 2); l2 = (l2 + 1)) {
810 			fRec1[l2] = 0.0f;
811 		}
812 		for (int l3 = 0; (l3 < 3); l3 = (l3 + 1)) {
813 			fRec0[l3] = 0.0f;
814 		}
815 		for (int l4 = 0; (l4 < 2); l4 = (l4 + 1)) {
816 			fRec3[l4] = 0.0f;
817 		}
818 		for (int l6 = 0; (l6 < 2); l6 = (l6 + 1)) {
819 			fRec6[l6] = 0.0f;
820 		}
821 		for (int l7 = 0; (l7 < 2); l7 = (l7 + 1)) {
822 			fRec5[l7] = 0.0f;
823 		}
824 		for (int l8 = 0; (l8 < 2); l8 = (l8 + 1)) {
825 			fRec8[l8] = 0.0f;
826 		}
827 		for (int l9 = 0; (l9 < 3); l9 = (l9 + 1)) {
828 			fRec7[l9] = 0.0f;
829 		}
830 	}
831 
init(int sample_rate)832 	virtual void init(int sample_rate) {
833 		classInit(sample_rate);
834 		instanceInit(sample_rate);
835 	}
instanceInit(int sample_rate)836 	virtual void instanceInit(int sample_rate) {
837 		instanceConstants(sample_rate);
838 		instanceResetUserInterface();
839 		instanceClear();
840 	}
841 
clone()842 	virtual harm_trem* clone() {
843 		return new harm_trem();
844 	}
845 
getSampleRate()846 	virtual int getSampleRate() {
847 		return fSampleRate;
848 	}
849 
buildUserInterface(UI * ui_interface)850 	virtual void buildUserInterface(UI* ui_interface) {
851 		ui_interface->openVerticalBox("harm_trem");
852 		ui_interface->declare(&fVslider1, "0", "");
853 		ui_interface->declare(&fVslider1, "midi", "ctrl 63");
854 		ui_interface->declare(&fVslider1, "style", "knob");
855 		ui_interface->addVerticalSlider("BPM", &fVslider1, 120.0f, 15.0f, 300.0f, 0.100000001f);
856 		ui_interface->declare(&fVslider0, "1", "");
857 		ui_interface->declare(&fVslider0, "midi", "ctrl 64");
858 		ui_interface->declare(&fVslider0, "style", "knob");
859 		ui_interface->addVerticalSlider("CrossoverFreq", &fVslider0, 800.0f, 20.0f, 10000.0f, 1.0f);
860 		ui_interface->declare(&fHslider0, "2", "");
861 		ui_interface->addHorizontalSlider("depth", &fHslider0, 0.0f, 0.0f, 1.0f, 0.00999999978f);
862 		ui_interface->closeBox();
863 	}
864 
compute(int count,FAUSTFLOAT ** inputs,FAUSTFLOAT ** outputs)865 	virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) {
866 		FAUSTFLOAT* input0 = inputs[0];
867 		FAUSTFLOAT* output0 = outputs[0];
868 		float fSlow0 = (0.00100000005f * float(fVslider0));
869 		float fSlow1 = (0.00100000005f * float(fHslider0));
870 		float fSlow2 = (0.00100000005f * float(fVslider1));
871 		for (int i = 0; (i < count); i = (i + 1)) {
872 			float fTemp0 = float(input0[i]);
873 			fVec0[0] = fTemp0;
874 			fRec2[0] = (fSlow0 + (0.999000013f * fRec2[1]));
875 			float fTemp1 = std::tan((fConst1 * fRec2[0]));
876 			float fTemp2 = (1.0f / fTemp1);
877 			float fTemp3 = (fTemp2 + 1.0f);
878 			float fTemp4 = (1.0f - fTemp2);
879 			fRec1[0] = ((fVec0[1] * (0.0f - (1.0f / (fTemp1 * fTemp3)))) - (((fRec1[1] * fTemp4) - (fTemp0 / fTemp1)) / fTemp3));
880 			float fTemp5 = (((fTemp2 + -1.0f) / fTemp1) + 1.0f);
881 			float fTemp6 = harm_trem_faustpower2_f(fTemp1);
882 			float fTemp7 = (1.0f - (1.0f / fTemp6));
883 			float fTemp8 = (((fTemp2 + 1.0f) / fTemp1) + 1.0f);
884 			fRec0[0] = (fRec1[0] - (((fRec0[2] * fTemp5) + (2.0f * (fRec0[1] * fTemp7))) / fTemp8));
885 			fRec3[0] = (fSlow1 + (0.999000013f * fRec3[1]));
886 			fRec6[0] = (fSlow2 + (0.999000013f * fRec6[1]));
887 			float fTemp9 = (fRec5[1] + (fConst2 * fRec6[0]));
888 			fRec5[0] = (fTemp9 - std::floor(fTemp9));
889 			float fTemp10 = ftbl0harm_tremSIG0[int((65536.0f * fRec5[0]))];
890 			fRec8[0] = (0.0f - (((fTemp4 * fRec8[1]) - (fTemp0 + fVec0[1])) / fTemp3));
891 			fRec7[0] = (fRec8[0] - (((fTemp5 * fRec7[2]) + (2.0f * (fTemp7 * fRec7[1]))) / fTemp8));
892 			output0[i] = FAUSTFLOAT(((((((fRec0[1] * (0.0f - (2.0f / fTemp6))) + (fRec0[0] / fTemp6)) + (fRec0[2] / fTemp6)) * (1.0f - (0.5f * (fRec3[0] * (fTemp10 + 1.0f))))) + ((fRec7[2] + (fRec7[0] + (2.0f * fRec7[1]))) * (1.0f - (0.5f * (fRec3[0] * ((1.0f - fTemp10) + 1.0f)))))) / fTemp8));
893 			fVec0[1] = fVec0[0];
894 			fRec2[1] = fRec2[0];
895 			fRec1[1] = fRec1[0];
896 			fRec0[2] = fRec0[1];
897 			fRec0[1] = fRec0[0];
898 			fRec3[1] = fRec3[0];
899 			fRec6[1] = fRec6[0];
900 			fRec5[1] = fRec5[0];
901 			fRec8[1] = fRec8[0];
902 			fRec7[2] = fRec7[1];
903 			fRec7[1] = fRec7[0];
904 		}
905 	}
906 
907 };
908 
909 //----------------------------------------------------------------------------
910 //  LV2 interface
911 //----------------------------------------------------------------------------
912 
913 #line 286 "lv2.cpp"
914 
915 #include <assert.h>
916 #include <stdio.h>
917 #include <stdlib.h>
918 
919 #include <bitset>
920 #include <boost/circular_buffer.hpp>
921 
922 #include <lv2/lv2plug.in/ns/lv2core/lv2.h>
923 #include <lv2/lv2plug.in/ns/ext/dynmanifest/dynmanifest.h>
924 #include <lv2/lv2plug.in/ns/ext/atom/util.h>
925 #include <lv2/lv2plug.in/ns/ext/urid/urid.h>
926 
927 // Set this to the proper shared library extension for your system
928 #ifndef DLLEXT
929 #define DLLEXT ".so"
930 #endif
931 
932 #ifndef URI_PREFIX
933 #define URI_PREFIX "https://faustlv2.bitbucket.io"
934 #endif
935 
936 #ifndef PLUGIN_URI
937 #define PLUGIN_URI URI_PREFIX "/harm_trem"
938 #endif
939 
940 #define MIDI_EVENT_URI "http://lv2plug.in/ns/ext/midi#MidiEvent"
941 
942 /* Setting NVOICES at compile time overrides meta data in the Faust source. If
943    set, this must be an integer value >= 0. A nonzero value indicates an
944    instrument (VSTi) plugin with the given maximum number of voices. Use 1 for
945    a monophonic synthesizer, and 0 for a simple effect plugin. If NVOICES
946    isn't defined at compile time then the number of voices of an instrument
947    plugin can also be set with the global "nvoices" meta data key in the Faust
948    source. This setting also adds a special "polyphony" control to the plugin
949    which can be used to dynamically adjust the actual number of voices in the
950    range 1..NVOICES. */
951 //#define NVOICES 16
952 
953 /* This enables a special "tuning" control for instruments which lets you
954    select the MTS tuning to be used for the synth. In order to use this, you
955    just drop some sysex (.syx) files with MTS octave-based tunings in 1- or
956    2-byte format into the ~/.fautvst/tuning directory (these can be generated
957    with the author's sclsyx program, https://bitbucket.org/agraef/sclsyx).
958    The control will only be shown if any .syx files were found at startup. 0
959    selects the default tuning (standard 12-tone equal temperament), i>0 the
960    tuning in the ith sysex file (in alphabetic order). */
961 #ifndef FAUST_MTS
962 #define FAUST_MTS 1
963 #endif
964 
965 /* This allows various manifest data to be generated from the corresponding
966    metadata (author, name, description, license) in the Faust source. */
967 #ifndef FAUST_META
968 #define FAUST_META 1
969 #endif
970 
971 /* This enables automatic MIDI controller mapping based on the midi:ctrl
972    attributes in the Faust source. We have this enabled by default, but you
973    may have to disable it if the custom controller mapping gets in the way of
974    the automation facilities that the host provides. (But then again if the
975    host wants to do its own controller mapping then it probably won't, or at
976    least shouldn't, send us the MIDI controllers in the first place.) */
977 #ifndef FAUST_MIDICC
978 #define FAUST_MIDICC 1
979 #endif
980 
981 /* This enables or disables the plugin's custom Qt GUI (cf. lv2ui.cpp). Note
982    that this only affects the plugin manifest, the GUI code itself is in a
983    separate module created with the lv2ui.cpp architecture. Also, you'll have
984    to use the alternative lv2ui manifest templates to tell the LV2 host about
985    the GUI. */
986 #ifndef FAUST_UI
987 #define FAUST_UI 0
988 #endif
989 
990 // You can define these for various debugging output items.
991 //#define DEBUG_META 1 // recognized MIDI controller metadata
992 //#define DEBUG_VOICES 1 // triggering of synth voices
993 //#define DEBUG_VOICE_ALLOC 1 // voice allocation
994 //#define DEBUG_MIDI 1 // incoming MIDI messages
995 //#define DEBUG_NOTES 1 // note messages
996 //#define DEBUG_MIDICC 1 // controller messages
997 //#define DEBUG_RPN 1 // RPN messages (pitch bend range, master tuning)
998 //#define DEBUG_MTS 1 // MTS messages (octave/scale tuning)
999 
1000 // Note and voice data structures.
1001 
1002 struct NoteInfo {
1003   uint8_t ch;
1004   int8_t note;
1005 };
1006 
1007 struct VoiceData {
1008   // Octave tunings (offsets in semitones) per MIDI channel.
1009   float tuning[16][12];
1010   // Allocated voices per MIDI channel and note.
1011   int8_t notes[16][128];
1012   // Free and used voices.
1013   int n_free, n_used;
1014   boost::circular_buffer<int> free_voices;
1015   boost::circular_buffer<int> used_voices;
1016   NoteInfo *note_info;
1017   // Voices queued for note-offs (zero-length notes).
1018   set<int> queued;
1019   // Last gate value during run() for each voice. We need to keep track of
1020   // these so that we can force the Faust synth to retrigger a note when
1021   // needed.
1022   float *lastgate;
1023   // Current pitch bend and pitch bend range on each MIDI channel, in semitones.
1024   float bend[16], range[16];
1025   // Current coarse, fine and total master tuning on each MIDI channel (tuning
1026   // offset relative to A4 = 440 Hz, in semitones).
1027   float coarse[16], fine[16], tune[16];
VoiceDataVoiceData1028   VoiceData(int n) : free_voices(n), used_voices(n) { }
1029 };
1030 
1031 #if FAUST_MTS
1032 
1033 // Helper classes to read and store MTS tunings.
1034 
1035 #include <sys/types.h>
1036 #include <sys/stat.h>
1037 #include <dirent.h>
1038 
1039 #include <string>
1040 #include <vector>
1041 
1042 struct MTSTuning {
1043   char *name; // name of the tuning
1044   int len; // length of sysex data in bytes
1045   unsigned char *data; // sysex data
MTSTuningMTSTuning1046   MTSTuning() : name(0), len(0), data(0) {}
operator =MTSTuning1047   MTSTuning& operator=(const MTSTuning &t)
1048   {
1049     if (this == &t) return *this;
1050     if (name) free(name); if (data) free(data);
1051     name = 0; data = 0; len = t.len;
1052     if (t.name) {
1053       name = strdup(t.name); assert(name);
1054     }
1055     if (t.data) {
1056       data = (unsigned char*)malloc(len); assert(data);
1057       memcpy(data, t.data, len);
1058     }
1059     return *this;
1060   }
MTSTuningMTSTuning1061   MTSTuning(const MTSTuning& t) : name(0), len(0), data(0)
1062   { *this = t; }
1063   MTSTuning(const char *filename);
~MTSTuningMTSTuning1064   ~MTSTuning()
1065   { if (name) free(name); if (data) free(data); }
1066 };
1067 
MTSTuning(const char * filename)1068 MTSTuning::MTSTuning(const char *filename)
1069 {
1070   FILE *fp = fopen(filename, "rb");
1071   name = 0; len = 0; data = 0;
1072   if (!fp) return;
1073   struct stat st;
1074   if (fstat(fileno(fp), &st)) return;
1075   len = st.st_size;
1076   data = (unsigned char*)calloc(len, 1);
1077   if (!data) {
1078     len = 0; fclose(fp);
1079     return;
1080   }
1081   assert(len > 0);
1082   if (fread(data, 1, len, fp) < len) {
1083     free(data); len = 0; data = 0; fclose(fp);
1084     return;
1085   }
1086   fclose(fp);
1087   // Do some basic sanity checks.
1088   if (data[0] != 0xf0 || data[len-1] != 0xf7 || // not a sysex message
1089       (data[1] != 0x7e && data[1] != 0x7f) || data[3] != 8 || // not MTS
1090       !((len == 21 && data[4] == 8) ||
1091 	(len == 33 && data[4] == 9))) { // no 1- or 2-byte tuning
1092     free(data); len = 0; data = 0;
1093     return;
1094   }
1095   // Name of the tuning is the basename of the file, without the trailing .syx
1096   // suffix.
1097   string nm = filename;
1098   size_t p = nm.rfind(".syx");
1099   if (p != string::npos) nm.erase(p);
1100   p = nm.rfind('/');
1101   if (p != string::npos) nm.erase(0, p+1);
1102   name = strdup(nm.c_str());
1103   assert(name);
1104 }
1105 
1106 struct MTSTunings {
1107   vector<MTSTuning> tuning;
MTSTuningsMTSTunings1108   MTSTunings() {}
1109   MTSTunings(const char *path);
1110 };
1111 
compareByName(const MTSTuning & a,const MTSTuning & b)1112 static bool compareByName(const MTSTuning &a, const MTSTuning &b)
1113 {
1114   return strcmp(a.name, b.name) < 0;
1115 }
1116 
MTSTunings(const char * path)1117 MTSTunings::MTSTunings(const char *path)
1118 {
1119   DIR *dp = opendir(path);
1120   if (!dp) return;
1121   struct dirent *d;
1122   while ((d = readdir(dp))) {
1123     string nm = d->d_name;
1124     if (nm.length() > 4 && nm.substr(nm.length()-4) == ".syx") {
1125       string pathname = path;
1126       pathname += "/";
1127       pathname += nm;
1128       MTSTuning t(pathname.c_str());
1129       if (t.data) tuning.push_back(t);
1130     }
1131   }
1132   closedir(dp);
1133   // sort found tunings by name
1134   sort(tuning.begin(), tuning.end(), compareByName);
1135 }
1136 
1137 #endif
1138 
1139 #if FAUST_MIDICC
ctrlval(const ui_elem_t & el,uint8_t v)1140 static float ctrlval(const ui_elem_t &el, uint8_t v)
1141 {
1142   // Translate the given MIDI controller value to the range and stepsize
1143   // indicated by the Faust control.
1144   switch (el.type) {
1145   case UI_BUTTON: case UI_CHECK_BUTTON:
1146     return (float)(v>=64);
1147   default:
1148     /* Continuous controllers. The problem here is that the range 0..127 is
1149        not symmetric. We'd like to map 64 to the center of the range
1150        (max-min)/2 and at the same time retain the full control range
1151        min..max. So let's just pretend that there are 128 controller values
1152        and map value 127 to the max value anyway. */
1153     if (v==127)
1154       return el.max;
1155     else
1156       // XXXFIXME: We might want to add proper quantization according to
1157       // el.step here.
1158       return el.min+(el.max-el.min)*v/128;
1159   }
1160 }
1161 #endif
1162 
1163 /***************************************************************************/
1164 
1165 /* Polyphonic Faust plugin data structure. XXXTODO: At present this is just a
1166    big struct which exposes all requisite data. Some more work is needed to
1167    make the interface a bit more abstract and properly encapsulate the
1168    internal data structures, so that implementation details can be changed
1169    more easily. */
1170 
1171 struct LV2Plugin {
1172   const int maxvoices;	// maximum number of voices (zero if not an instrument)
1173   const int ndsps;	// number of dsp instances (1 if maxvoices==0)
1174   bool active;		// activation status
1175   int rate;		// sampling rate
1176   int nvoices;		// current number of voices (<= maxvoices)
1177   int tuning_no;	// current tuning number (<= n_tunings)
1178   harm_trem **dsp;		// the dsps
1179   LV2UI **ui;		// their Faust interface descriptions
1180   int n_in, n_out;	// number of input and output control ports
1181   int *ctrls;		// Faust ui elements (indices into ui->elems)
1182   float **ports;	// corresponding LV2 data
1183   float *portvals;	// cached port data from the last run
1184   float *midivals[16];	// per-midi channel data
1185   int *inctrls, *outctrls;	// indices for active and passive controls
1186   float **inputs, **outputs;	// audio buffers
1187   int freq, gain, gate;	// indices of voice controls
1188   unsigned n_samples;	// current block size
1189   float **outbuf;	// audio buffers for mixing down the voices
1190   float **inbuf;	// dummy input buffer
1191   LV2_Atom_Sequence* event_port; // midi input
1192   float *poly, *tuning;	// polyphony and tuning ports
1193   std::map<uint8_t,int> ctrlmap; // MIDI controller map
1194   // Needed host features.
1195   LV2_URID_Map* map;	// the urid extension
1196   LV2_URID midi_event;	// midi event uri
1197   // Current RPN MSB and LSB numbers, as set with controllers 101 and 100.
1198   uint8_t rpn_msb[16], rpn_lsb[16];
1199   // Current data entry MSB and LSB numbers, as set with controllers 6 and 38.
1200   uint8_t data_msb[16], data_lsb[16];
1201   // Synth voice data (instruments only).
1202   VoiceData *vd;
1203 
1204   // Static methods. These all use static data so they can be invoked before
1205   // instantiating a plugin.
1206 
1207   // Global meta data (dsp name, author, etc.).
1208   static Meta *meta;
init_metaLV2Plugin1209   static void init_meta()
1210   {
1211     if (!meta && (meta = new Meta)) {
1212       // We allocate the temporary dsp object on the heap here, to prevent
1213       // large dsp objects from running out of stack in environments where
1214       // stack space is precious (e.g., Reaper). Note that if any of these
1215       // allocations fail then no meta data will be available, but at least we
1216       // won't make the host crash and burn.
1217       harm_trem* tmp_dsp = new harm_trem();
1218       if (tmp_dsp) {
1219 	tmp_dsp->metadata(meta);
1220 	delete tmp_dsp;
1221       }
1222     }
1223   }
meta_getLV2Plugin1224   static const char *meta_get(const char *key, const char *deflt)
1225   {
1226     init_meta();
1227     return meta?meta->get(key, deflt):deflt;
1228   }
1229 
pluginNameLV2Plugin1230   static const char *pluginName()
1231   {
1232     return meta_get("name", "harm_trem");
1233   }
1234 
pluginAuthorLV2Plugin1235   static const char *pluginAuthor()
1236   {
1237     return meta_get("author", "");
1238   }
1239 
pluginDescriptionLV2Plugin1240   static const char *pluginDescription()
1241   {
1242     return meta_get("description", "");
1243   }
1244 
pluginLicenseLV2Plugin1245   static const char *pluginLicense()
1246   {
1247     return meta_get("license", "");
1248   }
1249 
pluginVersionLV2Plugin1250   static const char *pluginVersion()
1251   {
1252     return meta_get("version", "");
1253   }
1254 
1255   // Load a collection of sysex files with MTS tunings in ~/.faust/tuning.
1256   static int n_tunings;
1257 #if FAUST_MTS
1258   static MTSTunings *mts;
1259 
load_sysex_dataLV2Plugin1260   static MTSTunings *load_sysex_data()
1261   {
1262     if (!mts) {
1263       string mts_path;
1264       // Look for FAUST_HOME. If that isn't set, try $HOME/.faust. If HOME
1265       // isn't set either, just assume a .faust subdir of the cwd.
1266       const char *home = getenv("FAUST_HOME");
1267       if (home)
1268 	mts_path = home;
1269       else {
1270 	home = getenv("HOME");
1271 	if (home) {
1272 	  mts_path = home;
1273 	  mts_path += "/.faust";
1274 	} else
1275 	  mts_path = ".faust";
1276       }
1277       // MTS tunings are looked for in this subdir.
1278       mts_path += "/tuning";
1279       mts = new MTSTunings(mts_path.c_str());
1280 #ifdef __APPLE__
1281       if (!mts || mts->tuning.size() == 0) {
1282 	// Also check ~/Library/Faust/Tuning on the Mac.
1283 	home = getenv("HOME");
1284 	if (home) {
1285 	  if (mts) delete mts;
1286 	  mts_path = home;
1287 	  mts_path += "/Library/Faust/Tuning";
1288 	  mts = new MTSTunings(mts_path.c_str());
1289 	}
1290       }
1291 #endif
1292       n_tunings = mts->tuning.size();
1293     }
1294     return mts;
1295   }
1296 #endif
1297 
1298   // The number of voices of an instrument plugin. We get this information
1299   // from the global meta data (nvoices key) of the dsp module if present, and
1300   // you can also override this setting at compile time by defining the
1301   // NVOICES macro. If neither is defined or the value is zero then the plugin
1302   // becomes a simple audio effect instead.
numVoicesLV2Plugin1303   static int numVoices()
1304   {
1305 #ifdef NVOICES
1306     return NVOICES;
1307 #else
1308     const char *numVoices = meta_get("nvoices", "0");
1309     int nvoices = atoi(numVoices);
1310     if (nvoices < 0 ) nvoices = 0;
1311     return nvoices;
1312 #endif
1313   }
1314 
1315   // Instance methods.
1316 
LV2PluginLV2Plugin1317   LV2Plugin(const int num_voices, const int sr)
1318     : maxvoices(num_voices), ndsps(num_voices<=0?1:num_voices),
1319       vd(num_voices>0?new VoiceData(num_voices):0)
1320   {
1321     // Initialize static data.
1322     init_meta();
1323 #if FAUST_MTS
1324     // Synth: load tuning sysex data if present.
1325     if (num_voices>0) load_sysex_data();
1326 #endif
1327     // Allocate data structures and set some reasonable defaults.
1328     dsp = (harm_trem**)calloc(ndsps, sizeof(harm_trem*));
1329     ui = (LV2UI**)calloc(ndsps, sizeof(LV2UI*));
1330     assert(dsp && ui);
1331     if (vd) {
1332       vd->note_info = (NoteInfo*)calloc(ndsps, sizeof(NoteInfo));
1333       vd->lastgate = (float*)calloc(ndsps, sizeof(float));
1334       assert(vd->note_info && vd->lastgate);
1335     }
1336     active = false;
1337     rate = sr;
1338     nvoices = maxvoices;
1339     tuning_no = 0;
1340     n_in = n_out = 0;
1341     map = NULL;
1342     midi_event = -1;
1343     event_port = NULL;
1344     poly = tuning = NULL;
1345     freq = gain = gate = -1;
1346     if (vd) {
1347       vd->n_free = maxvoices;
1348       for (int i = 0; i < maxvoices; i++) {
1349 	vd->free_voices.push_back(i);
1350 	vd->lastgate[i] = 0.0f;
1351       }
1352       for (int i = 0; i < 16; i++) {
1353 	vd->bend[i] = 0.0f;
1354 	vd->range[i] = 2.0f;
1355 	vd->coarse[i] = vd->fine[i] = vd->tune[i] = 0.0f;
1356 	for (int j = 0; j < 12; j++)
1357 	  vd->tuning[i][j] = 0.0f;
1358       }
1359       vd->n_used = 0;
1360       memset(vd->notes, 0xff, sizeof(vd->notes));
1361     }
1362     n_samples = 0;
1363     ctrls = inctrls = outctrls = NULL;
1364     ports = inputs = outputs = inbuf = outbuf = NULL;
1365     portvals = NULL;
1366     memset(midivals, 0, sizeof(midivals));
1367     // Initialize the Faust DSPs.
1368     for (int i = 0; i < ndsps; i++) {
1369       dsp[i] = new harm_trem();
1370       ui[i] = new LV2UI(num_voices);
1371       dsp[i]->init(rate);
1372       dsp[i]->buildUserInterface(ui[i]);
1373     }
1374     // The ports are numbered as follows: 0..k-1 are the control ports, then
1375     // come the n audio input ports, then the m audio output ports, and
1376     // finally the midi input port and the polyphony and tuning controls.
1377     int k = ui[0]->nports, p = 0, q = 0;
1378     int n = dsp[0]->getNumInputs(), m = dsp[0]->getNumOutputs();
1379     // Allocate tables for the built-in control elements and their ports.
1380     ctrls = (int*)calloc(k, sizeof(int));
1381     inctrls = (int*)calloc(k, sizeof(int));
1382     outctrls = (int*)calloc(k, sizeof(int));
1383     ports = (float**)calloc(k, sizeof(float*));
1384     portvals = (float*)calloc(k, sizeof(float));
1385     assert(k == 0 || (ctrls && inctrls && outctrls && ports && portvals));
1386     for (int ch = 0; ch < 16; ch++) {
1387       midivals[ch] = (float*)calloc(k, sizeof(float));
1388       assert(k == 0 || midivals[ch]);
1389     }
1390     // Scan the Faust UI for active and passive controls which become the
1391     // input and output control ports of the plugin, respectively.
1392     for (int i = 0, j = 0; i < ui[0]->nelems; i++) {
1393       switch (ui[0]->elems[i].type) {
1394       case UI_T_GROUP: case UI_H_GROUP: case UI_V_GROUP: case UI_END_GROUP:
1395 	// control groups (ignored right now)
1396 	break;
1397       case UI_H_BARGRAPH: case UI_V_BARGRAPH:
1398 	// passive controls (output ports)
1399 	ctrls[j++] = i;
1400 	outctrls[q++] = i;
1401 	break;
1402       default:
1403 	// active controls (input ports)
1404 	if (maxvoices == 0)
1405 	  goto noinstr;
1406 	else if (freq == -1 &&
1407 		 !strcmp(ui[0]->elems[i].label, "freq"))
1408 	  freq = i;
1409 	else if (gain == -1 &&
1410 		 !strcmp(ui[0]->elems[i].label, "gain"))
1411 	  gain = i;
1412 	else if (gate == -1 &&
1413 		 !strcmp(ui[0]->elems[i].label, "gate"))
1414 	  gate = i;
1415 	else {
1416 	noinstr:
1417 #if FAUST_MIDICC
1418 	  std::map< int, list<strpair> >::iterator it =
1419 	    ui[0]->metadata.find(i);
1420 	  if (it != ui[0]->metadata.end()) {
1421 	    // Scan for controller mappings.
1422 	    for (std::list<strpair>::iterator jt = it->second.begin();
1423 		 jt != it->second.end(); jt++) {
1424 	      const char *key = jt->first, *val = jt->second;
1425 #if DEBUG_META
1426 	      fprintf(stderr, "ctrl '%s' meta: '%s' -> '%s'\n",
1427 		      ui[0]->elems[i].label, key, val);
1428 #endif
1429 	      if (strcmp(key, "midi") == 0) {
1430 		unsigned num;
1431 		if (sscanf(val, "ctrl %u", &num) < 1) continue;
1432 #if 0 // enable this to get feedback about controller assignments
1433 		fprintf(stderr, "%s: cc %d -> %s\n", PLUGIN_URI, num,
1434 			ui[0]->elems[i].label);
1435 #endif
1436 		ctrlmap.insert(std::pair<uint8_t,int>(num, p));
1437 	      }
1438 	    }
1439 	  }
1440 #endif
1441 	  ctrls[j++] = i;
1442 	  inctrls[p++] = i;
1443 	  int p = ui[0]->elems[i].port;
1444 	  float val = ui[0]->elems[i].init;
1445 	  assert(p>=0);
1446 	  portvals[p] = val;
1447 	  for (int ch = 0; ch < 16; ch++)
1448 	    midivals[ch][p] = val;
1449 	}
1450 	break;
1451       }
1452     }
1453     // Realloc the inctrls and outctrls vectors to their appropriate sizes.
1454     inctrls = (int*)realloc(inctrls, p*sizeof(int));
1455     assert(p == 0 || inctrls);
1456     outctrls = (int*)realloc(outctrls, q*sizeof(int));
1457     assert(q == 0 || outctrls);
1458     n_in = p; n_out = q;
1459     // Allocate vectors for the audio input and output ports. Like
1460     // ports, these will be initialized in the connect_port callback.
1461     inputs = (float**)calloc(n, sizeof(float*));
1462     assert(n == 0 || inputs);
1463     outputs = (float**)calloc(m, sizeof(float*));
1464     assert(m == 0 || outputs);
1465     if (maxvoices > 0) {
1466       // Initialize the mixdown buffer.
1467       outbuf = (float**)calloc(m, sizeof(float*));
1468       assert(m == 0 || outbuf);
1469       // We start out with a blocksize of 512 samples here. Hopefully this is
1470       // enough for most realtime hosts so that we can avoid reallocations
1471       // later when we know what the actual blocksize is.
1472       n_samples = 512;
1473       for (int i = 0; i < m; i++) {
1474 	outbuf[i] = (float*)malloc(n_samples*sizeof(float));
1475 	assert(outbuf[i]);
1476       }
1477       // Initialize a 1-sample dummy input buffer used for retriggering notes.
1478       inbuf = (float**)calloc(n, sizeof(float*));
1479       assert(n == 0 || inbuf);
1480       for (int i = 0; i < m; i++) {
1481 	inbuf[i] = (float*)malloc(sizeof(float));
1482 	assert(inbuf[i]);
1483 	*inbuf[i] = 0.0f;
1484       }
1485     }
1486   }
1487 
~LV2PluginLV2Plugin1488   ~LV2Plugin()
1489   {
1490     const int n = dsp[0]->getNumInputs();
1491     const int m = dsp[0]->getNumOutputs();
1492     for (int i = 0; i < ndsps; i++) {
1493       delete dsp[i];
1494       delete ui[i];
1495     }
1496     free(ctrls); free(inctrls); free(outctrls);
1497     free(ports); free(portvals);
1498     free(inputs); free(outputs);
1499     for (int ch = 0; ch < 16; ch++)
1500       free(midivals[ch]);
1501     if (inbuf) {
1502       for (int i = 0; i < n; i++)
1503 	free(inbuf[i]);
1504       free(inbuf);
1505     }
1506     if (outbuf) {
1507       for (int i = 0; i < m; i++)
1508 	free(outbuf[i]);
1509       free(outbuf);
1510     }
1511     free(dsp); free(ui);
1512     if (vd) {
1513       free(vd->note_info);
1514       free(vd->lastgate);
1515       delete vd;
1516     }
1517   }
1518   // Voice allocation.
1519 
1520 #if DEBUG_VOICE_ALLOC
print_voicesLV2Plugin1521   void print_voices(const char *msg)
1522   {
1523     fprintf(stderr, "%s: notes =", msg);
1524     for (uint8_t ch = 0; ch < 16; ch++)
1525       for (int note = 0; note < 128; note++)
1526 	if (vd->notes[ch][note] >= 0)
1527 	  fprintf(stderr, " [%d] %d(#%d)", ch, note, vd->notes[ch][note]);
1528     fprintf(stderr, "\nqueued (%d):", vd->queued.size());
1529     for (int i = 0; i < nvoices; i++)
1530       if (vd->queued.find(i) != vd->queued.end()) fprintf(stderr, " #%d", i);
1531     fprintf(stderr, "\nused (%d):", vd->n_used);
1532     for (boost::circular_buffer<int>::iterator it = vd->used_voices.begin();
1533 	 it != vd->used_voices.end(); it++)
1534       fprintf(stderr, " #%d->%d", *it, vd->note_info[*it].note);
1535     fprintf(stderr, "\nfree (%d):", vd->n_free);
1536     for (boost::circular_buffer<int>::iterator it = vd->free_voices.begin();
1537 	 it != vd->free_voices.end(); it++)
1538       fprintf(stderr, " #%d", *it);
1539     fprintf(stderr, "\n");
1540   }
1541 #endif
1542 
alloc_voiceLV2Plugin1543   int alloc_voice(uint8_t ch, int8_t note, int8_t vel)
1544   {
1545     int i = vd->notes[ch][note];
1546     if (i >= 0) {
1547       // note already playing on same channel, retrigger it
1548       voice_off(i);
1549       voice_on(i, note, vel, ch);
1550       // move this voice to the end of the used list
1551       for (boost::circular_buffer<int>::iterator it =
1552 	     vd->used_voices.begin();
1553 	   it != vd->used_voices.end(); it++) {
1554 	if (*it == i) {
1555 	  vd->used_voices.erase(it);
1556 	  vd->used_voices.push_back(i);
1557 	  break;
1558 	}
1559       }
1560 #if DEBUG_VOICE_ALLOC
1561       print_voices("retrigger");
1562 #endif
1563       return i;
1564     } else if (vd->n_free > 0) {
1565       // take voice from free list
1566       int i = vd->free_voices.front();
1567       vd->free_voices.pop_front();
1568       vd->n_free--;
1569       vd->used_voices.push_back(i);
1570       vd->note_info[i].ch = ch;
1571       vd->note_info[i].note = note;
1572       vd->n_used++;
1573       voice_on(i, note, vel, ch);
1574       vd->notes[ch][note] = i;
1575 #if DEBUG_VOICE_ALLOC
1576       print_voices("alloc");
1577 #endif
1578       return i;
1579     } else {
1580       // steal a voice
1581       assert(vd->n_used > 0);
1582       // FIXME: Maybe we should look for the oldest note on the *current*
1583       // channel here, but this is faster.
1584       int i = vd->used_voices.front();
1585       int oldch = vd->note_info[i].ch;
1586       int oldnote = vd->note_info[i].note;
1587       voice_off(i);
1588       vd->notes[oldch][oldnote] = -1;
1589       vd->queued.erase(i);
1590       vd->used_voices.pop_front();
1591       vd->used_voices.push_back(i);
1592       vd->note_info[i].ch = ch;
1593       vd->note_info[i].note = note;
1594       voice_on(i, note, vel, ch);
1595       vd->notes[ch][note] = i;
1596 #if DEBUG_VOICE_ALLOC
1597       print_voices("steal");
1598 #endif
1599       return i;
1600     }
1601   }
1602 
dealloc_voiceLV2Plugin1603   int dealloc_voice(uint8_t ch, int8_t note, int8_t vel)
1604   {
1605     int i = vd->notes[ch][note];
1606     if (i >= 0) {
1607       if (vd->lastgate[i] == 0.0f && gate >= 0) {
1608 	// zero-length note, queued for later
1609 	vd->queued.insert(i);
1610 	vd->notes[ch][note] = -1;
1611 #if DEBUG_VOICE_ALLOC
1612 	print_voices("dealloc (queued)");
1613 #endif
1614 	return i;
1615       }
1616       assert(vd->n_free < nvoices);
1617       vd->free_voices.push_back(i);
1618       vd->n_free++;
1619       voice_off(i);
1620       vd->notes[ch][note] = -1;
1621       // erase this voice from the used list
1622       for (boost::circular_buffer<int>::iterator it =
1623 	     vd->used_voices.begin();
1624 	   it != vd->used_voices.end(); it++) {
1625 	if (*it == i) {
1626 	  vd->used_voices.erase(it);
1627 	  vd->n_used--;
1628 	  break;
1629 	}
1630       }
1631 #if DEBUG_VOICE_ALLOC
1632       print_voices("dealloc");
1633 #endif
1634       return i;
1635     }
1636     return -1;
1637   }
1638 
1639 
midicpsLV2Plugin1640   float midicps(int8_t note, uint8_t chan)
1641   {
1642     float pitch = note + vd->tune[chan] +
1643       vd->tuning[chan][note%12] + vd->bend[chan];
1644     return 440.0*pow(2, (pitch-69.0)/12.0);
1645   }
1646 
voice_onLV2Plugin1647   void voice_on(int i, int8_t note, int8_t vel, uint8_t ch)
1648   {
1649     if (vd->lastgate[i] == 1.0f && gate >= 0) {
1650       // Make sure that the synth sees the 0.0f gate so that the voice is
1651       // properly retriggered.
1652       *ui[i]->elems[gate].zone = 0.0f;
1653       dsp[i]->compute(1, inbuf, outbuf);
1654     }
1655 #if DEBUG_VOICES
1656     fprintf(stderr, "voice on: %d %d (%g Hz) %d (%g)\n", i,
1657 	    note, midicps(note, ch), vel, vel/127.0);
1658 #endif
1659     if (freq >= 0)
1660       *ui[i]->elems[freq].zone = midicps(note, ch);
1661     if (gate >= 0)
1662       *ui[i]->elems[gate].zone = 1.0f;
1663     if (gain >= 0)
1664       *ui[i]->elems[gain].zone = vel/127.0;
1665     // reinitialize the per-channel control data for this voice
1666     for (int idx = 0; idx < n_in; idx++) {
1667       int j = inctrls[idx], k = ui[0]->elems[j].port;
1668       *ui[i]->elems[j].zone = midivals[ch][k];
1669     }
1670   }
1671 
voice_offLV2Plugin1672   void voice_off(int i)
1673   {
1674 #if DEBUG_VOICES
1675     fprintf(stderr, "voice off: %d\n", i);
1676 #endif
1677     if (gate >= 0)
1678       *ui[i]->elems[gate].zone = 0.0f;
1679   }
1680 
update_voicesLV2Plugin1681   void update_voices(uint8_t chan)
1682   {
1683     // update running voices on the given channel after tuning or pitch bend
1684     // changes
1685     for (boost::circular_buffer<int>::iterator it =
1686 	   vd->used_voices.begin();
1687 	 it != vd->used_voices.end(); it++) {
1688       int i = *it;
1689       if (vd->note_info[i].ch == chan && freq >= 0) {
1690 	int note = vd->note_info[i].note;
1691 	*ui[i]->elems[freq].zone = midicps(note, chan);
1692       }
1693     }
1694   }
1695 
all_notes_offLV2Plugin1696   void all_notes_off()
1697   {
1698     for (int i = 0; i < nvoices; i++)
1699       voice_off(i);
1700     for (int i = 0; i < 16; i++)
1701       vd->bend[i] = 0.0f;
1702     memset(vd->notes, 0xff, sizeof(vd->notes));
1703     vd->free_voices.clear();
1704     vd->n_free = nvoices;
1705     for (int i = 0; i < nvoices; i++)
1706       vd->free_voices.push_back(i);
1707     vd->queued.clear();
1708     vd->used_voices.clear();
1709     vd->n_used = 0;
1710   }
1711 
all_notes_offLV2Plugin1712   void all_notes_off(uint8_t chan)
1713   {
1714     for (boost::circular_buffer<int>::iterator it =
1715 	   vd->used_voices.begin();
1716 	 it != vd->used_voices.end(); ) {
1717       int i = *it;
1718       if (vd->note_info[i].ch == chan) {
1719 	assert(vd->n_free < nvoices);
1720 	vd->free_voices.push_back(i);
1721 	vd->n_free++;
1722 	voice_off(i);
1723 	vd->notes[vd->note_info[i].ch][vd->note_info[i].note] = -1;
1724 	vd->queued.erase(i);
1725 	// erase this voice from the used list
1726 	it = vd->used_voices.erase(it);
1727 	vd->n_used--;
1728 #if DEBUG_VOICE_ALLOC
1729 	print_voices("dealloc (all-notes-off)");
1730 #endif
1731       } else
1732 	it++;
1733     }
1734     vd->bend[chan] = 0.0f;
1735   }
1736 
queued_notes_offLV2Plugin1737   void queued_notes_off()
1738   {
1739     if (vd->queued.empty()) return;
1740     for (int i = 0; i < nvoices; i++)
1741       if (vd->queued.find(i) != vd->queued.end()) {
1742 	assert(vd->n_free < nvoices);
1743 	vd->free_voices.push_back(i);
1744 	vd->n_free++;
1745 	voice_off(i);
1746 	vd->notes[vd->note_info[i].ch][vd->note_info[i].note] = -1;
1747 	vd->queued.erase(i);
1748 	// erase this voice from the used list
1749 	for (boost::circular_buffer<int>::iterator it =
1750 	       vd->used_voices.begin();
1751 	     it != vd->used_voices.end(); it++) {
1752 	  if (*it == i) {
1753 	    vd->used_voices.erase(it);
1754 	    vd->n_used--;
1755 	    break;
1756 	  }
1757 	}
1758 #if DEBUG_VOICE_ALLOC
1759 	print_voices("dealloc (unqueued)");
1760 #endif
1761       }
1762   }
1763 
1764   // Plugin activation status. suspend() deactivates a plugin (disables audio
1765   // processing), resume() reactivates it. Also, set_rate() changes the sample
1766   // rate. Note that the audio and MIDI process functions (see below) can
1767   // still be called in deactivated state, but this is optional. The plugin
1768   // tries to do some reasonable processing in either case, no matter whether
1769   // the host plugin architecture actually executes callbacks in suspended
1770   // state or not.
1771 
suspendLV2Plugin1772   void suspend()
1773   {
1774     active = false;
1775     if (maxvoices > 0) all_notes_off();
1776   }
1777 
resumeLV2Plugin1778   void resume()
1779   {
1780     for (int i = 0; i < ndsps; i++)
1781       dsp[i]->init(rate);
1782     for (int i = 0, j = 0; i < ui[0]->nelems; i++) {
1783       int p = ui[0]->elems[i].port;
1784       if (p >= 0) {
1785 	float val = ui[0]->elems[i].init;
1786 	portvals[p] = val;
1787       }
1788     }
1789     active = true;
1790   }
1791 
set_rateLV2Plugin1792   void set_rate(int sr)
1793   {
1794     rate = sr;
1795     for (int i = 0; i < ndsps; i++)
1796       dsp[i]->init(rate);
1797   }
1798 
1799   // Audio and MIDI process functions. The plugin should run these in the
1800   // appropriate real-time callbacks.
1801 
process_audioLV2Plugin1802   void process_audio(int blocksz, float **inputs, float **outputs)
1803   {
1804     int n = dsp[0]->getNumInputs(), m = dsp[0]->getNumOutputs();
1805     AVOIDDENORMALS;
1806     if (maxvoices > 0) queued_notes_off();
1807     if (!active) {
1808       // Depending on the plugin architecture and host, this code might never
1809       // be invoked, since the plugin is deactivitated at this point. But
1810       // let's do something reasonable here anyway.
1811       if (n == m) {
1812 	// copy inputs to outputs
1813 	for (int i = 0; i < m; i++)
1814 	  for (unsigned j = 0; j < blocksz; j++)
1815 	    outputs[i][j] = inputs[i][j];
1816       } else {
1817 	// silence
1818 	for (int i = 0; i < m; i++)
1819 	  for (unsigned j = 0; j < blocksz; j++)
1820 	    outputs[i][j] = 0.0f;
1821       }
1822       return;
1823     }
1824     // Handle changes in the polyphony and tuning controls.
1825     bool is_instr = maxvoices > 0;
1826     if (is_instr) {
1827       if (!poly)
1828 	; // this shouldn't happen but...
1829       else if (nvoices != (int)*poly &&
1830 	       (int)*poly > 0 && (int)*poly <= maxvoices) {
1831 	for (int i = 0; i < nvoices; i++)
1832 	  voice_off(i);
1833         nvoices = (int)*poly;
1834 	// Reset the voice allocation.
1835 	memset(vd->notes, 0xff, sizeof(vd->notes));
1836 	vd->free_voices.clear();
1837 	vd->n_free = nvoices;
1838 	for (int i = 0; i < nvoices; i++)
1839 	  vd->free_voices.push_back(i);
1840 	vd->used_voices.clear();
1841 	vd->n_used = 0;
1842       } else
1843 	*poly = nvoices;
1844 #if FAUST_MTS
1845       if (tuning && tuning_no != (int)*tuning) change_tuning((int)*tuning);
1846 #endif
1847     }
1848     // Only update the controls (of all voices simultaneously) if a port value
1849     // actually changed. This is necessary to allow MIDI controllers to modify
1850     // the values for individual MIDI channels (see processEvents below). Also
1851     // note that this will be done *after* processing the MIDI controller data
1852     // for the current audio block, so manual inputs can still override these.
1853     for (int i = 0; i < n_in; i++) {
1854       int j = inctrls[i], k = ui[0]->elems[j].port;
1855       float &oldval = portvals[k], newval = *ports[k];
1856       if (newval != oldval) {
1857 	if (is_instr) {
1858 	  // instrument: update running voices
1859 	  for (boost::circular_buffer<int>::iterator it =
1860 		 vd->used_voices.begin();
1861 	       it != vd->used_voices.end(); it++) {
1862 	    int i = *it;
1863 	    *ui[i]->elems[j].zone = newval;
1864 	  }
1865 	} else {
1866 	  // simple effect: here we only have a single dsp instance
1867 	  *ui[0]->elems[j].zone = newval;
1868 	}
1869 	// also update the MIDI controller data for all channels (manual
1870 	// control input is always omni)
1871 	for (int ch = 0; ch < 16; ch++)
1872 	  midivals[ch][k] = newval;
1873 	// record the new value
1874 	oldval = newval;
1875       }
1876     }
1877     // Initialize the output buffers.
1878     if (n_samples < blocksz) {
1879       // We need to enlarge the buffers. We're not officially allowed to do
1880       // this here (presumably in the realtime thread), but since we usually
1881       // don't know the hosts's block size beforehand, there's really nothing
1882       // else that we can do. Let's just hope that doing this once suffices,
1883       // then hopefully noone will notice.
1884       if (outbuf) {
1885 	for (int i = 0; i < m; i++) {
1886 	  outbuf[i] = (float*)realloc(outbuf[i],
1887 				      blocksz*sizeof(float));
1888 	  assert(outbuf[i]);
1889 	}
1890       }
1891       n_samples = blocksz;
1892     }
1893     if (outbuf) {
1894       // Polyphonic instrument: Mix the voices down to one signal.
1895       for (int i = 0; i < m; i++)
1896 	for (unsigned j = 0; j < blocksz; j++)
1897 	  outputs[i][j] = 0.0f;
1898       for (int l = 0; l < nvoices; l++) {
1899 	// Let Faust do all the hard work.
1900 	dsp[l]->compute(blocksz, inputs, outbuf);
1901 	for (int i = 0; i < m; i++)
1902 	  for (unsigned j = 0; j < blocksz; j++)
1903 	    outputs[i][j] += outbuf[i][j];
1904       }
1905     } else {
1906       // Simple effect: We can write directly to the output buffer.
1907       dsp[0]->compute(blocksz, inputs, outputs);
1908     }
1909     // Finally grab the passive controls and write them back to the
1910     // corresponding control ports. NOTE: Depending on the plugin
1911     // architecture, this might require a host call to get the control GUI
1912     // updated in real-time (if the host supports this at all).
1913     // FIXME: It's not clear how to aggregate the data of the different
1914     // voices. We compute the maximum of each control for now.
1915     for (int i = 0; i < n_out; i++) {
1916       int j = outctrls[i], k = ui[0]->elems[j].port;
1917       float *z = ui[0]->elems[j].zone;
1918       *ports[k] = *z;
1919       for (int l = 1; l < nvoices; l++) {
1920 	float *z = ui[l]->elems[j].zone;
1921 	if (*ports[k] < *z)
1922 	  *ports[k] = *z;
1923       }
1924     }
1925     // Keep track of the last gates set for each voice, so that voices can be
1926     // forcibly retriggered if needed.
1927     if (gate >= 0)
1928       for (int i = 0; i < nvoices; i++)
1929 	vd->lastgate[i] =
1930 	  *ui[i]->elems[gate].zone;
1931   }
1932 
1933   // This processes just a single MIDI message, so to process an entire series
1934   // of MIDI events you'll have to loop over the event data in the plugin's
1935   // MIDI callback. XXXTODO: Sample-accurate processing of MIDI events.
1936 
process_midiLV2Plugin1937   void process_midi(unsigned char *data, int sz)
1938   {
1939 #if DEBUG_MIDI
1940     fprintf(stderr, "midi ev (%d bytes):", sz);
1941     for (int i = 0; i < sz; i++)
1942       fprintf(stderr, " 0x%0x", data[i]);
1943     fprintf(stderr, "\n");
1944 #endif
1945     uint8_t status = data[0] & 0xf0, chan = data[0] & 0x0f;
1946     bool is_instr = maxvoices > 0;
1947     switch (status) {
1948     case 0x90: {
1949       if (!is_instr) break;
1950       // note on
1951 #if DEBUG_NOTES
1952       fprintf(stderr, "note-on  chan %d, note %d, vel %d\n", chan+1,
1953 	      data[1], data[2]);
1954 #endif
1955       if (data[2] == 0) goto note_off;
1956       alloc_voice(chan, data[1], data[2]);
1957       break;
1958     }
1959     case 0x80: {
1960       if (!is_instr) break;
1961       // note off
1962 #if DEBUG_NOTES
1963       fprintf(stderr, "note-off chan %d, note %d, vel %d\n", chan+1,
1964 	      data[1], data[2]);
1965 #endif
1966       note_off:
1967       dealloc_voice(chan, data[1], data[2]);
1968       break;
1969     }
1970     case 0xe0: {
1971       if (!is_instr) break;
1972       // pitch bend
1973       // data[1] is LSB, data[2] MSB, range is 0..0x3fff (which maps to
1974       // -2..+2 semitones by default), center point is 0x2000 = 8192
1975       int val = data[1] | (data[2]<<7);
1976       vd->bend[chan] =
1977 	(val-0x2000)/8192.0f*vd->range[chan];
1978 #if DEBUG_MIDICC
1979       fprintf(stderr, "pitch-bend (chan %d): %g cent\n", chan+1,
1980 	      vd->bend[chan]*100.0);
1981 #endif
1982       update_voices(chan);
1983       break;
1984     }
1985     case 0xb0: {
1986       // controller change
1987       switch (data[1]) {
1988       case 120: case 123:
1989 	if (!is_instr) break;
1990 	// all-sound-off and all-notes-off controllers (these are treated
1991 	// the same in the current implementation)
1992 	all_notes_off(chan);
1993 #if DEBUG_MIDICC
1994 	fprintf(stderr, "all-notes-off (chan %d)\n", chan+1);
1995 #endif
1996 	break;
1997       case 121:
1998 	// all-controllers-off (in the current implementation, this just
1999 	// resets the RPN-related controllers)
2000 	data_msb[chan] = data_lsb[chan] = 0;
2001 	rpn_msb[chan] = rpn_lsb[chan] = 0x7f;
2002 #if DEBUG_MIDICC
2003 	fprintf(stderr, "all-controllers-off (chan %d)\n", chan+1);
2004 #endif
2005 	break;
2006       case 101: case 100:
2007 	// RPN MSB/LSB
2008 	if (data[1] == 101)
2009 	  rpn_msb[chan] = data[2];
2010 	else
2011 	  rpn_lsb[chan] = data[2];
2012 	break;
2013       case 6: case 38:
2014 	// data entry coarse/fine
2015 	if (data[1] == 6)
2016 	  data_msb[chan] = data[2];
2017 	else
2018 	  data_lsb[chan] = data[2];
2019 	goto rpn;
2020       case 96: case 97:
2021 	// data increment/decrement
2022 	/* NOTE: The specification of these controllers is a complete
2023 	   mess. Originally, the MIDI specification didn't have anything
2024 	   to say about their exact behaviour at all. Nowadays, the
2025 	   behaviour depends on which RPN or NRPN is being modified, which
2026 	   is also rather confusing. Fortunately, as we only handle RPNs
2027 	   0..2 here anyway, it's sufficient to assume the MSB for RPN #2
2028 	   (channel coarse tuning) and the LSB otherwise. */
2029 	if (rpn_msb[chan] == 0 && rpn_lsb[chan] == 2) {
2030 	  // modify the MSB
2031 	  if (data[1] == 96 && data_msb[chan] < 0x7f)
2032 	    data_msb[chan]++;
2033 	  else if (data[1] == 97 && data_msb[chan] > 0)
2034 	    data_msb[chan]--;
2035 	} else {
2036 	  // modify the LSB
2037 	  if (data[1] == 96 && data_lsb[chan] < 0x7f)
2038 	    data_lsb[chan]++;
2039 	  else if (data[1] == 97 && data_lsb[chan] > 0)
2040 	    data_lsb[chan]--;
2041 	}
2042       rpn:
2043 	if (!is_instr) break;
2044 	if (rpn_msb[chan] == 0) {
2045 	  switch (rpn_lsb[chan]) {
2046 	  case 0:
2047 	    // pitch bend range, coarse value is in semitones, fine value
2048 	    // in cents
2049 	    vd->range[chan] = data_msb[chan]+
2050 	      data_lsb[chan]/100.0;
2051 #if DEBUG_RPN
2052 	    fprintf(stderr, "pitch-bend-range (chan %d): %g cent\n", chan+1,
2053 		    vd->range[chan]*100.0);
2054 #endif
2055 	    break;
2056 	  case 1:
2057 	    {
2058 	      // channel fine tuning (14 bit value, range -100..+100 cents)
2059 	      int value = (data_msb[chan]<<7) |
2060 		data_lsb[chan];
2061 	      vd->fine[chan] = (value-8192)/8192.0f;
2062 	    }
2063 	    goto master_tune;
2064 	  case 2:
2065 	    // channel coarse tuning (only msb is used, range -64..+63
2066 	    // semitones)
2067 	    vd->coarse[chan] = data_msb[chan]-64;
2068 	  master_tune:
2069 	    vd->tune[chan] = vd->coarse[chan]+
2070 	      vd->fine[chan];
2071 #if DEBUG_RPN
2072 	    fprintf(stderr, "master-tuning (chan %d): %g cent\n", chan+1,
2073 		    vd->tune[chan]*100.0);
2074 #endif
2075 	    update_voices(chan);
2076 	    break;
2077 	  default:
2078 	    break;
2079 	  }
2080 	}
2081 	break;
2082       default: {
2083 #if FAUST_MIDICC
2084 	// interpret all other controller changes according to the MIDI
2085 	// controller map defined in the Faust plugin itself
2086 	std::map<uint8_t,int>::iterator it = ctrlmap.find(data[1]);
2087 	if (it != ctrlmap.end()) {
2088 	  // defined MIDI controller
2089 	  int j = inctrls[it->second],
2090 	    k = ui[0]->elems[j].port;
2091 	  float val = ctrlval(ui[0]->elems[j], data[2]);
2092 	  midivals[chan][k] = val;
2093 	  if (is_instr) {
2094 	    // instrument: update running voices on this channel
2095 	    for (boost::circular_buffer<int>::iterator it =
2096 		   vd->used_voices.begin();
2097 		 it != vd->used_voices.end(); it++) {
2098 	      int i = *it;
2099 	      if (vd->note_info[i].ch == chan)
2100 		*ui[i]->elems[j].zone = val;
2101 	    }
2102 	  } else {
2103 	    // simple effect: here we only have a single dsp instance and
2104 	    // we're operating in omni mode, so we just update the control no
2105 	    // matter what the midi channel is
2106 	    *ui[0]->elems[j].zone = val;
2107 	  }
2108 #if DEBUG_MIDICC
2109 	  fprintf(stderr, "ctrl-change chan %d, ctrl %d, val %d\n", chan+1,
2110 		  data[1], data[2]);
2111 #endif
2112 	}
2113 #endif
2114 	break;
2115       }
2116       }
2117       break;
2118     }
2119     default:
2120       break;
2121     }
2122   }
2123 
2124   // Process an MTS sysex message and update the control values accordingly.
2125 
process_sysexLV2Plugin2126   void process_sysex(uint8_t *data, int sz)
2127   {
2128     if (!data || sz < 2) return;
2129 #if DEBUG_MIDI
2130     fprintf(stderr, "midi sysex (%d bytes):", sz);
2131     for (int i = 0; i < sz; i++)
2132       fprintf(stderr, " 0x%0x", data[i]);
2133     fprintf(stderr, "\n");
2134 #endif
2135     if (data[0] == 0xf0) {
2136       // Skip over the f0 and f7 status bytes in case they are included in the
2137       // dump.
2138       data++; sz--;
2139       if (data[sz-1] == 0xf7) sz--;
2140     }
2141     if ((data[0] == 0x7e || data[0] == 0x7f) && data[2] == 8) {
2142       // MIDI tuning standard
2143       bool realtime = data[0] == 0x7f;
2144       if ((sz == 19 && data[3] == 8) ||
2145 	  (sz == 31 && data[3] == 9)) {
2146 	// MTS scale/octave tuning 1- or 2-byte form
2147 	bool onebyte = data[3] == 8;
2148 	unsigned chanmsk = (data[4]<<14) | (data[5]<<7) | data[6];
2149 	for (int i = 0; i < 12; i++) {
2150 	  float t;
2151 	  if (onebyte)
2152 	    t = (data[i+7]-64)/100.0;
2153 	  else
2154 	    t = (((data[2*i+7]<<7)|data[2*i+8])-8192)/8192.0;
2155 	  for (uint8_t ch = 0; ch < 16; ch++)
2156 	    if (chanmsk & (1<<ch))
2157 	      vd->tuning[ch][i] = t;
2158 	}
2159 	if (realtime) {
2160 	  for (uint8_t ch = 0; ch < 16; ch++)
2161 	    if (chanmsk & (1<<ch)) {
2162 	      // update running voices on this channel
2163 	      update_voices(ch);
2164 	    }
2165 	}
2166 #if DEBUG_MTS
2167 	fprintf(stderr, "octave-tuning-%s (chan ",
2168 		realtime?"realtime":"non-realtime");
2169 	bool first = true;
2170 	for (uint8_t i = 0; i < 16; )
2171 	  if (chanmsk & (1<<i)) {
2172 	    uint8_t j;
2173 	    for (j = i+1; j < 16 && (chanmsk&(1<<j)); )
2174 	      j++;
2175 	    if (first)
2176 	      first = false;
2177 	    else
2178 	      fprintf(stderr, ",");
2179 	    if (j > i+1)
2180 	      fprintf(stderr, "%u-%u", i+1, j);
2181 	    else
2182 	      fprintf(stderr, "%u", i+1);
2183 	    i = j;
2184 	  } else
2185 	    i++;
2186 	fprintf(stderr, "):");
2187 	if (onebyte) {
2188 	  for (int i = 7; i < 19; i++) {
2189 	    int val = data[i];
2190 	    fprintf(stderr, " %d", val-64);
2191 	  }
2192 	} else {
2193 	  for (int i = 7; i < 31; i++) {
2194 	    int val = data[i++] << 7;
2195 	    val |= data[i];
2196 	    fprintf(stderr, " %g", ((double)val-8192.0)/8192.0*100.0);
2197 	  }
2198 	}
2199 	fprintf(stderr, "\n");
2200 #endif
2201       }
2202     }
2203   }
2204 
2205   // Change to a given preloaded tuning. The given tuning number may be in the
2206   // range 1..PFaustPlugin::n_tunings, zero denotes the default tuning (equal
2207   // temperament). This is only supported if FAUST_MTS is defined at compile
2208   // time.
2209 
change_tuningLV2Plugin2210   void change_tuning(int num)
2211   {
2212 #if FAUST_MTS
2213     if (!mts || num == tuning_no) return;
2214     if (num < 0) num = 0;
2215     if (num > mts->tuning.size())
2216       num = mts->tuning.size();
2217     tuning_no = num;
2218     if (tuning_no > 0) {
2219       process_sysex(mts->tuning[tuning_no-1].data,
2220 		    mts->tuning[tuning_no-1].len);
2221     } else {
2222       memset(vd->tuning, 0, sizeof(vd->tuning));
2223 #if DEBUG_MTS
2224       fprintf(stderr,
2225 	      "octave-tuning-default (chan 1-16): equal temperament\n");
2226 #endif
2227     }
2228 #endif
2229   }
2230 
2231 };
2232 
2233 Meta *LV2Plugin::meta = 0;
2234 int LV2Plugin::n_tunings = 0;
2235 #if FAUST_MTS
2236 MTSTunings *LV2Plugin::mts = 0;
2237 #endif
2238 
2239 /* LV2-specific part starts here. ********************************************/
2240 
2241 static LV2_Handle
instantiate(const LV2_Descriptor * descriptor,double rate,const char * bundle_path,const LV2_Feature * const * features)2242 instantiate(const LV2_Descriptor*     descriptor,
2243             double                    rate,
2244             const char*               bundle_path,
2245             const LV2_Feature* const* features)
2246 {
2247   LV2Plugin* plugin =
2248     new LV2Plugin(LV2Plugin::numVoices(), (int)rate);
2249   // Scan host features for URID map.
2250   for (int i = 0; features[i]; i++) {
2251     if (!strcmp(features[i]->URI, LV2_URID_URI "#map")) {
2252       plugin->map = (LV2_URID_Map*)features[i]->data;
2253       plugin->midi_event =
2254 	plugin->map->map(plugin->map->handle, MIDI_EVENT_URI);
2255     }
2256   }
2257   if (!plugin->map) {
2258     fprintf
2259       (stderr, "%s: host doesn't support urid:map, giving up\n",
2260        PLUGIN_URI);
2261     delete plugin;
2262     return 0;
2263   }
2264   return (LV2_Handle)plugin;
2265 }
2266 
2267 static void
cleanup(LV2_Handle instance)2268 cleanup(LV2_Handle instance)
2269 {
2270   LV2Plugin* plugin = (LV2Plugin*)instance;
2271   delete plugin;
2272 }
2273 
2274 static void
connect_port(LV2_Handle instance,uint32_t port,void * data)2275 connect_port(LV2_Handle instance,
2276              uint32_t   port,
2277              void*      data)
2278 {
2279   LV2Plugin* plugin = (LV2Plugin*)instance;
2280   int i = port, k = plugin->ui[0]->nports;
2281   int n = plugin->dsp[0]->getNumInputs(), m = plugin->dsp[0]->getNumOutputs();
2282   if (i < k)
2283     plugin->ports[i] = (float*)data;
2284   else {
2285     i -= k;
2286     if (i < n)
2287       plugin->inputs[i] = (float*)data;
2288     else {
2289       i -= n;
2290       if (i < m)
2291 	plugin->outputs[i] = (float*)data;
2292       else if (i == m)
2293 	plugin->event_port = (LV2_Atom_Sequence*)data;
2294       else if (i == m+1)
2295 	plugin->poly = (float*)data;
2296       else if (i == m+2)
2297 	plugin->tuning = (float*)data;
2298       else
2299 	fprintf(stderr, "%s: bad port number %u\n", PLUGIN_URI, port);
2300     }
2301   }
2302 }
2303 
2304 static void
run(LV2_Handle instance,uint32_t n_samples)2305 run(LV2_Handle instance, uint32_t n_samples)
2306 {
2307   LV2Plugin* plugin = (LV2Plugin*)instance;
2308   // Process incoming MIDI events.
2309   if (plugin->event_port) {
2310     LV2_ATOM_SEQUENCE_FOREACH(plugin->event_port, ev) {
2311       if (ev->body.type == plugin->midi_event) {
2312 	uint8_t *data = (uint8_t*)(ev+1);
2313 #if 0
2314 	// FIXME: Consider doing sample-accurate note onsets here. LV2 keeps
2315 	// track of the exact onset in the frames and subframes fields
2316 	// (http://lv2plug.in/ns/doc/html/structLV2__Atom__Event.html), but we
2317 	// can't use that information at present, since our gate parameter is
2318 	// a control variable which can only change at block boundaries. In
2319 	// the future, the gate could be implemented as an audio signal to get
2320 	// sample-accurate note onsets.
2321 	uint32_t frames = ev->body.frames;
2322 #endif
2323 	if (data[0] == 0xf0)
2324 	  plugin->process_sysex(data, ev->body.size);
2325 	else
2326 	  plugin->process_midi(data, ev->body.size);
2327       }
2328     }
2329   }
2330   // Process audio.
2331   plugin->process_audio(n_samples, plugin->inputs, plugin->outputs);
2332 }
2333 
2334 static void
activate(LV2_Handle instance)2335 activate(LV2_Handle instance)
2336 {
2337   LV2Plugin* plugin = (LV2Plugin*)instance;
2338   plugin->resume();
2339 }
2340 
2341 static void
deactivate(LV2_Handle instance)2342 deactivate(LV2_Handle instance)
2343 {
2344   LV2Plugin* plugin = (LV2Plugin*)instance;
2345   plugin->suspend();
2346 }
2347 
2348 const void*
extension_data(const char * uri)2349 extension_data(const char* uri)
2350 {
2351   return NULL;
2352 }
2353 
2354 static const LV2_Descriptor descriptor = {
2355   PLUGIN_URI,
2356   instantiate,
2357   connect_port,
2358   activate,
2359   run,
2360   deactivate,
2361   cleanup,
2362   extension_data
2363 };
2364 
2365 extern "C"
2366 LV2_SYMBOL_EXPORT
2367 const LV2_Descriptor*
lv2_descriptor(uint32_t index)2368 lv2_descriptor(uint32_t index)
2369 {
2370   switch (index) {
2371   case 0:
2372     return &descriptor;
2373   default:
2374     return NULL;
2375   }
2376 }
2377 
2378 //----------------------------------------------------------------------------
2379 //  Dynamic manifest
2380 //----------------------------------------------------------------------------
2381 
2382 // NOTE: If your LV2 host doesn't offer this extension then you'll have to
2383 // create a static ttl file with the descriptions of the ports. You can do
2384 // this by compiling this code to a standalone executable. Running the
2385 // executable then prints the manifest on stdout.
2386 
2387 extern "C"
2388 LV2_SYMBOL_EXPORT
lv2_dyn_manifest_open(LV2_Dyn_Manifest_Handle * handle,const LV2_Feature * const * features)2389 int lv2_dyn_manifest_open(LV2_Dyn_Manifest_Handle *handle,
2390 			  const LV2_Feature *const *features)
2391 {
2392   LV2Plugin* plugin =
2393     new LV2Plugin(LV2Plugin::numVoices(), 48000);
2394   *handle = (LV2_Dyn_Manifest_Handle)plugin;
2395   return 0;
2396 }
2397 
2398 extern "C"
2399 LV2_SYMBOL_EXPORT
lv2_dyn_manifest_get_subjects(LV2_Dyn_Manifest_Handle handle,FILE * fp)2400 int lv2_dyn_manifest_get_subjects(LV2_Dyn_Manifest_Handle handle,
2401 				  FILE *fp)
2402 {
2403   fprintf(fp, "@prefix lv2:  <http://lv2plug.in/ns/lv2core#> .\n\
2404 <%s> a lv2:Plugin .\n", PLUGIN_URI);
2405   return 0;
2406 }
2407 
2408 #include <string>
2409 #include <ctype.h>
2410 
mangle(const string & s)2411 static string mangle(const string &s)
2412 {
2413   string t = s;
2414   size_t n = s.size();
2415   for (size_t i = 0; i < n; i++)
2416     if ((i == 0 && !isalpha(t[i]) && t[i] != '_') ||
2417 	(!isalnum(t[i]) && t[i] != '_'))
2418       t[i] = '_';
2419   return t;
2420 }
2421 
steps(float min,float max,float step)2422 static unsigned steps(float min, float max, float step)
2423 {
2424   if (step == 0.0) return 1;
2425   int n = (max-min)/step;
2426   if (n < 0) n = -n;
2427   if (n == 0) n = 1;
2428   return n;
2429 }
2430 
2431 #if FAUST_META
is_xmlstring(const char * s)2432 static bool is_xmlstring(const char *s)
2433 {
2434   // This is just a basic sanity check. The string must not contain any
2435   // (unescaped) newlines, carriage returns or double quotes.
2436   return !strchr(s, '\n') && !strchr(s, '\r') && !strchr(s, '"');
2437 }
2438 #endif
2439 
2440 extern "C"
2441 LV2_SYMBOL_EXPORT
lv2_dyn_manifest_get_data(LV2_Dyn_Manifest_Handle handle,FILE * fp,const char * uri)2442 int lv2_dyn_manifest_get_data(LV2_Dyn_Manifest_Handle handle,
2443 			      FILE *fp,
2444 			      const char *uri)
2445 {
2446   LV2Plugin* plugin = (LV2Plugin*)handle;
2447   int k = plugin->ui[0]->nports;
2448   int n = plugin->dsp[0]->getNumInputs(), m = plugin->dsp[0]->getNumOutputs();
2449   bool is_instr = plugin->maxvoices > 0, have_midi = is_instr;
2450   // Scan the global metadata for plugin name, description, license etc.
2451   const char *plugin_name = NULL, *plugin_author = NULL, *plugin_descr = NULL,
2452     *plugin_version = NULL, *plugin_license = NULL;
2453 #if FAUST_META
2454   plugin_name = plugin->pluginName();
2455   plugin_descr = plugin->pluginDescription();
2456   plugin_author = plugin->pluginAuthor();
2457   plugin_version = plugin->pluginVersion();
2458   plugin_license = plugin->pluginLicense();
2459 #endif
2460   if (!plugin_name || !*plugin_name) plugin_name = "harm_trem";
2461   fprintf(fp, "@prefix doap:  <http://usefulinc.com/ns/doap#> .\n\
2462 @prefix foaf:  <http://xmlns.com/foaf/0.1/> .\n\
2463 @prefix lv2:   <http://lv2plug.in/ns/lv2core#> .\n\
2464 @prefix ui:    <http://lv2plug.in/ns/extensions/ui#> .\n\
2465 @prefix epp:   <http://lv2plug.in/ns/ext/port-props#> .\n\
2466 @prefix atom:  <http://lv2plug.in/ns/ext/atom#> .\n\
2467 @prefix rdf:   <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n\
2468 @prefix rdfs:  <http://www.w3.org/2000/01/rdf-schema#> .\n\
2469 @prefix units: <http://lv2plug.in/ns/extensions/units#> .\n\
2470 <%s>\n\
2471        a lv2:Plugin%s ;\n\
2472        doap:name \"%s\" ;\n\
2473        lv2:binary <harm_trem%s> ;\n\
2474        lv2:optionalFeature epp:supportsStrictBounds ;\n\
2475        lv2:optionalFeature lv2:hardRtCapable ;\n", PLUGIN_URI,
2476 	  is_instr?", lv2:InstrumentPlugin":"",
2477 	  plugin_name, DLLEXT);
2478   if (plugin_author && *plugin_author)
2479     fprintf(fp, "\
2480        doap:maintainer [ foaf:name \"%s\" ] ;\n", plugin_author);
2481   // doap:description just seems to be ignored by all LV2 hosts anyway, so we
2482   // rather use rdfs:comment now which works with Ardour at least.
2483   if (plugin_descr && *plugin_descr)
2484     fprintf(fp, "\
2485        rdfs:comment \"%s\" ;\n", plugin_descr);
2486   if (plugin_version && *plugin_version)
2487     fprintf(fp, "\
2488        doap:revision \"%s\" ;\n", plugin_version);
2489   if (plugin_license && *plugin_license)
2490     fprintf(fp, "\
2491        doap:license \"%s\" ;\n", plugin_license);
2492 #if FAUST_UI
2493     fprintf(fp, "\
2494        ui:ui <%sui> ;\n", PLUGIN_URI);
2495 #endif
2496   int idx = 0;
2497   // control ports
2498   for (int i = 0; i < k; i++, idx++) {
2499     int j = plugin->ctrls[i];
2500     assert(idx == plugin->ui[0]->elems[j].port);
2501     fprintf(fp, "%s [\n", idx==0?"    lv2:port":" ,");
2502     const char *label = plugin->ui[0]->elems[j].label;
2503     assert(label);
2504     string sym = mangle(plugin->ui[0]->elems[j].label);
2505     switch (plugin->ui[0]->elems[j].type) {
2506     // active controls (input ports)
2507     case UI_BUTTON: case UI_CHECK_BUTTON:
2508     fprintf(fp, "\
2509 	a lv2:InputPort ;\n\
2510 	a lv2:ControlPort ;\n\
2511 	lv2:index %d ;\n\
2512 	lv2:symbol \"%s_%d\" ;\n\
2513 	lv2:name \"%s\" ;\n\
2514         lv2:portProperty epp:hasStrictBounds ;\n\
2515         lv2:portProperty lv2:toggled ;\n\
2516 	lv2:default 0.00000 ;\n\
2517 	lv2:minimum 0.00000 ;\n\
2518 	lv2:maximum 1.00000 ;\n", idx, sym.c_str(), idx, label);
2519       break;
2520     case UI_NUM_ENTRY: case UI_H_SLIDER: case UI_V_SLIDER:
2521     fprintf(fp, "\
2522 	a lv2:InputPort ;\n\
2523 	a lv2:ControlPort ;\n\
2524 	lv2:index %d ;\n\
2525 	lv2:symbol \"%s_%d\" ;\n\
2526 	lv2:name \"%s\" ;\n\
2527         lv2:portProperty epp:hasStrictBounds ;\n\
2528         epp:rangeSteps %u ;\n\
2529 	lv2:default %g ;\n\
2530 	lv2:minimum %g ;\n\
2531 	lv2:maximum %g ;\n", idx, sym.c_str(), idx, label,
2532 	    steps(plugin->ui[0]->elems[j].min,
2533 		  plugin->ui[0]->elems[j].max,
2534 		  plugin->ui[0]->elems[j].step),
2535 	    plugin->ui[0]->elems[j].init,
2536 	    plugin->ui[0]->elems[j].min,
2537 	    plugin->ui[0]->elems[j].max);
2538       break;
2539     // passive controls (output ports)
2540     case UI_H_BARGRAPH: case UI_V_BARGRAPH:
2541     fprintf(fp, "\
2542 	a lv2:OutputPort ;\n\
2543 	a lv2:ControlPort ;\n\
2544 	lv2:index %d ;\n\
2545 	lv2:symbol \"%s_%d\" ;\n\
2546 	lv2:name \"%s\" ;\n\
2547 	lv2:default %g ;\n\
2548 	lv2:minimum %g ;\n\
2549 	lv2:maximum %g ;\n", idx, sym.c_str(), idx, label,
2550 	    plugin->ui[0]->elems[j].min,
2551 	    plugin->ui[0]->elems[j].min,
2552 	    plugin->ui[0]->elems[j].max);
2553       break;
2554     default:
2555       assert(0 && "this can't happen");
2556       break;
2557     }
2558     // Scan for Faust control metadata we understand and add corresponding
2559     // hints to the LV2 description of the port.
2560     std::map< int, list<strpair> >::iterator it =
2561       plugin->ui[0]->metadata.find(j);
2562     if (it != plugin->ui[0]->metadata.end()) {
2563       for (std::list<strpair>::iterator jt = it->second.begin();
2564 	   jt != it->second.end(); jt++) {
2565 	const char *key = jt->first, *val = jt->second;
2566 #if FAUST_MIDICC
2567 	unsigned num;
2568 	if (!strcmp(key, "midi") && sscanf(val, "ctrl %u", &num) == 1)
2569 	  have_midi = true;
2570 #endif
2571 	if (!strcmp(key, "unit"))
2572 	  fprintf(fp, "\
2573 	units:unit [\n\
2574             a            units:Unit ;\n\
2575             units:name   \"%s\" ;\n\
2576             units:symbol \"%s\" ;\n\
2577             units:render \"%%f %s\"\n\
2578 	] ;\n", val, val, val);
2579 	if (strcmp(key, "lv2")) continue;
2580 	if (!strcmp(val, "integer"))
2581 	  fprintf(fp, "\
2582 	lv2:portProperty lv2:integer ;\n");
2583 	else if (!strcmp(val, "reportsLatency"))
2584 	  fprintf(fp, "\
2585 	lv2:portProperty lv2:reportsLatency ;\n\
2586 	lv2:designation lv2:latency ;\n");
2587 	else if (!strcmp(val, "hidden") || !strcmp(val, "notOnGUI"))
2588 	  fprintf(fp, "\
2589 	lv2:portProperty epp:notOnGUI ;\n");
2590 	else if (!strncmp(val, "scalepoint", 10) ||
2591 		 !strncmp(val, "scalePoint", 10)) {
2592 	  val += 10;
2593 	  if (!isspace(*val)) continue;
2594 	  char *label = (char*)malloc(strlen(val)+1);
2595 	  float point;
2596 	  int pos;
2597 	  while (sscanf(val, "%s %g%n", label, &point, &pos) == 2) {
2598 	    fprintf(fp, "\
2599 	lv2:scalePoint [ rdfs:label \"%s\"; rdf:value %g ] ;\n",
2600 		    label, point);
2601 	    val += pos;
2602 	  }
2603 	  free(label);
2604 	} else
2605 	  fprintf(stderr, "%s: bad port property '%s:%s'\n", PLUGIN_URI,
2606 		  key, val);
2607       }
2608     }
2609     fprintf(fp, "    ]");
2610   }
2611   // audio inputs
2612   for (int i = 0; i < n; i++, idx++)
2613     fprintf(fp, "%s [\n\
2614 	a lv2:InputPort ;\n\
2615 	a lv2:AudioPort ;\n\
2616 	lv2:index %d ;\n\
2617 	lv2:symbol \"in%d\" ;\n\
2618 	lv2:name \"in%d\" ;\n\
2619     ]", idx==0?"    lv2:port":" ,", idx, i, i);
2620   // audio outputs
2621   for (int i = 0; i < m; i++, idx++)
2622     fprintf(fp, "%s [\n\
2623 	a lv2:OutputPort ;\n\
2624 	a lv2:AudioPort ;\n\
2625 	lv2:index %d ;\n\
2626 	lv2:symbol \"out%d\" ;\n\
2627 	lv2:name \"out%d\" ;\n\
2628     ]", idx==0?"    lv2:port":" ,", idx, i, i);
2629   if (have_midi) {
2630     // midi input
2631     fprintf(fp, "%s [\n\
2632 	a lv2:InputPort ;\n\
2633 	a atom:AtomPort ;\n\
2634 	atom:bufferType atom:Sequence ;\n\
2635 	atom:supports <http://lv2plug.in/ns/ext/midi#MidiEvent> ;\n\
2636 	lv2:index %d ;\n\
2637 	lv2:symbol \"midiin\" ;\n\
2638 	lv2:name \"midiin\"\n\
2639     ]", idx==0?"    lv2:port":" ,", idx);
2640     idx++;
2641   }
2642   if (is_instr) {
2643     // polyphony control
2644     fprintf(fp, "%s [\n\
2645 	a lv2:InputPort ;\n\
2646 	a lv2:ControlPort ;\n\
2647 	lv2:index %d ;\n\
2648 	lv2:symbol \"polyphony\" ;\n\
2649 	lv2:name \"polyphony\" ;\n\
2650         lv2:portProperty epp:hasStrictBounds ;\n\
2651 #       lv2:portProperty epp:expensive ;\n\
2652         lv2:portProperty lv2:integer ;\n\
2653         epp:rangeSteps %d ;\n\
2654 	lv2:default %d ;\n\
2655 	lv2:minimum 1 ;\n\
2656 	lv2:maximum %d ;\n\
2657     ]", idx==0?"    lv2:port":" ,", idx, plugin->maxvoices-1,
2658       plugin->maxvoices>1?plugin->maxvoices/2:1,
2659       plugin->maxvoices);
2660     idx++;
2661 #if FAUST_MTS
2662     if (plugin->n_tunings > 0) {
2663       // tuning control
2664       fprintf(fp, "%s [\n\
2665 	a lv2:InputPort ;\n\
2666 	a lv2:ControlPort ;\n\
2667 	lv2:index %d ;\n\
2668 	lv2:symbol \"tuning\" ;\n\
2669 	lv2:name \"tuning\" ;\n\
2670         lv2:portProperty epp:hasStrictBounds ;\n\
2671         lv2:portProperty lv2:integer ;\n\
2672         epp:rangeSteps %d ;\n\
2673 	lv2:default 0 ;\n\
2674 	lv2:minimum 0 ;\n\
2675 	lv2:maximum %d ;\n",
2676 	idx==0?"    lv2:port":" ,", idx, plugin->n_tunings, plugin->n_tunings);
2677       for (int i = 0; i <= plugin->n_tunings; i++)
2678 	fprintf(fp, "\
2679 	lv2:scalePoint [ rdfs:label \"%s\"; rdf:value %d ] ;\n",
2680 		(i>0)?plugin->mts->tuning[i-1].name:"default", i);
2681       fprintf(fp, "    ]");
2682       idx++;
2683     }
2684 #endif
2685   }
2686   fprintf(fp, "\n.\n");
2687   return 0;
2688 }
2689 
2690 extern "C"
2691 LV2_SYMBOL_EXPORT
lv2_dyn_manifest_close(LV2_Dyn_Manifest_Handle handle)2692 void lv2_dyn_manifest_close(LV2_Dyn_Manifest_Handle handle)
2693 {
2694   LV2Plugin* plugin = (LV2Plugin*)handle;
2695   delete plugin;
2696 }
2697 
main()2698 int main()
2699 {
2700   LV2_Dyn_Manifest_Handle handle;
2701   LV2_Feature **features = { NULL };
2702   int res = lv2_dyn_manifest_open(&handle, features);
2703   if (res) return res;
2704   res = lv2_dyn_manifest_get_data(handle, stdout, PLUGIN_URI);
2705   return res;
2706 }
2707 
2708 #endif
2709