Refactoring of rec process "~" in faustexp.ml.
[Faustine.git] / interpretor / faust-0.9.47mr3 / architecture / ladspa.cpp
1 /************************************************************************
2
3 IMPORTANT NOTE : this file contains two clearly delimited sections :
4 the ARCHITECTURE section (in two parts) and the USER section. Each section
5 is governed by its own copyright and license. Please check individually
6 each section for license and copyright information.
7 *************************************************************************/
8
9 /*******************BEGIN ARCHITECTURE SECTION (part 1/2)****************/
10
11 /************************************************************************
12 FAUST Architecture File
13 Copyright (C) 2003-2011 GRAME, Centre National de Creation Musicale
14 ---------------------------------------------------------------------
15 This Architecture section is free software; you can redistribute it
16 and/or modify it under the terms of the GNU General Public License
17 as published by the Free Software Foundation; either version 3 of
18 the 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 General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; If not, see <http://www.gnu.org/licenses/>.
27
28 EXCEPTION : As a special exception, you may create a larger work
29 that contains this FAUST architecture section and distribute
30 that work under terms of your choice, so long as this FAUST
31 architecture section is not modified.
32
33
34 ************************************************************************
35 ************************************************************************/
36
37 #include <math.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <stdio.h>
41
42 #include <stack>
43 #include <string>
44 #include <iostream>
45 #include <map>
46
47 #include "ladspa.h"
48 #include "gui/GUI.h"
49 #include "misc.h"
50 #include "audio/dsp.h"
51
52 // On Intel set FZ (Flush to Zero) and DAZ (Denormals Are Zero)
53 // flags to avoid costly denormals
54 #ifdef __SSE__
55 #include <xmmintrin.h>
56 #ifdef __SSE2__
57 #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8040)
58 #else
59 #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8000)
60 #endif
61 #else
62 #warning *** ladspa.cpp: NO SSE FLAG (denormals may slow things down) ***
63 #define AVOIDDENORMALS
64 #endif
65
66 #define sym(name) xsym(name)
67 #define xsym(name) #name
68
69 /******************************************************************************
70 *******************************************************************************
71
72 VECTOR INTRINSICS
73
74 *******************************************************************************
75 *******************************************************************************/
76
77 <<includeIntrinsic>>
78
79 /********************END ARCHITECTURE SECTION (part 1/2)****************/
80
81 /**************************BEGIN USER SECTION **************************/
82
83 <<includeclass>>
84
85 /***************************END USER SECTION ***************************/
86
87 /*******************BEGIN ARCHITECTURE SECTION (part 2/2)***************/
88
89 //-----------------------------------portCollector--------------------------------------
90 //
91 // portCollector is passed to the buildUserInterface method of a dsp object
92 // in order to build a description of its inputs, outputs and control ports.
93 // This description is used to fill a LADSPA_Descriptor
94 //
95 //--------------------------------------------------------------------------------------
96
97 //--------------------------------useful constants--------------------------------------
98
99 #define MAXPORT 1024
100 static const int ICONTROL = LADSPA_PORT_INPUT|LADSPA_PORT_CONTROL;
101 static const int OCONTROL = LADSPA_PORT_OUTPUT|LADSPA_PORT_CONTROL;
102 static const int RANGE = LADSPA_PORT_INPUT|LADSPA_PORT_CONTROL;
103
104 static const char* inames[] = {
105 "input00", "input01", "input02", "input03", "input04",
106 "input05", "input06", "input07", "input08", "input09",
107 "input10", "input11", "input12", "input13", "input14",
108 "input15", "input16", "input17", "input18", "input19",
109 "input20", "input21", "input22", "input23", "input24",
110 "input25", "input26", "input27", "input28", "input29",
111 "input30", "input31", "input32", "input33", "input34",
112 "input35", "input36", "input37", "input38", "input39"
113 };
114
115 static const char* onames[] = {
116 "output00", "output01", "output02", "output03", "output04",
117 "output05", "output06", "output07", "output08", "output09",
118 "output10", "output11", "output12", "output13", "output14",
119 "output15", "output16", "output17", "output18", "output19",
120 "output20", "output21", "output22", "output23", "output24",
121 "output25", "output26", "output27", "output28", "output29",
122 "output30", "output31", "output32", "output33", "output34",
123 "output35", "output36", "output37", "output38", "output39"
124 };
125
126 class portCollector : public UI
127 {
128 private:
129
130 //--------------------------------------------------------------------------------------
131
132 const int fInsCount; // number of audio input ports
133 const int fOutsCount; // number of audio output ports
134 int fCtrlCount; // number of control ports
135
136 LADSPA_PortDescriptor fPortDescs[MAXPORT]; // table of port descriptors to be used in a LADSPA_Descriptor
137 const char* fPortNames[MAXPORT]; // table of port names to be used in a LADSPA_Descriptor
138 LADSPA_PortRangeHint fPortHints[MAXPORT]; // table of port hints to be used in a LADSPA_Descriptor
139
140 string fPluginName; // toplevel prefix used as plugin name
141 stack<string> fPrefix; // current prefix for controls name
142
143
144 //--------------------------------------------------------------------------------------
145 string simplify(const string& src)
146 {
147 int i=0;
148 int level=2;
149 string dst;
150
151 while (src[i] ) {
152
153 switch (level) {
154
155 case 0 :
156 case 1 :
157 case 2 :
158 // Skip the begin of the label "--foo-"
159 // until 3 '-' have been read
160 if (src[i]=='-') { level++; }
161 break;
162
163 case 3 :
164 // copy the content, but skip non alphnum
165 // and content in parenthesis
166 switch (src[i]) {
167 case '(' :
168 case '[' :
169 level++;
170 break;
171
172 case '-' :
173 dst += '-';
174 break;
175
176 default :
177 if (isalnum(src[i])) {
178 dst+= tolower(src[i]);
179 }
180
181 }
182 break;
183
184 default :
185 // here we are inside parenthesis and
186 // we skip the content until we are back to
187 // level 3
188 switch (src[i]) {
189
190 case '(' :
191 case '[' :
192 level++;
193 break;
194
195 case ')' :
196 case ']' :
197 level--;
198 break;
199
200 default :
201 break;
202 }
203
204 }
205 i++;
206 }
207 return (dst.size() > 0) ? dst :src;
208 }
209
210 void addPortDescr(int type, const char* label, int hint, float min=0.0, float max=0.0)
211 {
212 string fullname = simplify(fPrefix.top() + "-" + label);
213 char * str = strdup(fullname.c_str());
214
215 fPortDescs[fInsCount + fOutsCount + fCtrlCount] = type;
216 fPortNames[fInsCount + fOutsCount + fCtrlCount] = str;
217 fPortHints[fInsCount + fOutsCount + fCtrlCount].HintDescriptor = hint;
218 fPortHints[fInsCount + fOutsCount + fCtrlCount].LowerBound = min;
219 fPortHints[fInsCount + fOutsCount + fCtrlCount].UpperBound = max;
220 fCtrlCount++;
221 }
222
223 void openAnyBox(const char* label)
224 {
225 if (fPrefix.size() == 0) {
226 // top level label is used as plugin name
227 fPluginName = label;
228 fPrefix.push(label);
229
230 } else {
231 string s;
232 if (label && label[0]) {
233 s = fPrefix.top() + "-" + label;
234 } else {
235 s = fPrefix.top();
236 }
237 fPrefix.push(s);
238 }
239 }
240
241 public:
242
243 //--------------------------------Collect the audio ports-------------------------------
244
245 portCollector(int ins, int outs) : UI(), fInsCount(ins), fOutsCount(outs), fCtrlCount(0)
246 {
247 for (int i = 0; i < ins; i++) {
248 fPortDescs[i] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
249 fPortNames[i] = inames[i];
250 fPortHints[i].HintDescriptor = 0;
251 }
252 for (int j = 0; j < outs; j++) {
253 fPortDescs[ins + j] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
254 fPortNames[ins + j] = onames[j];
255 fPortHints[ins + j].HintDescriptor = 0;
256 }
257 };
258
259 virtual ~portCollector() {}
260
261 //------------------------------Collect the control ports-------------------------------
262
263 virtual void addButton(const char* label, float* zone) {
264 addPortDescr(ICONTROL, label, LADSPA_HINT_TOGGLED);
265 }
266
267 virtual void addToggleButton(const char* label, float* zone) {
268 addPortDescr(ICONTROL, label, LADSPA_HINT_TOGGLED);
269 }
270
271 virtual void addCheckButton(const char* label, float* zone) {
272 addPortDescr(ICONTROL, label, LADSPA_HINT_TOGGLED);
273 }
274
275 virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step) {
276 addPortDescr(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max);
277 }
278
279 virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step) {
280 addPortDescr(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max);
281 }
282
283 virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step) {
284 addPortDescr(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max);
285 }
286
287 // -- passive widgets
288
289 virtual void addNumDisplay(const char* label, float* zone, int precision) {
290 addPortDescr(OCONTROL, label, 0, -10000, +10000);
291 }
292 virtual void addTextDisplay(const char* label, float* zone, const char* names[], float min, float max) {
293 addPortDescr(OCONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max);
294 }
295 virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) {
296 addPortDescr(OCONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max);
297 }
298 virtual void addVerticalBargraph(const char* label, float* zone, float min, float max){
299 addPortDescr(OCONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max);
300 }
301
302 virtual void openFrameBox(const char* label) { openAnyBox(label); }
303 virtual void openTabBox(const char* label) { openAnyBox(label); }
304 virtual void openHorizontalBox(const char* label) { openAnyBox(label); }
305 virtual void openVerticalBox(const char* label) { openAnyBox(label); }
306
307 virtual void closeBox() { fPrefix.pop(); }
308
309 virtual void show() {}
310 virtual void run() {}
311
312 //---------------------------------Fill the LADSPA descriptor---------------------------
313
314 // generate an ID from a plugin name
315 int makeID (const char* s) {
316 int h = 0;
317 for (int i = 0; s[i]; i++) {
318 h = (h << 3) + (s[i] & 7);
319 }
320 return 1+h%1000;
321 }
322
323 // fill a ladspa descriptor with the information collected on ports
324 void fillPortDescription (LADSPA_Descriptor * descriptor) {
325 const char* name = sym(mydsp);
326 descriptor->PortCount = fCtrlCount+fInsCount+fOutsCount;
327 descriptor->PortDescriptors = fPortDescs;
328 descriptor->PortNames = fPortNames;
329 descriptor->PortRangeHints = fPortHints;
330
331 descriptor->Label = strdup(name);
332 descriptor->UniqueID = makeID(name);
333 // descriptor->Label = strdup(fPluginName.c_str());
334 // descriptor->UniqueID = makeID(fPluginName.c_str());
335 descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE;
336 descriptor->Name = name;
337 // descriptor->Name = strdup(fPluginName.c_str());
338 descriptor->Maker = "undefined";
339 descriptor->Copyright = "undefined";
340 }
341 };
342
343 //--------------------------------------portData----------------------------------------
344 //
345 // portData : a user interface used to associate the data buffers and the ports
346 //
347 //--------------------------------------------------------------------------------------
348
349 class portData : public UI
350 {
351
352 private:
353
354 //--------------------------------------------------------------------------------------
355
356 const int fInsCount; // number of audio input ports
357 const int fOutsCount; // number of audio output ports
358 int fCtrlCount; // number of control ports
359
360 float* fPortZone[MAXPORT]; //
361 float* fPortData[MAXPORT];
362
363 //--------------------------------------------------------------------------------------
364
365 void addZone(float* zone)
366 {
367 fPortZone[fInsCount + fOutsCount + fCtrlCount] = zone;
368 fCtrlCount++;
369 }
370
371 public:
372
373 //--------------------------------Collect the audio ports-------------------------------
374
375 portData(int ins, int outs) : UI(), fInsCount(ins), fOutsCount(outs), fCtrlCount(0) {};
376 virtual ~portData() {}
377
378 //------------------------------Collect the control zones-------------------------------
379
380 virtual void addButton(const char* label, float* zone) { addZone(zone); }
381 virtual void addToggleButton(const char* label, float* zone) { addZone(zone); }
382 virtual void addCheckButton(const char* label, float* zone) { addZone(zone); }
383
384 virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step) { addZone(zone); }
385 virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step) { addZone(zone); }
386 virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step) { addZone(zone); }
387
388 // -- passive widgets
389
390 virtual void addNumDisplay(const char* label, float* zone, int precision) { addZone(zone); }
391 virtual void addTextDisplay(const char* label, float* zone, const char* names[], float min, float max) { addZone(zone); }
392 virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) { addZone(zone); }
393 virtual void addVerticalBargraph(const char* label, float* zone, float min, float max) { addZone(zone); }
394
395 virtual void openFrameBox(const char* label) { }
396 virtual void openTabBox(const char* label) { }
397 virtual void openHorizontalBox(const char* label) { }
398 virtual void openVerticalBox(const char* label) { }
399 virtual void closeBox() { }
400
401 virtual void show() {}
402 virtual void run() {}
403
404 //---------------------------------interaction with LADSPA------------------------------
405
406 void setPortData (unsigned long port, LADSPA_Data* data) {
407 fPortData[port] = data;
408 }
409
410 void updateCtrlZones() {
411 for (int i = fInsCount+fOutsCount; i < fInsCount+fOutsCount+fCtrlCount; i++) *fPortZone[i] = *fPortData[i];
412 }
413
414 float** getInputs() {
415 return &fPortData[0];
416 }
417
418 float** getOutputs() {
419 return &fPortData[fInsCount];
420 }
421 };
422
423 //--------------------------------Faust-LADSPA plugin-----------------------------------
424 //
425 // Plugin structure, callbacks and LADSPA_descriptor(i) entry point
426 //
427 //--------------------------------------------------------------------------------------
428
429 LADSPA_Descriptor* gDescriptor = 0;
430
431 struct PLUGIN
432 {
433 unsigned long fSampleRate;
434 portData* fPortData;
435 dsp* fDsp;
436
437 PLUGIN(unsigned long r, portData* d, dsp* p) : fSampleRate(r), fPortData(d), fDsp(p) {}
438 };
439
440 LADSPA_Handle instantiate_method (const struct _LADSPA_Descriptor * Descriptor, unsigned long SampleRate)
441 {
442 dsp* p = new mydsp();
443 portData* d = new portData(p->getNumInputs(), p->getNumOutputs());
444
445 p->buildUserInterface(d);
446 return new PLUGIN (SampleRate, d, p);
447 }
448
449 void connect_method (LADSPA_Handle Instance, unsigned long Port, LADSPA_Data * DataLocation)
450 {
451 PLUGIN* p = (PLUGIN*) Instance;
452 p->fPortData->setPortData(Port, DataLocation);
453 }
454
455 void activate_method (LADSPA_Handle Instance)
456 {
457 PLUGIN* p = (PLUGIN*) Instance;
458 p->fDsp->init(p->fSampleRate);
459 }
460
461 void run_method (LADSPA_Handle Instance, unsigned long SampleCount)
462 {
463 PLUGIN* p = (PLUGIN*) Instance;
464 p->fPortData->updateCtrlZones();
465 AVOIDDENORMALS;
466 p->fDsp->compute(SampleCount, p->fPortData->getInputs(), p->fPortData->getOutputs());
467 }
468
469 void deactivate_method (LADSPA_Handle Instance)
470 {}
471
472 void cleanup_method (LADSPA_Handle Instance)
473 {
474 PLUGIN* p = (PLUGIN*) Instance;
475 delete p->fPortData;
476 delete p->fDsp;
477 delete p;
478 }
479
480 //--------------------------------------------------------------------------------------
481
482 void init_descriptor(LADSPA_Descriptor* descriptor)
483 {
484 descriptor->UniqueID = 123456;
485 descriptor->Label = "none";
486 descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE;
487 descriptor->Name = "none";
488 descriptor->Maker = "Yann Orlarey";
489 descriptor->Copyright = "GPL";
490
491 descriptor->ImplementationData = 0;
492
493 // description des methods
494 descriptor->instantiate = instantiate_method;
495 descriptor->connect_port = connect_method;
496 descriptor->activate = activate_method;
497 descriptor->run = run_method;
498 descriptor->run_adding = 0;
499 descriptor->set_run_adding_gain = 0;
500 descriptor->deactivate = deactivate_method;
501 descriptor->cleanup = cleanup_method;
502 }
503
504 //--------------------------------------------------------------------------------------
505
506 const LADSPA_Descriptor * ladspa_descriptor(unsigned long Index)
507 {
508 if (Index == 0) {
509 if (gDescriptor == 0)
510 {
511 // allocate temporaries dsp and portCollector to build the plugin description
512 mydsp* p = new mydsp();
513 if (p) {
514 portCollector* c=new portCollector(p->getNumInputs(), p->getNumOutputs());
515 p->buildUserInterface(c);
516 gDescriptor = new LADSPA_Descriptor;
517 init_descriptor(gDescriptor);
518 c->fillPortDescription(gDescriptor);
519 delete p;
520 } else {
521 printf("Memory Error : unable to allocate the dsp object\n");
522 }
523 }
524 return gDescriptor;
525 } else {
526 return NULL;
527 }
528 }
529
530 /********************END ARCHITECTURE SECTION (part 2/2)****************/
531
532