1 /* ------------------------------------------------------------
2 name: "harm_trem_ext"
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_ext_H__
8 #define  __harm_trem_ext_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 
harm_trem_ext_faustpower2_f(float value)605 static float harm_trem_ext_faustpower2_f(float value) {
606 	return (value * value);
607 }
608 
609 #ifndef FAUSTCLASS
610 #define FAUSTCLASS harm_trem_ext
611 #endif
612 
613 #ifdef __APPLE__
614 #define exp10f __exp10f
615 #define exp10 __exp10
616 #endif
617 
618 class harm_trem_ext : public dsp {
619 
620  private:
621 
622 	float fVec0[2];
623 	int fSampleRate;
624 	float fConst0;
625 	FAUSTFLOAT fVslider0;
626 	float fRec2[2];
627 	float fRec1[2];
628 	float fRec0[3];
629 	FAUSTFLOAT fHslider0;
630 	float fRec3[2];
631 	float fRec5[2];
632 	float fRec4[3];
633 
634  public:
635 
metadata(Meta * m)636 	void metadata(Meta* m) {
637 		m->declare("analyzers.lib/name", "Faust Analyzer Library");
638 		m->declare("analyzers.lib/version", "0.0");
639 		m->declare("basics.lib/name", "Faust Basic Element Library");
640 		m->declare("basics.lib/version", "0.1");
641 		m->declare("filename", "harm_trem_ext.dsp");
642 		m->declare("filters.lib/filterbank:author", "Julius O. Smith III");
643 		m->declare("filters.lib/filterbank:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
644 		m->declare("filters.lib/filterbank:license", "MIT-style STK-4.3 license");
645 		m->declare("filters.lib/fir:author", "Julius O. Smith III");
646 		m->declare("filters.lib/fir:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
647 		m->declare("filters.lib/fir:license", "MIT-style STK-4.3 license");
648 		m->declare("filters.lib/highpass:author", "Julius O. Smith III");
649 		m->declare("filters.lib/highpass:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
650 		m->declare("filters.lib/iir:author", "Julius O. Smith III");
651 		m->declare("filters.lib/iir:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
652 		m->declare("filters.lib/iir:license", "MIT-style STK-4.3 license");
653 		m->declare("filters.lib/lowpass0_highpass1", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
654 		m->declare("filters.lib/lowpass0_highpass1:author", "Julius O. Smith III");
655 		m->declare("filters.lib/lowpass:author", "Julius O. Smith III");
656 		m->declare("filters.lib/lowpass:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
657 		m->declare("filters.lib/lowpass:license", "MIT-style STK-4.3 license");
658 		m->declare("filters.lib/name", "Faust Filters Library");
659 		m->declare("filters.lib/tf1:author", "Julius O. Smith III");
660 		m->declare("filters.lib/tf1:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
661 		m->declare("filters.lib/tf1:license", "MIT-style STK-4.3 license");
662 		m->declare("filters.lib/tf1s:author", "Julius O. Smith III");
663 		m->declare("filters.lib/tf1s:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
664 		m->declare("filters.lib/tf1s:license", "MIT-style STK-4.3 license");
665 		m->declare("filters.lib/tf2:author", "Julius O. Smith III");
666 		m->declare("filters.lib/tf2:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
667 		m->declare("filters.lib/tf2:license", "MIT-style STK-4.3 license");
668 		m->declare("filters.lib/tf2s:author", "Julius O. Smith III");
669 		m->declare("filters.lib/tf2s:copyright", "Copyright (C) 2003-2019 by Julius O. Smith III <jos@ccrma.stanford.edu>");
670 		m->declare("filters.lib/tf2s:license", "MIT-style STK-4.3 license");
671 		m->declare("maths.lib/author", "GRAME");
672 		m->declare("maths.lib/copyright", "GRAME");
673 		m->declare("maths.lib/license", "LGPL with exception");
674 		m->declare("maths.lib/name", "Faust Math Library");
675 		m->declare("maths.lib/version", "2.1");
676 		m->declare("name", "harm_trem_ext");
677 		m->declare("signals.lib/name", "Faust Signal Routing Library");
678 		m->declare("signals.lib/version", "0.0");
679 	}
680 
getNumInputs()681 	virtual int getNumInputs() {
682 		return 2;
683 	}
getNumOutputs()684 	virtual int getNumOutputs() {
685 		return 1;
686 	}
getInputRate(int channel)687 	virtual int getInputRate(int channel) {
688 		int rate;
689 		switch ((channel)) {
690 			case 0: {
691 				rate = 1;
692 				break;
693 			}
694 			case 1: {
695 				rate = 1;
696 				break;
697 			}
698 			default: {
699 				rate = -1;
700 				break;
701 			}
702 		}
703 		return rate;
704 	}
getOutputRate(int channel)705 	virtual int getOutputRate(int channel) {
706 		int rate;
707 		switch ((channel)) {
708 			case 0: {
709 				rate = 1;
710 				break;
711 			}
712 			default: {
713 				rate = -1;
714 				break;
715 			}
716 		}
717 		return rate;
718 	}
719 
classInit(int sample_rate)720 	static void classInit(int sample_rate) {
721 	}
722 
instanceConstants(int sample_rate)723 	virtual void instanceConstants(int sample_rate) {
724 		fSampleRate = sample_rate;
725 		fConst0 = (3.14159274f / std::min<float>(192000.0f, std::max<float>(1.0f, float(fSampleRate))));
726 	}
727 
instanceResetUserInterface()728 	virtual void instanceResetUserInterface() {
729 		fVslider0 = FAUSTFLOAT(800.0f);
730 		fHslider0 = FAUSTFLOAT(0.0f);
731 	}
732 
instanceClear()733 	virtual void instanceClear() {
734 		for (int l0 = 0; (l0 < 2); l0 = (l0 + 1)) {
735 			fVec0[l0] = 0.0f;
736 		}
737 		for (int l1 = 0; (l1 < 2); l1 = (l1 + 1)) {
738 			fRec2[l1] = 0.0f;
739 		}
740 		for (int l2 = 0; (l2 < 2); l2 = (l2 + 1)) {
741 			fRec1[l2] = 0.0f;
742 		}
743 		for (int l3 = 0; (l3 < 3); l3 = (l3 + 1)) {
744 			fRec0[l3] = 0.0f;
745 		}
746 		for (int l4 = 0; (l4 < 2); l4 = (l4 + 1)) {
747 			fRec3[l4] = 0.0f;
748 		}
749 		for (int l5 = 0; (l5 < 2); l5 = (l5 + 1)) {
750 			fRec5[l5] = 0.0f;
751 		}
752 		for (int l6 = 0; (l6 < 3); l6 = (l6 + 1)) {
753 			fRec4[l6] = 0.0f;
754 		}
755 	}
756 
init(int sample_rate)757 	virtual void init(int sample_rate) {
758 		classInit(sample_rate);
759 		instanceInit(sample_rate);
760 	}
instanceInit(int sample_rate)761 	virtual void instanceInit(int sample_rate) {
762 		instanceConstants(sample_rate);
763 		instanceResetUserInterface();
764 		instanceClear();
765 	}
766 
clone()767 	virtual harm_trem_ext* clone() {
768 		return new harm_trem_ext();
769 	}
770 
getSampleRate()771 	virtual int getSampleRate() {
772 		return fSampleRate;
773 	}
774 
buildUserInterface(UI * ui_interface)775 	virtual void buildUserInterface(UI* ui_interface) {
776 		ui_interface->openVerticalBox("harm_trem_ext");
777 		ui_interface->declare(&fVslider0, "1", "");
778 		ui_interface->declare(&fVslider0, "midi", "ctrl 64");
779 		ui_interface->declare(&fVslider0, "style", "knob");
780 		ui_interface->addVerticalSlider("CrossoverFreq", &fVslider0, 800.0f, 20.0f, 10000.0f, 1.0f);
781 		ui_interface->declare(&fHslider0, "2", "");
782 		ui_interface->addHorizontalSlider("depth", &fHslider0, 0.0f, 0.0f, 1.0f, 0.00999999978f);
783 		ui_interface->closeBox();
784 	}
785 
compute(int count,FAUSTFLOAT ** inputs,FAUSTFLOAT ** outputs)786 	virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) {
787 		FAUSTFLOAT* input0 = inputs[0];
788 		FAUSTFLOAT* input1 = inputs[1];
789 		FAUSTFLOAT* output0 = outputs[0];
790 		float fSlow0 = (0.00100000005f * float(fVslider0));
791 		float fSlow1 = (0.00100000005f * float(fHslider0));
792 		for (int i = 0; (i < count); i = (i + 1)) {
793 			float fTemp0 = float(input0[i]);
794 			fVec0[0] = fTemp0;
795 			fRec2[0] = (fSlow0 + (0.999000013f * fRec2[1]));
796 			float fTemp1 = std::tan((fConst0 * fRec2[0]));
797 			float fTemp2 = (1.0f / fTemp1);
798 			float fTemp3 = (fTemp2 + 1.0f);
799 			float fTemp4 = (1.0f - fTemp2);
800 			fRec1[0] = ((fVec0[1] * (0.0f - (1.0f / (fTemp1 * fTemp3)))) - (((fRec1[1] * fTemp4) - (fTemp0 / fTemp1)) / fTemp3));
801 			float fTemp5 = (((fTemp2 + -1.0f) / fTemp1) + 1.0f);
802 			float fTemp6 = harm_trem_ext_faustpower2_f(fTemp1);
803 			float fTemp7 = (1.0f - (1.0f / fTemp6));
804 			float fTemp8 = (((fTemp2 + 1.0f) / fTemp1) + 1.0f);
805 			fRec0[0] = (fRec1[0] - (((fRec0[2] * fTemp5) + (2.0f * (fRec0[1] * fTemp7))) / fTemp8));
806 			fRec3[0] = (fSlow1 + (0.999000013f * fRec3[1]));
807 			float fTemp9 = float(input1[i]);
808 			fRec5[0] = (0.0f - (((fTemp4 * fRec5[1]) - (fTemp0 + fVec0[1])) / fTemp3));
809 			fRec4[0] = (fRec5[0] - (((fTemp5 * fRec4[2]) + (2.0f * (fTemp7 * fRec4[1]))) / fTemp8));
810 			output0[i] = FAUSTFLOAT(((((((fRec0[1] * (0.0f - (2.0f / fTemp6))) + (fRec0[0] / fTemp6)) + (fRec0[2] / fTemp6)) * (1.0f - (0.5f * (fRec3[0] * (fTemp9 + 1.0f))))) + ((fRec4[2] + (fRec4[0] + (2.0f * fRec4[1]))) * (1.0f - (0.5f * (fRec3[0] * ((1.0f - fTemp9) + 1.0f)))))) / fTemp8));
811 			fVec0[1] = fVec0[0];
812 			fRec2[1] = fRec2[0];
813 			fRec1[1] = fRec1[0];
814 			fRec0[2] = fRec0[1];
815 			fRec0[1] = fRec0[0];
816 			fRec3[1] = fRec3[0];
817 			fRec5[1] = fRec5[0];
818 			fRec4[2] = fRec4[1];
819 			fRec4[1] = fRec4[0];
820 		}
821 	}
822 
823 };
824 
825 //----------------------------------------------------------------------------
826 //  LV2 interface
827 //----------------------------------------------------------------------------
828 
829 #line 286 "lv2.cpp"
830 
831 #include <assert.h>
832 #include <stdio.h>
833 #include <stdlib.h>
834 
835 #include <bitset>
836 #include <boost/circular_buffer.hpp>
837 
838 #include <lv2/lv2plug.in/ns/lv2core/lv2.h>
839 #include <lv2/lv2plug.in/ns/ext/dynmanifest/dynmanifest.h>
840 #include <lv2/lv2plug.in/ns/ext/atom/util.h>
841 #include <lv2/lv2plug.in/ns/ext/urid/urid.h>
842 
843 // Set this to the proper shared library extension for your system
844 #ifndef DLLEXT
845 #define DLLEXT ".so"
846 #endif
847 
848 #ifndef URI_PREFIX
849 #define URI_PREFIX "https://faustlv2.bitbucket.io"
850 #endif
851 
852 #ifndef PLUGIN_URI
853 #define PLUGIN_URI URI_PREFIX "/harm_trem_ext"
854 #endif
855 
856 #define MIDI_EVENT_URI "http://lv2plug.in/ns/ext/midi#MidiEvent"
857 
858 /* Setting NVOICES at compile time overrides meta data in the Faust source. If
859    set, this must be an integer value >= 0. A nonzero value indicates an
860    instrument (VSTi) plugin with the given maximum number of voices. Use 1 for
861    a monophonic synthesizer, and 0 for a simple effect plugin. If NVOICES
862    isn't defined at compile time then the number of voices of an instrument
863    plugin can also be set with the global "nvoices" meta data key in the Faust
864    source. This setting also adds a special "polyphony" control to the plugin
865    which can be used to dynamically adjust the actual number of voices in the
866    range 1..NVOICES. */
867 //#define NVOICES 16
868 
869 /* This enables a special "tuning" control for instruments which lets you
870    select the MTS tuning to be used for the synth. In order to use this, you
871    just drop some sysex (.syx) files with MTS octave-based tunings in 1- or
872    2-byte format into the ~/.fautvst/tuning directory (these can be generated
873    with the author's sclsyx program, https://bitbucket.org/agraef/sclsyx).
874    The control will only be shown if any .syx files were found at startup. 0
875    selects the default tuning (standard 12-tone equal temperament), i>0 the
876    tuning in the ith sysex file (in alphabetic order). */
877 #ifndef FAUST_MTS
878 #define FAUST_MTS 1
879 #endif
880 
881 /* This allows various manifest data to be generated from the corresponding
882    metadata (author, name, description, license) in the Faust source. */
883 #ifndef FAUST_META
884 #define FAUST_META 1
885 #endif
886 
887 /* This enables automatic MIDI controller mapping based on the midi:ctrl
888    attributes in the Faust source. We have this enabled by default, but you
889    may have to disable it if the custom controller mapping gets in the way of
890    the automation facilities that the host provides. (But then again if the
891    host wants to do its own controller mapping then it probably won't, or at
892    least shouldn't, send us the MIDI controllers in the first place.) */
893 #ifndef FAUST_MIDICC
894 #define FAUST_MIDICC 1
895 #endif
896 
897 /* This enables or disables the plugin's custom Qt GUI (cf. lv2ui.cpp). Note
898    that this only affects the plugin manifest, the GUI code itself is in a
899    separate module created with the lv2ui.cpp architecture. Also, you'll have
900    to use the alternative lv2ui manifest templates to tell the LV2 host about
901    the GUI. */
902 #ifndef FAUST_UI
903 #define FAUST_UI 0
904 #endif
905 
906 // You can define these for various debugging output items.
907 //#define DEBUG_META 1 // recognized MIDI controller metadata
908 //#define DEBUG_VOICES 1 // triggering of synth voices
909 //#define DEBUG_VOICE_ALLOC 1 // voice allocation
910 //#define DEBUG_MIDI 1 // incoming MIDI messages
911 //#define DEBUG_NOTES 1 // note messages
912 //#define DEBUG_MIDICC 1 // controller messages
913 //#define DEBUG_RPN 1 // RPN messages (pitch bend range, master tuning)
914 //#define DEBUG_MTS 1 // MTS messages (octave/scale tuning)
915 
916 // Note and voice data structures.
917 
918 struct NoteInfo {
919   uint8_t ch;
920   int8_t note;
921 };
922 
923 struct VoiceData {
924   // Octave tunings (offsets in semitones) per MIDI channel.
925   float tuning[16][12];
926   // Allocated voices per MIDI channel and note.
927   int8_t notes[16][128];
928   // Free and used voices.
929   int n_free, n_used;
930   boost::circular_buffer<int> free_voices;
931   boost::circular_buffer<int> used_voices;
932   NoteInfo *note_info;
933   // Voices queued for note-offs (zero-length notes).
934   set<int> queued;
935   // Last gate value during run() for each voice. We need to keep track of
936   // these so that we can force the Faust synth to retrigger a note when
937   // needed.
938   float *lastgate;
939   // Current pitch bend and pitch bend range on each MIDI channel, in semitones.
940   float bend[16], range[16];
941   // Current coarse, fine and total master tuning on each MIDI channel (tuning
942   // offset relative to A4 = 440 Hz, in semitones).
943   float coarse[16], fine[16], tune[16];
VoiceDataVoiceData944   VoiceData(int n) : free_voices(n), used_voices(n) { }
945 };
946 
947 #if FAUST_MTS
948 
949 // Helper classes to read and store MTS tunings.
950 
951 #include <sys/types.h>
952 #include <sys/stat.h>
953 #include <dirent.h>
954 
955 #include <string>
956 #include <vector>
957 
958 struct MTSTuning {
959   char *name; // name of the tuning
960   int len; // length of sysex data in bytes
961   unsigned char *data; // sysex data
MTSTuningMTSTuning962   MTSTuning() : name(0), len(0), data(0) {}
operator =MTSTuning963   MTSTuning& operator=(const MTSTuning &t)
964   {
965     if (this == &t) return *this;
966     if (name) free(name); if (data) free(data);
967     name = 0; data = 0; len = t.len;
968     if (t.name) {
969       name = strdup(t.name); assert(name);
970     }
971     if (t.data) {
972       data = (unsigned char*)malloc(len); assert(data);
973       memcpy(data, t.data, len);
974     }
975     return *this;
976   }
MTSTuningMTSTuning977   MTSTuning(const MTSTuning& t) : name(0), len(0), data(0)
978   { *this = t; }
979   MTSTuning(const char *filename);
~MTSTuningMTSTuning980   ~MTSTuning()
981   { if (name) free(name); if (data) free(data); }
982 };
983 
MTSTuning(const char * filename)984 MTSTuning::MTSTuning(const char *filename)
985 {
986   FILE *fp = fopen(filename, "rb");
987   name = 0; len = 0; data = 0;
988   if (!fp) return;
989   struct stat st;
990   if (fstat(fileno(fp), &st)) return;
991   len = st.st_size;
992   data = (unsigned char*)calloc(len, 1);
993   if (!data) {
994     len = 0; fclose(fp);
995     return;
996   }
997   assert(len > 0);
998   if (fread(data, 1, len, fp) < len) {
999     free(data); len = 0; data = 0; fclose(fp);
1000     return;
1001   }
1002   fclose(fp);
1003   // Do some basic sanity checks.
1004   if (data[0] != 0xf0 || data[len-1] != 0xf7 || // not a sysex message
1005       (data[1] != 0x7e && data[1] != 0x7f) || data[3] != 8 || // not MTS
1006       !((len == 21 && data[4] == 8) ||
1007 	(len == 33 && data[4] == 9))) { // no 1- or 2-byte tuning
1008     free(data); len = 0; data = 0;
1009     return;
1010   }
1011   // Name of the tuning is the basename of the file, without the trailing .syx
1012   // suffix.
1013   string nm = filename;
1014   size_t p = nm.rfind(".syx");
1015   if (p != string::npos) nm.erase(p);
1016   p = nm.rfind('/');
1017   if (p != string::npos) nm.erase(0, p+1);
1018   name = strdup(nm.c_str());
1019   assert(name);
1020 }
1021 
1022 struct MTSTunings {
1023   vector<MTSTuning> tuning;
MTSTuningsMTSTunings1024   MTSTunings() {}
1025   MTSTunings(const char *path);
1026 };
1027 
compareByName(const MTSTuning & a,const MTSTuning & b)1028 static bool compareByName(const MTSTuning &a, const MTSTuning &b)
1029 {
1030   return strcmp(a.name, b.name) < 0;
1031 }
1032 
MTSTunings(const char * path)1033 MTSTunings::MTSTunings(const char *path)
1034 {
1035   DIR *dp = opendir(path);
1036   if (!dp) return;
1037   struct dirent *d;
1038   while ((d = readdir(dp))) {
1039     string nm = d->d_name;
1040     if (nm.length() > 4 && nm.substr(nm.length()-4) == ".syx") {
1041       string pathname = path;
1042       pathname += "/";
1043       pathname += nm;
1044       MTSTuning t(pathname.c_str());
1045       if (t.data) tuning.push_back(t);
1046     }
1047   }
1048   closedir(dp);
1049   // sort found tunings by name
1050   sort(tuning.begin(), tuning.end(), compareByName);
1051 }
1052 
1053 #endif
1054 
1055 #if FAUST_MIDICC
ctrlval(const ui_elem_t & el,uint8_t v)1056 static float ctrlval(const ui_elem_t &el, uint8_t v)
1057 {
1058   // Translate the given MIDI controller value to the range and stepsize
1059   // indicated by the Faust control.
1060   switch (el.type) {
1061   case UI_BUTTON: case UI_CHECK_BUTTON:
1062     return (float)(v>=64);
1063   default:
1064     /* Continuous controllers. The problem here is that the range 0..127 is
1065        not symmetric. We'd like to map 64 to the center of the range
1066        (max-min)/2 and at the same time retain the full control range
1067        min..max. So let's just pretend that there are 128 controller values
1068        and map value 127 to the max value anyway. */
1069     if (v==127)
1070       return el.max;
1071     else
1072       // XXXFIXME: We might want to add proper quantization according to
1073       // el.step here.
1074       return el.min+(el.max-el.min)*v/128;
1075   }
1076 }
1077 #endif
1078 
1079 /***************************************************************************/
1080 
1081 /* Polyphonic Faust plugin data structure. XXXTODO: At present this is just a
1082    big struct which exposes all requisite data. Some more work is needed to
1083    make the interface a bit more abstract and properly encapsulate the
1084    internal data structures, so that implementation details can be changed
1085    more easily. */
1086 
1087 struct LV2Plugin {
1088   const int maxvoices;	// maximum number of voices (zero if not an instrument)
1089   const int ndsps;	// number of dsp instances (1 if maxvoices==0)
1090   bool active;		// activation status
1091   int rate;		// sampling rate
1092   int nvoices;		// current number of voices (<= maxvoices)
1093   int tuning_no;	// current tuning number (<= n_tunings)
1094   harm_trem_ext **dsp;		// the dsps
1095   LV2UI **ui;		// their Faust interface descriptions
1096   int n_in, n_out;	// number of input and output control ports
1097   int *ctrls;		// Faust ui elements (indices into ui->elems)
1098   float **ports;	// corresponding LV2 data
1099   float *portvals;	// cached port data from the last run
1100   float *midivals[16];	// per-midi channel data
1101   int *inctrls, *outctrls;	// indices for active and passive controls
1102   float **inputs, **outputs;	// audio buffers
1103   int freq, gain, gate;	// indices of voice controls
1104   unsigned n_samples;	// current block size
1105   float **outbuf;	// audio buffers for mixing down the voices
1106   float **inbuf;	// dummy input buffer
1107   LV2_Atom_Sequence* event_port; // midi input
1108   float *poly, *tuning;	// polyphony and tuning ports
1109   std::map<uint8_t,int> ctrlmap; // MIDI controller map
1110   // Needed host features.
1111   LV2_URID_Map* map;	// the urid extension
1112   LV2_URID midi_event;	// midi event uri
1113   // Current RPN MSB and LSB numbers, as set with controllers 101 and 100.
1114   uint8_t rpn_msb[16], rpn_lsb[16];
1115   // Current data entry MSB and LSB numbers, as set with controllers 6 and 38.
1116   uint8_t data_msb[16], data_lsb[16];
1117   // Synth voice data (instruments only).
1118   VoiceData *vd;
1119 
1120   // Static methods. These all use static data so they can be invoked before
1121   // instantiating a plugin.
1122 
1123   // Global meta data (dsp name, author, etc.).
1124   static Meta *meta;
init_metaLV2Plugin1125   static void init_meta()
1126   {
1127     if (!meta && (meta = new Meta)) {
1128       // We allocate the temporary dsp object on the heap here, to prevent
1129       // large dsp objects from running out of stack in environments where
1130       // stack space is precious (e.g., Reaper). Note that if any of these
1131       // allocations fail then no meta data will be available, but at least we
1132       // won't make the host crash and burn.
1133       harm_trem_ext* tmp_dsp = new harm_trem_ext();
1134       if (tmp_dsp) {
1135 	tmp_dsp->metadata(meta);
1136 	delete tmp_dsp;
1137       }
1138     }
1139   }
meta_getLV2Plugin1140   static const char *meta_get(const char *key, const char *deflt)
1141   {
1142     init_meta();
1143     return meta?meta->get(key, deflt):deflt;
1144   }
1145 
pluginNameLV2Plugin1146   static const char *pluginName()
1147   {
1148     return meta_get("name", "harm_trem_ext");
1149   }
1150 
pluginAuthorLV2Plugin1151   static const char *pluginAuthor()
1152   {
1153     return meta_get("author", "");
1154   }
1155 
pluginDescriptionLV2Plugin1156   static const char *pluginDescription()
1157   {
1158     return meta_get("description", "");
1159   }
1160 
pluginLicenseLV2Plugin1161   static const char *pluginLicense()
1162   {
1163     return meta_get("license", "");
1164   }
1165 
pluginVersionLV2Plugin1166   static const char *pluginVersion()
1167   {
1168     return meta_get("version", "");
1169   }
1170 
1171   // Load a collection of sysex files with MTS tunings in ~/.faust/tuning.
1172   static int n_tunings;
1173 #if FAUST_MTS
1174   static MTSTunings *mts;
1175 
load_sysex_dataLV2Plugin1176   static MTSTunings *load_sysex_data()
1177   {
1178     if (!mts) {
1179       string mts_path;
1180       // Look for FAUST_HOME. If that isn't set, try $HOME/.faust. If HOME
1181       // isn't set either, just assume a .faust subdir of the cwd.
1182       const char *home = getenv("FAUST_HOME");
1183       if (home)
1184 	mts_path = home;
1185       else {
1186 	home = getenv("HOME");
1187 	if (home) {
1188 	  mts_path = home;
1189 	  mts_path += "/.faust";
1190 	} else
1191 	  mts_path = ".faust";
1192       }
1193       // MTS tunings are looked for in this subdir.
1194       mts_path += "/tuning";
1195       mts = new MTSTunings(mts_path.c_str());
1196 #ifdef __APPLE__
1197       if (!mts || mts->tuning.size() == 0) {
1198 	// Also check ~/Library/Faust/Tuning on the Mac.
1199 	home = getenv("HOME");
1200 	if (home) {
1201 	  if (mts) delete mts;
1202 	  mts_path = home;
1203 	  mts_path += "/Library/Faust/Tuning";
1204 	  mts = new MTSTunings(mts_path.c_str());
1205 	}
1206       }
1207 #endif
1208       n_tunings = mts->tuning.size();
1209     }
1210     return mts;
1211   }
1212 #endif
1213 
1214   // The number of voices of an instrument plugin. We get this information
1215   // from the global meta data (nvoices key) of the dsp module if present, and
1216   // you can also override this setting at compile time by defining the
1217   // NVOICES macro. If neither is defined or the value is zero then the plugin
1218   // becomes a simple audio effect instead.
numVoicesLV2Plugin1219   static int numVoices()
1220   {
1221 #ifdef NVOICES
1222     return NVOICES;
1223 #else
1224     const char *numVoices = meta_get("nvoices", "0");
1225     int nvoices = atoi(numVoices);
1226     if (nvoices < 0 ) nvoices = 0;
1227     return nvoices;
1228 #endif
1229   }
1230 
1231   // Instance methods.
1232 
LV2PluginLV2Plugin1233   LV2Plugin(const int num_voices, const int sr)
1234     : maxvoices(num_voices), ndsps(num_voices<=0?1:num_voices),
1235       vd(num_voices>0?new VoiceData(num_voices):0)
1236   {
1237     // Initialize static data.
1238     init_meta();
1239 #if FAUST_MTS
1240     // Synth: load tuning sysex data if present.
1241     if (num_voices>0) load_sysex_data();
1242 #endif
1243     // Allocate data structures and set some reasonable defaults.
1244     dsp = (harm_trem_ext**)calloc(ndsps, sizeof(harm_trem_ext*));
1245     ui = (LV2UI**)calloc(ndsps, sizeof(LV2UI*));
1246     assert(dsp && ui);
1247     if (vd) {
1248       vd->note_info = (NoteInfo*)calloc(ndsps, sizeof(NoteInfo));
1249       vd->lastgate = (float*)calloc(ndsps, sizeof(float));
1250       assert(vd->note_info && vd->lastgate);
1251     }
1252     active = false;
1253     rate = sr;
1254     nvoices = maxvoices;
1255     tuning_no = 0;
1256     n_in = n_out = 0;
1257     map = NULL;
1258     midi_event = -1;
1259     event_port = NULL;
1260     poly = tuning = NULL;
1261     freq = gain = gate = -1;
1262     if (vd) {
1263       vd->n_free = maxvoices;
1264       for (int i = 0; i < maxvoices; i++) {
1265 	vd->free_voices.push_back(i);
1266 	vd->lastgate[i] = 0.0f;
1267       }
1268       for (int i = 0; i < 16; i++) {
1269 	vd->bend[i] = 0.0f;
1270 	vd->range[i] = 2.0f;
1271 	vd->coarse[i] = vd->fine[i] = vd->tune[i] = 0.0f;
1272 	for (int j = 0; j < 12; j++)
1273 	  vd->tuning[i][j] = 0.0f;
1274       }
1275       vd->n_used = 0;
1276       memset(vd->notes, 0xff, sizeof(vd->notes));
1277     }
1278     n_samples = 0;
1279     ctrls = inctrls = outctrls = NULL;
1280     ports = inputs = outputs = inbuf = outbuf = NULL;
1281     portvals = NULL;
1282     memset(midivals, 0, sizeof(midivals));
1283     // Initialize the Faust DSPs.
1284     for (int i = 0; i < ndsps; i++) {
1285       dsp[i] = new harm_trem_ext();
1286       ui[i] = new LV2UI(num_voices);
1287       dsp[i]->init(rate);
1288       dsp[i]->buildUserInterface(ui[i]);
1289     }
1290     // The ports are numbered as follows: 0..k-1 are the control ports, then
1291     // come the n audio input ports, then the m audio output ports, and
1292     // finally the midi input port and the polyphony and tuning controls.
1293     int k = ui[0]->nports, p = 0, q = 0;
1294     int n = dsp[0]->getNumInputs(), m = dsp[0]->getNumOutputs();
1295     // Allocate tables for the built-in control elements and their ports.
1296     ctrls = (int*)calloc(k, sizeof(int));
1297     inctrls = (int*)calloc(k, sizeof(int));
1298     outctrls = (int*)calloc(k, sizeof(int));
1299     ports = (float**)calloc(k, sizeof(float*));
1300     portvals = (float*)calloc(k, sizeof(float));
1301     assert(k == 0 || (ctrls && inctrls && outctrls && ports && portvals));
1302     for (int ch = 0; ch < 16; ch++) {
1303       midivals[ch] = (float*)calloc(k, sizeof(float));
1304       assert(k == 0 || midivals[ch]);
1305     }
1306     // Scan the Faust UI for active and passive controls which become the
1307     // input and output control ports of the plugin, respectively.
1308     for (int i = 0, j = 0; i < ui[0]->nelems; i++) {
1309       switch (ui[0]->elems[i].type) {
1310       case UI_T_GROUP: case UI_H_GROUP: case UI_V_GROUP: case UI_END_GROUP:
1311 	// control groups (ignored right now)
1312 	break;
1313       case UI_H_BARGRAPH: case UI_V_BARGRAPH:
1314 	// passive controls (output ports)
1315 	ctrls[j++] = i;
1316 	outctrls[q++] = i;
1317 	break;
1318       default:
1319 	// active controls (input ports)
1320 	if (maxvoices == 0)
1321 	  goto noinstr;
1322 	else if (freq == -1 &&
1323 		 !strcmp(ui[0]->elems[i].label, "freq"))
1324 	  freq = i;
1325 	else if (gain == -1 &&
1326 		 !strcmp(ui[0]->elems[i].label, "gain"))
1327 	  gain = i;
1328 	else if (gate == -1 &&
1329 		 !strcmp(ui[0]->elems[i].label, "gate"))
1330 	  gate = i;
1331 	else {
1332 	noinstr:
1333 #if FAUST_MIDICC
1334 	  std::map< int, list<strpair> >::iterator it =
1335 	    ui[0]->metadata.find(i);
1336 	  if (it != ui[0]->metadata.end()) {
1337 	    // Scan for controller mappings.
1338 	    for (std::list<strpair>::iterator jt = it->second.begin();
1339 		 jt != it->second.end(); jt++) {
1340 	      const char *key = jt->first, *val = jt->second;
1341 #if DEBUG_META
1342 	      fprintf(stderr, "ctrl '%s' meta: '%s' -> '%s'\n",
1343 		      ui[0]->elems[i].label, key, val);
1344 #endif
1345 	      if (strcmp(key, "midi") == 0) {
1346 		unsigned num;
1347 		if (sscanf(val, "ctrl %u", &num) < 1) continue;
1348 #if 0 // enable this to get feedback about controller assignments
1349 		fprintf(stderr, "%s: cc %d -> %s\n", PLUGIN_URI, num,
1350 			ui[0]->elems[i].label);
1351 #endif
1352 		ctrlmap.insert(std::pair<uint8_t,int>(num, p));
1353 	      }
1354 	    }
1355 	  }
1356 #endif
1357 	  ctrls[j++] = i;
1358 	  inctrls[p++] = i;
1359 	  int p = ui[0]->elems[i].port;
1360 	  float val = ui[0]->elems[i].init;
1361 	  assert(p>=0);
1362 	  portvals[p] = val;
1363 	  for (int ch = 0; ch < 16; ch++)
1364 	    midivals[ch][p] = val;
1365 	}
1366 	break;
1367       }
1368     }
1369     // Realloc the inctrls and outctrls vectors to their appropriate sizes.
1370     inctrls = (int*)realloc(inctrls, p*sizeof(int));
1371     assert(p == 0 || inctrls);
1372     outctrls = (int*)realloc(outctrls, q*sizeof(int));
1373     assert(q == 0 || outctrls);
1374     n_in = p; n_out = q;
1375     // Allocate vectors for the audio input and output ports. Like
1376     // ports, these will be initialized in the connect_port callback.
1377     inputs = (float**)calloc(n, sizeof(float*));
1378     assert(n == 0 || inputs);
1379     outputs = (float**)calloc(m, sizeof(float*));
1380     assert(m == 0 || outputs);
1381     if (maxvoices > 0) {
1382       // Initialize the mixdown buffer.
1383       outbuf = (float**)calloc(m, sizeof(float*));
1384       assert(m == 0 || outbuf);
1385       // We start out with a blocksize of 512 samples here. Hopefully this is
1386       // enough for most realtime hosts so that we can avoid reallocations
1387       // later when we know what the actual blocksize is.
1388       n_samples = 512;
1389       for (int i = 0; i < m; i++) {
1390 	outbuf[i] = (float*)malloc(n_samples*sizeof(float));
1391 	assert(outbuf[i]);
1392       }
1393       // Initialize a 1-sample dummy input buffer used for retriggering notes.
1394       inbuf = (float**)calloc(n, sizeof(float*));
1395       assert(n == 0 || inbuf);
1396       for (int i = 0; i < m; i++) {
1397 	inbuf[i] = (float*)malloc(sizeof(float));
1398 	assert(inbuf[i]);
1399 	*inbuf[i] = 0.0f;
1400       }
1401     }
1402   }
1403 
~LV2PluginLV2Plugin1404   ~LV2Plugin()
1405   {
1406     const int n = dsp[0]->getNumInputs();
1407     const int m = dsp[0]->getNumOutputs();
1408     for (int i = 0; i < ndsps; i++) {
1409       delete dsp[i];
1410       delete ui[i];
1411     }
1412     free(ctrls); free(inctrls); free(outctrls);
1413     free(ports); free(portvals);
1414     free(inputs); free(outputs);
1415     for (int ch = 0; ch < 16; ch++)
1416       free(midivals[ch]);
1417     if (inbuf) {
1418       for (int i = 0; i < n; i++)
1419 	free(inbuf[i]);
1420       free(inbuf);
1421     }
1422     if (outbuf) {
1423       for (int i = 0; i < m; i++)
1424 	free(outbuf[i]);
1425       free(outbuf);
1426     }
1427     free(dsp); free(ui);
1428     if (vd) {
1429       free(vd->note_info);
1430       free(vd->lastgate);
1431       delete vd;
1432     }
1433   }
1434   // Voice allocation.
1435 
1436 #if DEBUG_VOICE_ALLOC
print_voicesLV2Plugin1437   void print_voices(const char *msg)
1438   {
1439     fprintf(stderr, "%s: notes =", msg);
1440     for (uint8_t ch = 0; ch < 16; ch++)
1441       for (int note = 0; note < 128; note++)
1442 	if (vd->notes[ch][note] >= 0)
1443 	  fprintf(stderr, " [%d] %d(#%d)", ch, note, vd->notes[ch][note]);
1444     fprintf(stderr, "\nqueued (%d):", vd->queued.size());
1445     for (int i = 0; i < nvoices; i++)
1446       if (vd->queued.find(i) != vd->queued.end()) fprintf(stderr, " #%d", i);
1447     fprintf(stderr, "\nused (%d):", vd->n_used);
1448     for (boost::circular_buffer<int>::iterator it = vd->used_voices.begin();
1449 	 it != vd->used_voices.end(); it++)
1450       fprintf(stderr, " #%d->%d", *it, vd->note_info[*it].note);
1451     fprintf(stderr, "\nfree (%d):", vd->n_free);
1452     for (boost::circular_buffer<int>::iterator it = vd->free_voices.begin();
1453 	 it != vd->free_voices.end(); it++)
1454       fprintf(stderr, " #%d", *it);
1455     fprintf(stderr, "\n");
1456   }
1457 #endif
1458 
alloc_voiceLV2Plugin1459   int alloc_voice(uint8_t ch, int8_t note, int8_t vel)
1460   {
1461     int i = vd->notes[ch][note];
1462     if (i >= 0) {
1463       // note already playing on same channel, retrigger it
1464       voice_off(i);
1465       voice_on(i, note, vel, ch);
1466       // move this voice to the end of the used list
1467       for (boost::circular_buffer<int>::iterator it =
1468 	     vd->used_voices.begin();
1469 	   it != vd->used_voices.end(); it++) {
1470 	if (*it == i) {
1471 	  vd->used_voices.erase(it);
1472 	  vd->used_voices.push_back(i);
1473 	  break;
1474 	}
1475       }
1476 #if DEBUG_VOICE_ALLOC
1477       print_voices("retrigger");
1478 #endif
1479       return i;
1480     } else if (vd->n_free > 0) {
1481       // take voice from free list
1482       int i = vd->free_voices.front();
1483       vd->free_voices.pop_front();
1484       vd->n_free--;
1485       vd->used_voices.push_back(i);
1486       vd->note_info[i].ch = ch;
1487       vd->note_info[i].note = note;
1488       vd->n_used++;
1489       voice_on(i, note, vel, ch);
1490       vd->notes[ch][note] = i;
1491 #if DEBUG_VOICE_ALLOC
1492       print_voices("alloc");
1493 #endif
1494       return i;
1495     } else {
1496       // steal a voice
1497       assert(vd->n_used > 0);
1498       // FIXME: Maybe we should look for the oldest note on the *current*
1499       // channel here, but this is faster.
1500       int i = vd->used_voices.front();
1501       int oldch = vd->note_info[i].ch;
1502       int oldnote = vd->note_info[i].note;
1503       voice_off(i);
1504       vd->notes[oldch][oldnote] = -1;
1505       vd->queued.erase(i);
1506       vd->used_voices.pop_front();
1507       vd->used_voices.push_back(i);
1508       vd->note_info[i].ch = ch;
1509       vd->note_info[i].note = note;
1510       voice_on(i, note, vel, ch);
1511       vd->notes[ch][note] = i;
1512 #if DEBUG_VOICE_ALLOC
1513       print_voices("steal");
1514 #endif
1515       return i;
1516     }
1517   }
1518 
dealloc_voiceLV2Plugin1519   int dealloc_voice(uint8_t ch, int8_t note, int8_t vel)
1520   {
1521     int i = vd->notes[ch][note];
1522     if (i >= 0) {
1523       if (vd->lastgate[i] == 0.0f && gate >= 0) {
1524 	// zero-length note, queued for later
1525 	vd->queued.insert(i);
1526 	vd->notes[ch][note] = -1;
1527 #if DEBUG_VOICE_ALLOC
1528 	print_voices("dealloc (queued)");
1529 #endif
1530 	return i;
1531       }
1532       assert(vd->n_free < nvoices);
1533       vd->free_voices.push_back(i);
1534       vd->n_free++;
1535       voice_off(i);
1536       vd->notes[ch][note] = -1;
1537       // erase this voice from the used list
1538       for (boost::circular_buffer<int>::iterator it =
1539 	     vd->used_voices.begin();
1540 	   it != vd->used_voices.end(); it++) {
1541 	if (*it == i) {
1542 	  vd->used_voices.erase(it);
1543 	  vd->n_used--;
1544 	  break;
1545 	}
1546       }
1547 #if DEBUG_VOICE_ALLOC
1548       print_voices("dealloc");
1549 #endif
1550       return i;
1551     }
1552     return -1;
1553   }
1554 
1555 
midicpsLV2Plugin1556   float midicps(int8_t note, uint8_t chan)
1557   {
1558     float pitch = note + vd->tune[chan] +
1559       vd->tuning[chan][note%12] + vd->bend[chan];
1560     return 440.0*pow(2, (pitch-69.0)/12.0);
1561   }
1562 
voice_onLV2Plugin1563   void voice_on(int i, int8_t note, int8_t vel, uint8_t ch)
1564   {
1565     if (vd->lastgate[i] == 1.0f && gate >= 0) {
1566       // Make sure that the synth sees the 0.0f gate so that the voice is
1567       // properly retriggered.
1568       *ui[i]->elems[gate].zone = 0.0f;
1569       dsp[i]->compute(1, inbuf, outbuf);
1570     }
1571 #if DEBUG_VOICES
1572     fprintf(stderr, "voice on: %d %d (%g Hz) %d (%g)\n", i,
1573 	    note, midicps(note, ch), vel, vel/127.0);
1574 #endif
1575     if (freq >= 0)
1576       *ui[i]->elems[freq].zone = midicps(note, ch);
1577     if (gate >= 0)
1578       *ui[i]->elems[gate].zone = 1.0f;
1579     if (gain >= 0)
1580       *ui[i]->elems[gain].zone = vel/127.0;
1581     // reinitialize the per-channel control data for this voice
1582     for (int idx = 0; idx < n_in; idx++) {
1583       int j = inctrls[idx], k = ui[0]->elems[j].port;
1584       *ui[i]->elems[j].zone = midivals[ch][k];
1585     }
1586   }
1587 
voice_offLV2Plugin1588   void voice_off(int i)
1589   {
1590 #if DEBUG_VOICES
1591     fprintf(stderr, "voice off: %d\n", i);
1592 #endif
1593     if (gate >= 0)
1594       *ui[i]->elems[gate].zone = 0.0f;
1595   }
1596 
update_voicesLV2Plugin1597   void update_voices(uint8_t chan)
1598   {
1599     // update running voices on the given channel after tuning or pitch bend
1600     // changes
1601     for (boost::circular_buffer<int>::iterator it =
1602 	   vd->used_voices.begin();
1603 	 it != vd->used_voices.end(); it++) {
1604       int i = *it;
1605       if (vd->note_info[i].ch == chan && freq >= 0) {
1606 	int note = vd->note_info[i].note;
1607 	*ui[i]->elems[freq].zone = midicps(note, chan);
1608       }
1609     }
1610   }
1611 
all_notes_offLV2Plugin1612   void all_notes_off()
1613   {
1614     for (int i = 0; i < nvoices; i++)
1615       voice_off(i);
1616     for (int i = 0; i < 16; i++)
1617       vd->bend[i] = 0.0f;
1618     memset(vd->notes, 0xff, sizeof(vd->notes));
1619     vd->free_voices.clear();
1620     vd->n_free = nvoices;
1621     for (int i = 0; i < nvoices; i++)
1622       vd->free_voices.push_back(i);
1623     vd->queued.clear();
1624     vd->used_voices.clear();
1625     vd->n_used = 0;
1626   }
1627 
all_notes_offLV2Plugin1628   void all_notes_off(uint8_t chan)
1629   {
1630     for (boost::circular_buffer<int>::iterator it =
1631 	   vd->used_voices.begin();
1632 	 it != vd->used_voices.end(); ) {
1633       int i = *it;
1634       if (vd->note_info[i].ch == chan) {
1635 	assert(vd->n_free < nvoices);
1636 	vd->free_voices.push_back(i);
1637 	vd->n_free++;
1638 	voice_off(i);
1639 	vd->notes[vd->note_info[i].ch][vd->note_info[i].note] = -1;
1640 	vd->queued.erase(i);
1641 	// erase this voice from the used list
1642 	it = vd->used_voices.erase(it);
1643 	vd->n_used--;
1644 #if DEBUG_VOICE_ALLOC
1645 	print_voices("dealloc (all-notes-off)");
1646 #endif
1647       } else
1648 	it++;
1649     }
1650     vd->bend[chan] = 0.0f;
1651   }
1652 
queued_notes_offLV2Plugin1653   void queued_notes_off()
1654   {
1655     if (vd->queued.empty()) return;
1656     for (int i = 0; i < nvoices; i++)
1657       if (vd->queued.find(i) != vd->queued.end()) {
1658 	assert(vd->n_free < nvoices);
1659 	vd->free_voices.push_back(i);
1660 	vd->n_free++;
1661 	voice_off(i);
1662 	vd->notes[vd->note_info[i].ch][vd->note_info[i].note] = -1;
1663 	vd->queued.erase(i);
1664 	// erase this voice from the used list
1665 	for (boost::circular_buffer<int>::iterator it =
1666 	       vd->used_voices.begin();
1667 	     it != vd->used_voices.end(); it++) {
1668 	  if (*it == i) {
1669 	    vd->used_voices.erase(it);
1670 	    vd->n_used--;
1671 	    break;
1672 	  }
1673 	}
1674 #if DEBUG_VOICE_ALLOC
1675 	print_voices("dealloc (unqueued)");
1676 #endif
1677       }
1678   }
1679 
1680   // Plugin activation status. suspend() deactivates a plugin (disables audio
1681   // processing), resume() reactivates it. Also, set_rate() changes the sample
1682   // rate. Note that the audio and MIDI process functions (see below) can
1683   // still be called in deactivated state, but this is optional. The plugin
1684   // tries to do some reasonable processing in either case, no matter whether
1685   // the host plugin architecture actually executes callbacks in suspended
1686   // state or not.
1687 
suspendLV2Plugin1688   void suspend()
1689   {
1690     active = false;
1691     if (maxvoices > 0) all_notes_off();
1692   }
1693 
resumeLV2Plugin1694   void resume()
1695   {
1696     for (int i = 0; i < ndsps; i++)
1697       dsp[i]->init(rate);
1698     for (int i = 0, j = 0; i < ui[0]->nelems; i++) {
1699       int p = ui[0]->elems[i].port;
1700       if (p >= 0) {
1701 	float val = ui[0]->elems[i].init;
1702 	portvals[p] = val;
1703       }
1704     }
1705     active = true;
1706   }
1707 
set_rateLV2Plugin1708   void set_rate(int sr)
1709   {
1710     rate = sr;
1711     for (int i = 0; i < ndsps; i++)
1712       dsp[i]->init(rate);
1713   }
1714 
1715   // Audio and MIDI process functions. The plugin should run these in the
1716   // appropriate real-time callbacks.
1717 
process_audioLV2Plugin1718   void process_audio(int blocksz, float **inputs, float **outputs)
1719   {
1720     int n = dsp[0]->getNumInputs(), m = dsp[0]->getNumOutputs();
1721     AVOIDDENORMALS;
1722     if (maxvoices > 0) queued_notes_off();
1723     if (!active) {
1724       // Depending on the plugin architecture and host, this code might never
1725       // be invoked, since the plugin is deactivitated at this point. But
1726       // let's do something reasonable here anyway.
1727       if (n == m) {
1728 	// copy inputs to outputs
1729 	for (int i = 0; i < m; i++)
1730 	  for (unsigned j = 0; j < blocksz; j++)
1731 	    outputs[i][j] = inputs[i][j];
1732       } else {
1733 	// silence
1734 	for (int i = 0; i < m; i++)
1735 	  for (unsigned j = 0; j < blocksz; j++)
1736 	    outputs[i][j] = 0.0f;
1737       }
1738       return;
1739     }
1740     // Handle changes in the polyphony and tuning controls.
1741     bool is_instr = maxvoices > 0;
1742     if (is_instr) {
1743       if (!poly)
1744 	; // this shouldn't happen but...
1745       else if (nvoices != (int)*poly &&
1746 	       (int)*poly > 0 && (int)*poly <= maxvoices) {
1747 	for (int i = 0; i < nvoices; i++)
1748 	  voice_off(i);
1749         nvoices = (int)*poly;
1750 	// Reset the voice allocation.
1751 	memset(vd->notes, 0xff, sizeof(vd->notes));
1752 	vd->free_voices.clear();
1753 	vd->n_free = nvoices;
1754 	for (int i = 0; i < nvoices; i++)
1755 	  vd->free_voices.push_back(i);
1756 	vd->used_voices.clear();
1757 	vd->n_used = 0;
1758       } else
1759 	*poly = nvoices;
1760 #if FAUST_MTS
1761       if (tuning && tuning_no != (int)*tuning) change_tuning((int)*tuning);
1762 #endif
1763     }
1764     // Only update the controls (of all voices simultaneously) if a port value
1765     // actually changed. This is necessary to allow MIDI controllers to modify
1766     // the values for individual MIDI channels (see processEvents below). Also
1767     // note that this will be done *after* processing the MIDI controller data
1768     // for the current audio block, so manual inputs can still override these.
1769     for (int i = 0; i < n_in; i++) {
1770       int j = inctrls[i], k = ui[0]->elems[j].port;
1771       float &oldval = portvals[k], newval = *ports[k];
1772       if (newval != oldval) {
1773 	if (is_instr) {
1774 	  // instrument: update running voices
1775 	  for (boost::circular_buffer<int>::iterator it =
1776 		 vd->used_voices.begin();
1777 	       it != vd->used_voices.end(); it++) {
1778 	    int i = *it;
1779 	    *ui[i]->elems[j].zone = newval;
1780 	  }
1781 	} else {
1782 	  // simple effect: here we only have a single dsp instance
1783 	  *ui[0]->elems[j].zone = newval;
1784 	}
1785 	// also update the MIDI controller data for all channels (manual
1786 	// control input is always omni)
1787 	for (int ch = 0; ch < 16; ch++)
1788 	  midivals[ch][k] = newval;
1789 	// record the new value
1790 	oldval = newval;
1791       }
1792     }
1793     // Initialize the output buffers.
1794     if (n_samples < blocksz) {
1795       // We need to enlarge the buffers. We're not officially allowed to do
1796       // this here (presumably in the realtime thread), but since we usually
1797       // don't know the hosts's block size beforehand, there's really nothing
1798       // else that we can do. Let's just hope that doing this once suffices,
1799       // then hopefully noone will notice.
1800       if (outbuf) {
1801 	for (int i = 0; i < m; i++) {
1802 	  outbuf[i] = (float*)realloc(outbuf[i],
1803 				      blocksz*sizeof(float));
1804 	  assert(outbuf[i]);
1805 	}
1806       }
1807       n_samples = blocksz;
1808     }
1809     if (outbuf) {
1810       // Polyphonic instrument: Mix the voices down to one signal.
1811       for (int i = 0; i < m; i++)
1812 	for (unsigned j = 0; j < blocksz; j++)
1813 	  outputs[i][j] = 0.0f;
1814       for (int l = 0; l < nvoices; l++) {
1815 	// Let Faust do all the hard work.
1816 	dsp[l]->compute(blocksz, inputs, outbuf);
1817 	for (int i = 0; i < m; i++)
1818 	  for (unsigned j = 0; j < blocksz; j++)
1819 	    outputs[i][j] += outbuf[i][j];
1820       }
1821     } else {
1822       // Simple effect: We can write directly to the output buffer.
1823       dsp[0]->compute(blocksz, inputs, outputs);
1824     }
1825     // Finally grab the passive controls and write them back to the
1826     // corresponding control ports. NOTE: Depending on the plugin
1827     // architecture, this might require a host call to get the control GUI
1828     // updated in real-time (if the host supports this at all).
1829     // FIXME: It's not clear how to aggregate the data of the different
1830     // voices. We compute the maximum of each control for now.
1831     for (int i = 0; i < n_out; i++) {
1832       int j = outctrls[i], k = ui[0]->elems[j].port;
1833       float *z = ui[0]->elems[j].zone;
1834       *ports[k] = *z;
1835       for (int l = 1; l < nvoices; l++) {
1836 	float *z = ui[l]->elems[j].zone;
1837 	if (*ports[k] < *z)
1838 	  *ports[k] = *z;
1839       }
1840     }
1841     // Keep track of the last gates set for each voice, so that voices can be
1842     // forcibly retriggered if needed.
1843     if (gate >= 0)
1844       for (int i = 0; i < nvoices; i++)
1845 	vd->lastgate[i] =
1846 	  *ui[i]->elems[gate].zone;
1847   }
1848 
1849   // This processes just a single MIDI message, so to process an entire series
1850   // of MIDI events you'll have to loop over the event data in the plugin's
1851   // MIDI callback. XXXTODO: Sample-accurate processing of MIDI events.
1852 
process_midiLV2Plugin1853   void process_midi(unsigned char *data, int sz)
1854   {
1855 #if DEBUG_MIDI
1856     fprintf(stderr, "midi ev (%d bytes):", sz);
1857     for (int i = 0; i < sz; i++)
1858       fprintf(stderr, " 0x%0x", data[i]);
1859     fprintf(stderr, "\n");
1860 #endif
1861     uint8_t status = data[0] & 0xf0, chan = data[0] & 0x0f;
1862     bool is_instr = maxvoices > 0;
1863     switch (status) {
1864     case 0x90: {
1865       if (!is_instr) break;
1866       // note on
1867 #if DEBUG_NOTES
1868       fprintf(stderr, "note-on  chan %d, note %d, vel %d\n", chan+1,
1869 	      data[1], data[2]);
1870 #endif
1871       if (data[2] == 0) goto note_off;
1872       alloc_voice(chan, data[1], data[2]);
1873       break;
1874     }
1875     case 0x80: {
1876       if (!is_instr) break;
1877       // note off
1878 #if DEBUG_NOTES
1879       fprintf(stderr, "note-off chan %d, note %d, vel %d\n", chan+1,
1880 	      data[1], data[2]);
1881 #endif
1882       note_off:
1883       dealloc_voice(chan, data[1], data[2]);
1884       break;
1885     }
1886     case 0xe0: {
1887       if (!is_instr) break;
1888       // pitch bend
1889       // data[1] is LSB, data[2] MSB, range is 0..0x3fff (which maps to
1890       // -2..+2 semitones by default), center point is 0x2000 = 8192
1891       int val = data[1] | (data[2]<<7);
1892       vd->bend[chan] =
1893 	(val-0x2000)/8192.0f*vd->range[chan];
1894 #if DEBUG_MIDICC
1895       fprintf(stderr, "pitch-bend (chan %d): %g cent\n", chan+1,
1896 	      vd->bend[chan]*100.0);
1897 #endif
1898       update_voices(chan);
1899       break;
1900     }
1901     case 0xb0: {
1902       // controller change
1903       switch (data[1]) {
1904       case 120: case 123:
1905 	if (!is_instr) break;
1906 	// all-sound-off and all-notes-off controllers (these are treated
1907 	// the same in the current implementation)
1908 	all_notes_off(chan);
1909 #if DEBUG_MIDICC
1910 	fprintf(stderr, "all-notes-off (chan %d)\n", chan+1);
1911 #endif
1912 	break;
1913       case 121:
1914 	// all-controllers-off (in the current implementation, this just
1915 	// resets the RPN-related controllers)
1916 	data_msb[chan] = data_lsb[chan] = 0;
1917 	rpn_msb[chan] = rpn_lsb[chan] = 0x7f;
1918 #if DEBUG_MIDICC
1919 	fprintf(stderr, "all-controllers-off (chan %d)\n", chan+1);
1920 #endif
1921 	break;
1922       case 101: case 100:
1923 	// RPN MSB/LSB
1924 	if (data[1] == 101)
1925 	  rpn_msb[chan] = data[2];
1926 	else
1927 	  rpn_lsb[chan] = data[2];
1928 	break;
1929       case 6: case 38:
1930 	// data entry coarse/fine
1931 	if (data[1] == 6)
1932 	  data_msb[chan] = data[2];
1933 	else
1934 	  data_lsb[chan] = data[2];
1935 	goto rpn;
1936       case 96: case 97:
1937 	// data increment/decrement
1938 	/* NOTE: The specification of these controllers is a complete
1939 	   mess. Originally, the MIDI specification didn't have anything
1940 	   to say about their exact behaviour at all. Nowadays, the
1941 	   behaviour depends on which RPN or NRPN is being modified, which
1942 	   is also rather confusing. Fortunately, as we only handle RPNs
1943 	   0..2 here anyway, it's sufficient to assume the MSB for RPN #2
1944 	   (channel coarse tuning) and the LSB otherwise. */
1945 	if (rpn_msb[chan] == 0 && rpn_lsb[chan] == 2) {
1946 	  // modify the MSB
1947 	  if (data[1] == 96 && data_msb[chan] < 0x7f)
1948 	    data_msb[chan]++;
1949 	  else if (data[1] == 97 && data_msb[chan] > 0)
1950 	    data_msb[chan]--;
1951 	} else {
1952 	  // modify the LSB
1953 	  if (data[1] == 96 && data_lsb[chan] < 0x7f)
1954 	    data_lsb[chan]++;
1955 	  else if (data[1] == 97 && data_lsb[chan] > 0)
1956 	    data_lsb[chan]--;
1957 	}
1958       rpn:
1959 	if (!is_instr) break;
1960 	if (rpn_msb[chan] == 0) {
1961 	  switch (rpn_lsb[chan]) {
1962 	  case 0:
1963 	    // pitch bend range, coarse value is in semitones, fine value
1964 	    // in cents
1965 	    vd->range[chan] = data_msb[chan]+
1966 	      data_lsb[chan]/100.0;
1967 #if DEBUG_RPN
1968 	    fprintf(stderr, "pitch-bend-range (chan %d): %g cent\n", chan+1,
1969 		    vd->range[chan]*100.0);
1970 #endif
1971 	    break;
1972 	  case 1:
1973 	    {
1974 	      // channel fine tuning (14 bit value, range -100..+100 cents)
1975 	      int value = (data_msb[chan]<<7) |
1976 		data_lsb[chan];
1977 	      vd->fine[chan] = (value-8192)/8192.0f;
1978 	    }
1979 	    goto master_tune;
1980 	  case 2:
1981 	    // channel coarse tuning (only msb is used, range -64..+63
1982 	    // semitones)
1983 	    vd->coarse[chan] = data_msb[chan]-64;
1984 	  master_tune:
1985 	    vd->tune[chan] = vd->coarse[chan]+
1986 	      vd->fine[chan];
1987 #if DEBUG_RPN
1988 	    fprintf(stderr, "master-tuning (chan %d): %g cent\n", chan+1,
1989 		    vd->tune[chan]*100.0);
1990 #endif
1991 	    update_voices(chan);
1992 	    break;
1993 	  default:
1994 	    break;
1995 	  }
1996 	}
1997 	break;
1998       default: {
1999 #if FAUST_MIDICC
2000 	// interpret all other controller changes according to the MIDI
2001 	// controller map defined in the Faust plugin itself
2002 	std::map<uint8_t,int>::iterator it = ctrlmap.find(data[1]);
2003 	if (it != ctrlmap.end()) {
2004 	  // defined MIDI controller
2005 	  int j = inctrls[it->second],
2006 	    k = ui[0]->elems[j].port;
2007 	  float val = ctrlval(ui[0]->elems[j], data[2]);
2008 	  midivals[chan][k] = val;
2009 	  if (is_instr) {
2010 	    // instrument: update running voices on this channel
2011 	    for (boost::circular_buffer<int>::iterator it =
2012 		   vd->used_voices.begin();
2013 		 it != vd->used_voices.end(); it++) {
2014 	      int i = *it;
2015 	      if (vd->note_info[i].ch == chan)
2016 		*ui[i]->elems[j].zone = val;
2017 	    }
2018 	  } else {
2019 	    // simple effect: here we only have a single dsp instance and
2020 	    // we're operating in omni mode, so we just update the control no
2021 	    // matter what the midi channel is
2022 	    *ui[0]->elems[j].zone = val;
2023 	  }
2024 #if DEBUG_MIDICC
2025 	  fprintf(stderr, "ctrl-change chan %d, ctrl %d, val %d\n", chan+1,
2026 		  data[1], data[2]);
2027 #endif
2028 	}
2029 #endif
2030 	break;
2031       }
2032       }
2033       break;
2034     }
2035     default:
2036       break;
2037     }
2038   }
2039 
2040   // Process an MTS sysex message and update the control values accordingly.
2041 
process_sysexLV2Plugin2042   void process_sysex(uint8_t *data, int sz)
2043   {
2044     if (!data || sz < 2) return;
2045 #if DEBUG_MIDI
2046     fprintf(stderr, "midi sysex (%d bytes):", sz);
2047     for (int i = 0; i < sz; i++)
2048       fprintf(stderr, " 0x%0x", data[i]);
2049     fprintf(stderr, "\n");
2050 #endif
2051     if (data[0] == 0xf0) {
2052       // Skip over the f0 and f7 status bytes in case they are included in the
2053       // dump.
2054       data++; sz--;
2055       if (data[sz-1] == 0xf7) sz--;
2056     }
2057     if ((data[0] == 0x7e || data[0] == 0x7f) && data[2] == 8) {
2058       // MIDI tuning standard
2059       bool realtime = data[0] == 0x7f;
2060       if ((sz == 19 && data[3] == 8) ||
2061 	  (sz == 31 && data[3] == 9)) {
2062 	// MTS scale/octave tuning 1- or 2-byte form
2063 	bool onebyte = data[3] == 8;
2064 	unsigned chanmsk = (data[4]<<14) | (data[5]<<7) | data[6];
2065 	for (int i = 0; i < 12; i++) {
2066 	  float t;
2067 	  if (onebyte)
2068 	    t = (data[i+7]-64)/100.0;
2069 	  else
2070 	    t = (((data[2*i+7]<<7)|data[2*i+8])-8192)/8192.0;
2071 	  for (uint8_t ch = 0; ch < 16; ch++)
2072 	    if (chanmsk & (1<<ch))
2073 	      vd->tuning[ch][i] = t;
2074 	}
2075 	if (realtime) {
2076 	  for (uint8_t ch = 0; ch < 16; ch++)
2077 	    if (chanmsk & (1<<ch)) {
2078 	      // update running voices on this channel
2079 	      update_voices(ch);
2080 	    }
2081 	}
2082 #if DEBUG_MTS
2083 	fprintf(stderr, "octave-tuning-%s (chan ",
2084 		realtime?"realtime":"non-realtime");
2085 	bool first = true;
2086 	for (uint8_t i = 0; i < 16; )
2087 	  if (chanmsk & (1<<i)) {
2088 	    uint8_t j;
2089 	    for (j = i+1; j < 16 && (chanmsk&(1<<j)); )
2090 	      j++;
2091 	    if (first)
2092 	      first = false;
2093 	    else
2094 	      fprintf(stderr, ",");
2095 	    if (j > i+1)
2096 	      fprintf(stderr, "%u-%u", i+1, j);
2097 	    else
2098 	      fprintf(stderr, "%u", i+1);
2099 	    i = j;
2100 	  } else
2101 	    i++;
2102 	fprintf(stderr, "):");
2103 	if (onebyte) {
2104 	  for (int i = 7; i < 19; i++) {
2105 	    int val = data[i];
2106 	    fprintf(stderr, " %d", val-64);
2107 	  }
2108 	} else {
2109 	  for (int i = 7; i < 31; i++) {
2110 	    int val = data[i++] << 7;
2111 	    val |= data[i];
2112 	    fprintf(stderr, " %g", ((double)val-8192.0)/8192.0*100.0);
2113 	  }
2114 	}
2115 	fprintf(stderr, "\n");
2116 #endif
2117       }
2118     }
2119   }
2120 
2121   // Change to a given preloaded tuning. The given tuning number may be in the
2122   // range 1..PFaustPlugin::n_tunings, zero denotes the default tuning (equal
2123   // temperament). This is only supported if FAUST_MTS is defined at compile
2124   // time.
2125 
change_tuningLV2Plugin2126   void change_tuning(int num)
2127   {
2128 #if FAUST_MTS
2129     if (!mts || num == tuning_no) return;
2130     if (num < 0) num = 0;
2131     if (num > mts->tuning.size())
2132       num = mts->tuning.size();
2133     tuning_no = num;
2134     if (tuning_no > 0) {
2135       process_sysex(mts->tuning[tuning_no-1].data,
2136 		    mts->tuning[tuning_no-1].len);
2137     } else {
2138       memset(vd->tuning, 0, sizeof(vd->tuning));
2139 #if DEBUG_MTS
2140       fprintf(stderr,
2141 	      "octave-tuning-default (chan 1-16): equal temperament\n");
2142 #endif
2143     }
2144 #endif
2145   }
2146 
2147 };
2148 
2149 Meta *LV2Plugin::meta = 0;
2150 int LV2Plugin::n_tunings = 0;
2151 #if FAUST_MTS
2152 MTSTunings *LV2Plugin::mts = 0;
2153 #endif
2154 
2155 /* LV2-specific part starts here. ********************************************/
2156 
2157 static LV2_Handle
instantiate(const LV2_Descriptor * descriptor,double rate,const char * bundle_path,const LV2_Feature * const * features)2158 instantiate(const LV2_Descriptor*     descriptor,
2159             double                    rate,
2160             const char*               bundle_path,
2161             const LV2_Feature* const* features)
2162 {
2163   LV2Plugin* plugin =
2164     new LV2Plugin(LV2Plugin::numVoices(), (int)rate);
2165   // Scan host features for URID map.
2166   for (int i = 0; features[i]; i++) {
2167     if (!strcmp(features[i]->URI, LV2_URID_URI "#map")) {
2168       plugin->map = (LV2_URID_Map*)features[i]->data;
2169       plugin->midi_event =
2170 	plugin->map->map(plugin->map->handle, MIDI_EVENT_URI);
2171     }
2172   }
2173   if (!plugin->map) {
2174     fprintf
2175       (stderr, "%s: host doesn't support urid:map, giving up\n",
2176        PLUGIN_URI);
2177     delete plugin;
2178     return 0;
2179   }
2180   return (LV2_Handle)plugin;
2181 }
2182 
2183 static void
cleanup(LV2_Handle instance)2184 cleanup(LV2_Handle instance)
2185 {
2186   LV2Plugin* plugin = (LV2Plugin*)instance;
2187   delete plugin;
2188 }
2189 
2190 static void
connect_port(LV2_Handle instance,uint32_t port,void * data)2191 connect_port(LV2_Handle instance,
2192              uint32_t   port,
2193              void*      data)
2194 {
2195   LV2Plugin* plugin = (LV2Plugin*)instance;
2196   int i = port, k = plugin->ui[0]->nports;
2197   int n = plugin->dsp[0]->getNumInputs(), m = plugin->dsp[0]->getNumOutputs();
2198   if (i < k)
2199     plugin->ports[i] = (float*)data;
2200   else {
2201     i -= k;
2202     if (i < n)
2203       plugin->inputs[i] = (float*)data;
2204     else {
2205       i -= n;
2206       if (i < m)
2207 	plugin->outputs[i] = (float*)data;
2208       else if (i == m)
2209 	plugin->event_port = (LV2_Atom_Sequence*)data;
2210       else if (i == m+1)
2211 	plugin->poly = (float*)data;
2212       else if (i == m+2)
2213 	plugin->tuning = (float*)data;
2214       else
2215 	fprintf(stderr, "%s: bad port number %u\n", PLUGIN_URI, port);
2216     }
2217   }
2218 }
2219 
2220 static void
run(LV2_Handle instance,uint32_t n_samples)2221 run(LV2_Handle instance, uint32_t n_samples)
2222 {
2223   LV2Plugin* plugin = (LV2Plugin*)instance;
2224   // Process incoming MIDI events.
2225   if (plugin->event_port) {
2226     LV2_ATOM_SEQUENCE_FOREACH(plugin->event_port, ev) {
2227       if (ev->body.type == plugin->midi_event) {
2228 	uint8_t *data = (uint8_t*)(ev+1);
2229 #if 0
2230 	// FIXME: Consider doing sample-accurate note onsets here. LV2 keeps
2231 	// track of the exact onset in the frames and subframes fields
2232 	// (http://lv2plug.in/ns/doc/html/structLV2__Atom__Event.html), but we
2233 	// can't use that information at present, since our gate parameter is
2234 	// a control variable which can only change at block boundaries. In
2235 	// the future, the gate could be implemented as an audio signal to get
2236 	// sample-accurate note onsets.
2237 	uint32_t frames = ev->body.frames;
2238 #endif
2239 	if (data[0] == 0xf0)
2240 	  plugin->process_sysex(data, ev->body.size);
2241 	else
2242 	  plugin->process_midi(data, ev->body.size);
2243       }
2244     }
2245   }
2246   // Process audio.
2247   plugin->process_audio(n_samples, plugin->inputs, plugin->outputs);
2248 }
2249 
2250 static void
activate(LV2_Handle instance)2251 activate(LV2_Handle instance)
2252 {
2253   LV2Plugin* plugin = (LV2Plugin*)instance;
2254   plugin->resume();
2255 }
2256 
2257 static void
deactivate(LV2_Handle instance)2258 deactivate(LV2_Handle instance)
2259 {
2260   LV2Plugin* plugin = (LV2Plugin*)instance;
2261   plugin->suspend();
2262 }
2263 
2264 const void*
extension_data(const char * uri)2265 extension_data(const char* uri)
2266 {
2267   return NULL;
2268 }
2269 
2270 static const LV2_Descriptor descriptor = {
2271   PLUGIN_URI,
2272   instantiate,
2273   connect_port,
2274   activate,
2275   run,
2276   deactivate,
2277   cleanup,
2278   extension_data
2279 };
2280 
2281 extern "C"
2282 LV2_SYMBOL_EXPORT
2283 const LV2_Descriptor*
lv2_descriptor(uint32_t index)2284 lv2_descriptor(uint32_t index)
2285 {
2286   switch (index) {
2287   case 0:
2288     return &descriptor;
2289   default:
2290     return NULL;
2291   }
2292 }
2293 
2294 //----------------------------------------------------------------------------
2295 //  Dynamic manifest
2296 //----------------------------------------------------------------------------
2297 
2298 // NOTE: If your LV2 host doesn't offer this extension then you'll have to
2299 // create a static ttl file with the descriptions of the ports. You can do
2300 // this by compiling this code to a standalone executable. Running the
2301 // executable then prints the manifest on stdout.
2302 
2303 extern "C"
2304 LV2_SYMBOL_EXPORT
lv2_dyn_manifest_open(LV2_Dyn_Manifest_Handle * handle,const LV2_Feature * const * features)2305 int lv2_dyn_manifest_open(LV2_Dyn_Manifest_Handle *handle,
2306 			  const LV2_Feature *const *features)
2307 {
2308   LV2Plugin* plugin =
2309     new LV2Plugin(LV2Plugin::numVoices(), 48000);
2310   *handle = (LV2_Dyn_Manifest_Handle)plugin;
2311   return 0;
2312 }
2313 
2314 extern "C"
2315 LV2_SYMBOL_EXPORT
lv2_dyn_manifest_get_subjects(LV2_Dyn_Manifest_Handle handle,FILE * fp)2316 int lv2_dyn_manifest_get_subjects(LV2_Dyn_Manifest_Handle handle,
2317 				  FILE *fp)
2318 {
2319   fprintf(fp, "@prefix lv2:  <http://lv2plug.in/ns/lv2core#> .\n\
2320 <%s> a lv2:Plugin .\n", PLUGIN_URI);
2321   return 0;
2322 }
2323 
2324 #include <string>
2325 #include <ctype.h>
2326 
mangle(const string & s)2327 static string mangle(const string &s)
2328 {
2329   string t = s;
2330   size_t n = s.size();
2331   for (size_t i = 0; i < n; i++)
2332     if ((i == 0 && !isalpha(t[i]) && t[i] != '_') ||
2333 	(!isalnum(t[i]) && t[i] != '_'))
2334       t[i] = '_';
2335   return t;
2336 }
2337 
steps(float min,float max,float step)2338 static unsigned steps(float min, float max, float step)
2339 {
2340   if (step == 0.0) return 1;
2341   int n = (max-min)/step;
2342   if (n < 0) n = -n;
2343   if (n == 0) n = 1;
2344   return n;
2345 }
2346 
2347 #if FAUST_META
is_xmlstring(const char * s)2348 static bool is_xmlstring(const char *s)
2349 {
2350   // This is just a basic sanity check. The string must not contain any
2351   // (unescaped) newlines, carriage returns or double quotes.
2352   return !strchr(s, '\n') && !strchr(s, '\r') && !strchr(s, '"');
2353 }
2354 #endif
2355 
2356 extern "C"
2357 LV2_SYMBOL_EXPORT
lv2_dyn_manifest_get_data(LV2_Dyn_Manifest_Handle handle,FILE * fp,const char * uri)2358 int lv2_dyn_manifest_get_data(LV2_Dyn_Manifest_Handle handle,
2359 			      FILE *fp,
2360 			      const char *uri)
2361 {
2362   LV2Plugin* plugin = (LV2Plugin*)handle;
2363   int k = plugin->ui[0]->nports;
2364   int n = plugin->dsp[0]->getNumInputs(), m = plugin->dsp[0]->getNumOutputs();
2365   bool is_instr = plugin->maxvoices > 0, have_midi = is_instr;
2366   // Scan the global metadata for plugin name, description, license etc.
2367   const char *plugin_name = NULL, *plugin_author = NULL, *plugin_descr = NULL,
2368     *plugin_version = NULL, *plugin_license = NULL;
2369 #if FAUST_META
2370   plugin_name = plugin->pluginName();
2371   plugin_descr = plugin->pluginDescription();
2372   plugin_author = plugin->pluginAuthor();
2373   plugin_version = plugin->pluginVersion();
2374   plugin_license = plugin->pluginLicense();
2375 #endif
2376   if (!plugin_name || !*plugin_name) plugin_name = "harm_trem_ext";
2377   fprintf(fp, "@prefix doap:  <http://usefulinc.com/ns/doap#> .\n\
2378 @prefix foaf:  <http://xmlns.com/foaf/0.1/> .\n\
2379 @prefix lv2:   <http://lv2plug.in/ns/lv2core#> .\n\
2380 @prefix ui:    <http://lv2plug.in/ns/extensions/ui#> .\n\
2381 @prefix epp:   <http://lv2plug.in/ns/ext/port-props#> .\n\
2382 @prefix atom:  <http://lv2plug.in/ns/ext/atom#> .\n\
2383 @prefix rdf:   <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n\
2384 @prefix rdfs:  <http://www.w3.org/2000/01/rdf-schema#> .\n\
2385 @prefix units: <http://lv2plug.in/ns/extensions/units#> .\n\
2386 <%s>\n\
2387        a lv2:Plugin%s ;\n\
2388        doap:name \"%s\" ;\n\
2389        lv2:binary <harm_trem_ext%s> ;\n\
2390        lv2:optionalFeature epp:supportsStrictBounds ;\n\
2391        lv2:optionalFeature lv2:hardRtCapable ;\n", PLUGIN_URI,
2392 	  is_instr?", lv2:InstrumentPlugin":"",
2393 	  plugin_name, DLLEXT);
2394   if (plugin_author && *plugin_author)
2395     fprintf(fp, "\
2396        doap:maintainer [ foaf:name \"%s\" ] ;\n", plugin_author);
2397   // doap:description just seems to be ignored by all LV2 hosts anyway, so we
2398   // rather use rdfs:comment now which works with Ardour at least.
2399   if (plugin_descr && *plugin_descr)
2400     fprintf(fp, "\
2401        rdfs:comment \"%s\" ;\n", plugin_descr);
2402   if (plugin_version && *plugin_version)
2403     fprintf(fp, "\
2404        doap:revision \"%s\" ;\n", plugin_version);
2405   if (plugin_license && *plugin_license)
2406     fprintf(fp, "\
2407        doap:license \"%s\" ;\n", plugin_license);
2408 #if FAUST_UI
2409     fprintf(fp, "\
2410        ui:ui <%sui> ;\n", PLUGIN_URI);
2411 #endif
2412   int idx = 0;
2413   // control ports
2414   for (int i = 0; i < k; i++, idx++) {
2415     int j = plugin->ctrls[i];
2416     assert(idx == plugin->ui[0]->elems[j].port);
2417     fprintf(fp, "%s [\n", idx==0?"    lv2:port":" ,");
2418     const char *label = plugin->ui[0]->elems[j].label;
2419     assert(label);
2420     string sym = mangle(plugin->ui[0]->elems[j].label);
2421     switch (plugin->ui[0]->elems[j].type) {
2422     // active controls (input ports)
2423     case UI_BUTTON: case UI_CHECK_BUTTON:
2424     fprintf(fp, "\
2425 	a lv2:InputPort ;\n\
2426 	a lv2:ControlPort ;\n\
2427 	lv2:index %d ;\n\
2428 	lv2:symbol \"%s_%d\" ;\n\
2429 	lv2:name \"%s\" ;\n\
2430         lv2:portProperty epp:hasStrictBounds ;\n\
2431         lv2:portProperty lv2:toggled ;\n\
2432 	lv2:default 0.00000 ;\n\
2433 	lv2:minimum 0.00000 ;\n\
2434 	lv2:maximum 1.00000 ;\n", idx, sym.c_str(), idx, label);
2435       break;
2436     case UI_NUM_ENTRY: case UI_H_SLIDER: case UI_V_SLIDER:
2437     fprintf(fp, "\
2438 	a lv2:InputPort ;\n\
2439 	a lv2:ControlPort ;\n\
2440 	lv2:index %d ;\n\
2441 	lv2:symbol \"%s_%d\" ;\n\
2442 	lv2:name \"%s\" ;\n\
2443         lv2:portProperty epp:hasStrictBounds ;\n\
2444         epp:rangeSteps %u ;\n\
2445 	lv2:default %g ;\n\
2446 	lv2:minimum %g ;\n\
2447 	lv2:maximum %g ;\n", idx, sym.c_str(), idx, label,
2448 	    steps(plugin->ui[0]->elems[j].min,
2449 		  plugin->ui[0]->elems[j].max,
2450 		  plugin->ui[0]->elems[j].step),
2451 	    plugin->ui[0]->elems[j].init,
2452 	    plugin->ui[0]->elems[j].min,
2453 	    plugin->ui[0]->elems[j].max);
2454       break;
2455     // passive controls (output ports)
2456     case UI_H_BARGRAPH: case UI_V_BARGRAPH:
2457     fprintf(fp, "\
2458 	a lv2:OutputPort ;\n\
2459 	a lv2:ControlPort ;\n\
2460 	lv2:index %d ;\n\
2461 	lv2:symbol \"%s_%d\" ;\n\
2462 	lv2:name \"%s\" ;\n\
2463 	lv2:default %g ;\n\
2464 	lv2:minimum %g ;\n\
2465 	lv2:maximum %g ;\n", idx, sym.c_str(), idx, label,
2466 	    plugin->ui[0]->elems[j].min,
2467 	    plugin->ui[0]->elems[j].min,
2468 	    plugin->ui[0]->elems[j].max);
2469       break;
2470     default:
2471       assert(0 && "this can't happen");
2472       break;
2473     }
2474     // Scan for Faust control metadata we understand and add corresponding
2475     // hints to the LV2 description of the port.
2476     std::map< int, list<strpair> >::iterator it =
2477       plugin->ui[0]->metadata.find(j);
2478     if (it != plugin->ui[0]->metadata.end()) {
2479       for (std::list<strpair>::iterator jt = it->second.begin();
2480 	   jt != it->second.end(); jt++) {
2481 	const char *key = jt->first, *val = jt->second;
2482 #if FAUST_MIDICC
2483 	unsigned num;
2484 	if (!strcmp(key, "midi") && sscanf(val, "ctrl %u", &num) == 1)
2485 	  have_midi = true;
2486 #endif
2487 	if (!strcmp(key, "unit"))
2488 	  fprintf(fp, "\
2489 	units:unit [\n\
2490             a            units:Unit ;\n\
2491             units:name   \"%s\" ;\n\
2492             units:symbol \"%s\" ;\n\
2493             units:render \"%%f %s\"\n\
2494 	] ;\n", val, val, val);
2495 	if (strcmp(key, "lv2")) continue;
2496 	if (!strcmp(val, "integer"))
2497 	  fprintf(fp, "\
2498 	lv2:portProperty lv2:integer ;\n");
2499 	else if (!strcmp(val, "reportsLatency"))
2500 	  fprintf(fp, "\
2501 	lv2:portProperty lv2:reportsLatency ;\n\
2502 	lv2:designation lv2:latency ;\n");
2503 	else if (!strcmp(val, "hidden") || !strcmp(val, "notOnGUI"))
2504 	  fprintf(fp, "\
2505 	lv2:portProperty epp:notOnGUI ;\n");
2506 	else if (!strncmp(val, "scalepoint", 10) ||
2507 		 !strncmp(val, "scalePoint", 10)) {
2508 	  val += 10;
2509 	  if (!isspace(*val)) continue;
2510 	  char *label = (char*)malloc(strlen(val)+1);
2511 	  float point;
2512 	  int pos;
2513 	  while (sscanf(val, "%s %g%n", label, &point, &pos) == 2) {
2514 	    fprintf(fp, "\
2515 	lv2:scalePoint [ rdfs:label \"%s\"; rdf:value %g ] ;\n",
2516 		    label, point);
2517 	    val += pos;
2518 	  }
2519 	  free(label);
2520 	} else
2521 	  fprintf(stderr, "%s: bad port property '%s:%s'\n", PLUGIN_URI,
2522 		  key, val);
2523       }
2524     }
2525     fprintf(fp, "    ]");
2526   }
2527   // audio inputs
2528   for (int i = 0; i < n; i++, idx++)
2529     fprintf(fp, "%s [\n\
2530 	a lv2:InputPort ;\n\
2531 	a lv2:AudioPort ;\n\
2532 	lv2:index %d ;\n\
2533 	lv2:symbol \"in%d\" ;\n\
2534 	lv2:name \"in%d\" ;\n\
2535     ]", idx==0?"    lv2:port":" ,", idx, i, i);
2536   // audio outputs
2537   for (int i = 0; i < m; i++, idx++)
2538     fprintf(fp, "%s [\n\
2539 	a lv2:OutputPort ;\n\
2540 	a lv2:AudioPort ;\n\
2541 	lv2:index %d ;\n\
2542 	lv2:symbol \"out%d\" ;\n\
2543 	lv2:name \"out%d\" ;\n\
2544     ]", idx==0?"    lv2:port":" ,", idx, i, i);
2545   if (have_midi) {
2546     // midi input
2547     fprintf(fp, "%s [\n\
2548 	a lv2:InputPort ;\n\
2549 	a atom:AtomPort ;\n\
2550 	atom:bufferType atom:Sequence ;\n\
2551 	atom:supports <http://lv2plug.in/ns/ext/midi#MidiEvent> ;\n\
2552 	lv2:index %d ;\n\
2553 	lv2:symbol \"midiin\" ;\n\
2554 	lv2:name \"midiin\"\n\
2555     ]", idx==0?"    lv2:port":" ,", idx);
2556     idx++;
2557   }
2558   if (is_instr) {
2559     // polyphony control
2560     fprintf(fp, "%s [\n\
2561 	a lv2:InputPort ;\n\
2562 	a lv2:ControlPort ;\n\
2563 	lv2:index %d ;\n\
2564 	lv2:symbol \"polyphony\" ;\n\
2565 	lv2:name \"polyphony\" ;\n\
2566         lv2:portProperty epp:hasStrictBounds ;\n\
2567 #       lv2:portProperty epp:expensive ;\n\
2568         lv2:portProperty lv2:integer ;\n\
2569         epp:rangeSteps %d ;\n\
2570 	lv2:default %d ;\n\
2571 	lv2:minimum 1 ;\n\
2572 	lv2:maximum %d ;\n\
2573     ]", idx==0?"    lv2:port":" ,", idx, plugin->maxvoices-1,
2574       plugin->maxvoices>1?plugin->maxvoices/2:1,
2575       plugin->maxvoices);
2576     idx++;
2577 #if FAUST_MTS
2578     if (plugin->n_tunings > 0) {
2579       // tuning control
2580       fprintf(fp, "%s [\n\
2581 	a lv2:InputPort ;\n\
2582 	a lv2:ControlPort ;\n\
2583 	lv2:index %d ;\n\
2584 	lv2:symbol \"tuning\" ;\n\
2585 	lv2:name \"tuning\" ;\n\
2586         lv2:portProperty epp:hasStrictBounds ;\n\
2587         lv2:portProperty lv2:integer ;\n\
2588         epp:rangeSteps %d ;\n\
2589 	lv2:default 0 ;\n\
2590 	lv2:minimum 0 ;\n\
2591 	lv2:maximum %d ;\n",
2592 	idx==0?"    lv2:port":" ,", idx, plugin->n_tunings, plugin->n_tunings);
2593       for (int i = 0; i <= plugin->n_tunings; i++)
2594 	fprintf(fp, "\
2595 	lv2:scalePoint [ rdfs:label \"%s\"; rdf:value %d ] ;\n",
2596 		(i>0)?plugin->mts->tuning[i-1].name:"default", i);
2597       fprintf(fp, "    ]");
2598       idx++;
2599     }
2600 #endif
2601   }
2602   fprintf(fp, "\n.\n");
2603   return 0;
2604 }
2605 
2606 extern "C"
2607 LV2_SYMBOL_EXPORT
lv2_dyn_manifest_close(LV2_Dyn_Manifest_Handle handle)2608 void lv2_dyn_manifest_close(LV2_Dyn_Manifest_Handle handle)
2609 {
2610   LV2Plugin* plugin = (LV2Plugin*)handle;
2611   delete plugin;
2612 }
2613 
main()2614 int main()
2615 {
2616   LV2_Dyn_Manifest_Handle handle;
2617   LV2_Feature **features = { NULL };
2618   int res = lv2_dyn_manifest_open(&handle, features);
2619   if (res) return res;
2620   res = lv2_dyn_manifest_get_data(handle, stdout, PLUGIN_URI);
2621   return res;
2622 }
2623 
2624 #endif
2625