1 /************************************************************************
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 *************************************************************************/
9 /*******************BEGIN ARCHITECTURE SECTION (part 1/2)****************/
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.
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.
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/>.
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.
34 ************************************************************************
35 ************************************************************************/
50 #include "audio/dsp.h"
52 // On Intel set FZ (Flush to Zero) and DAZ (Denormals Are Zero)
53 // flags to avoid costly denormals
55 #include <xmmintrin.h>
57 #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8040)
59 #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8000)
62 #warning *** ladspa.cpp: NO SSE FLAG (denormals may slow things down) ***
63 #define AVOIDDENORMALS
66 #define sym(name) xsym(name)
67 #define xsym(name) #name
69 /******************************************************************************
70 *******************************************************************************
74 *******************************************************************************
75 *******************************************************************************/
79 /********************END ARCHITECTURE SECTION (part 1/2)****************/
81 /**************************BEGIN USER SECTION **************************/
85 /***************************END USER SECTION ***************************/
87 /*******************BEGIN ARCHITECTURE SECTION (part 2/2)***************/
89 //-----------------------------------portCollector--------------------------------------
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
95 //--------------------------------------------------------------------------------------
97 //--------------------------------useful constants--------------------------------------
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
;
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"
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"
126 class portCollector
: public UI
130 //--------------------------------------------------------------------------------------
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
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
140 string fPluginName
; // toplevel prefix used as plugin name
141 stack
<string
> fPrefix
; // current prefix for controls name
144 //--------------------------------------------------------------------------------------
145 string
simplify(const string
& src
)
158 // Skip the begin of the label "--foo-"
159 // until 3 '-' have been read
160 if (src
[i
]=='-') { level
++; }
164 // copy the content, but skip non alphnum
165 // and content in parenthesis
177 if (isalnum(src
[i
])) {
178 dst
+= tolower(src
[i
]);
185 // here we are inside parenthesis and
186 // we skip the content until we are back to
207 return (dst
.size() > 0) ? dst
:src
;
210 void addPortDescr(int type
, const char* label
, int hint
, float min
=0.0, float max
=0.0)
212 string fullname
= simplify(fPrefix
.top() + "-" + label
);
213 char * str
= strdup(fullname
.c_str());
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
;
223 void openAnyBox(const char* label
)
225 if (fPrefix
.size() == 0) {
226 // top level label is used as plugin name
232 if (label
&& label
[0]) {
233 s
= fPrefix
.top() + "-" + label
;
243 //--------------------------------Collect the audio ports-------------------------------
245 portCollector(int ins
, int outs
) : UI(), fInsCount(ins
), fOutsCount(outs
), fCtrlCount(0)
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;
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;
259 virtual ~portCollector() {}
261 //------------------------------Collect the control ports-------------------------------
263 virtual void addButton(const char* label
, float* zone
) {
264 addPortDescr(ICONTROL
, label
, LADSPA_HINT_TOGGLED
);
267 virtual void addToggleButton(const char* label
, float* zone
) {
268 addPortDescr(ICONTROL
, label
, LADSPA_HINT_TOGGLED
);
271 virtual void addCheckButton(const char* label
, float* zone
) {
272 addPortDescr(ICONTROL
, label
, LADSPA_HINT_TOGGLED
);
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
);
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
);
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
);
287 // -- passive widgets
289 virtual void addNumDisplay(const char* label
, float* zone
, int precision
) {
290 addPortDescr(OCONTROL
, label
, 0, -10000, +10000);
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
);
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
);
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
);
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
); }
307 virtual void closeBox() { fPrefix
.pop(); }
309 virtual void show() {}
310 virtual void run() {}
312 //---------------------------------Fill the LADSPA descriptor---------------------------
314 // generate an ID from a plugin name
315 int makeID (const char* s
) {
317 for (int i
= 0; s
[i
]; i
++) {
318 h
= (h
<< 3) + (s
[i
] & 7);
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
;
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";
343 //--------------------------------------portData----------------------------------------
345 // portData : a user interface used to associate the data buffers and the ports
347 //--------------------------------------------------------------------------------------
349 class portData
: public UI
354 //--------------------------------------------------------------------------------------
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
360 float* fPortZone
[MAXPORT
]; //
361 float* fPortData
[MAXPORT
];
363 //--------------------------------------------------------------------------------------
365 void addZone(float* zone
)
367 fPortZone
[fInsCount
+ fOutsCount
+ fCtrlCount
] = zone
;
373 //--------------------------------Collect the audio ports-------------------------------
375 portData(int ins
, int outs
) : UI(), fInsCount(ins
), fOutsCount(outs
), fCtrlCount(0) {};
376 virtual ~portData() {}
378 //------------------------------Collect the control zones-------------------------------
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
); }
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
); }
388 // -- passive widgets
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
); }
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() { }
401 virtual void show() {}
402 virtual void run() {}
404 //---------------------------------interaction with LADSPA------------------------------
406 void setPortData (unsigned long port
, LADSPA_Data
* data
) {
407 fPortData
[port
] = data
;
410 void updateCtrlZones() {
411 for (int i
= fInsCount
+fOutsCount
; i
< fInsCount
+fOutsCount
+fCtrlCount
; i
++) *fPortZone
[i
] = *fPortData
[i
];
414 float** getInputs() {
415 return &fPortData
[0];
418 float** getOutputs() {
419 return &fPortData
[fInsCount
];
423 //--------------------------------Faust-LADSPA plugin-----------------------------------
425 // Plugin structure, callbacks and LADSPA_descriptor(i) entry point
427 //--------------------------------------------------------------------------------------
429 LADSPA_Descriptor
* gDescriptor
= 0;
433 unsigned long fSampleRate
;
437 PLUGIN(unsigned long r
, portData
* d
, dsp
* p
) : fSampleRate(r
), fPortData(d
), fDsp(p
) {}
440 LADSPA_Handle
instantiate_method (const struct _LADSPA_Descriptor
* Descriptor
, unsigned long SampleRate
)
442 dsp
* p
= new mydsp();
443 portData
* d
= new portData(p
->getNumInputs(), p
->getNumOutputs());
445 p
->buildUserInterface(d
);
446 return new PLUGIN (SampleRate
, d
, p
);
449 void connect_method (LADSPA_Handle Instance
, unsigned long Port
, LADSPA_Data
* DataLocation
)
451 PLUGIN
* p
= (PLUGIN
*) Instance
;
452 p
->fPortData
->setPortData(Port
, DataLocation
);
455 void activate_method (LADSPA_Handle Instance
)
457 PLUGIN
* p
= (PLUGIN
*) Instance
;
458 p
->fDsp
->init(p
->fSampleRate
);
461 void run_method (LADSPA_Handle Instance
, unsigned long SampleCount
)
463 PLUGIN
* p
= (PLUGIN
*) Instance
;
464 p
->fPortData
->updateCtrlZones();
466 p
->fDsp
->compute(SampleCount
, p
->fPortData
->getInputs(), p
->fPortData
->getOutputs());
469 void deactivate_method (LADSPA_Handle Instance
)
472 void cleanup_method (LADSPA_Handle Instance
)
474 PLUGIN
* p
= (PLUGIN
*) Instance
;
480 //--------------------------------------------------------------------------------------
482 void init_descriptor(LADSPA_Descriptor
* descriptor
)
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";
491 descriptor
->ImplementationData
= 0;
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
;
504 //--------------------------------------------------------------------------------------
506 const LADSPA_Descriptor
* ladspa_descriptor(unsigned long Index
)
509 if (gDescriptor
== 0)
511 // allocate temporaries dsp and portCollector to build the plugin description
512 mydsp
* p
= new mydsp();
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
);
521 printf("Memory Error : unable to allocate the dsp object\n");
530 /********************END ARCHITECTURE SECTION (part 2/2)****************/