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