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 ************************************************************************
13 FAUST Architecture File
14 Copyright (C) 2007-2011 Remy Muller & Julius Smith
16 ----------------------------BSD License------------------------------
17 Redistribution and use in source and binary forms, with or without
18 modification, are permitted provided that the following conditions
21 * Redistributions of source code must retain the above copyright
22 notice, this list of conditions and the following disclaimer.
23 * Redistributions in binary form must reproduce the above
24 copyright notice, this list of conditions and the following
25 disclaimer in the documentation and/or other materials provided
26 with the distribution.
27 * Neither the name of Remy Muller or Julius Smith or of its
28 contributors may be used to endorse or promote products derived
29 from this software without specific prior written permission.
31 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
34 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
35 COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
36 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
37 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
39 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
41 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
42 OF THE POSSIBILITY OF SUCH DAMAGE.
44 ----------------------------VST SDK----------------------------------
45 In order to compile a VST (TM) plugin with this architecture file
46 you will need the proprietary VST SDK from Steinberg. Please check
47 the corresponding license.
49 ************************************************************************
50 ************************************************************************/
54 /********************************************************************
55 * VST-2.4 wrapper for the FAUST language.
57 * Usage: faust -a vst2p4.cpp myfaustprog.dsp
59 * By Julius Smith (http://ccrma.stanford.edu/~jos/), based on
60 * vst.cpp by remy muller remy.muller@ircam.fr
61 * http://www.smartelectronix.com/~mdsp/.
62 * Essentially, vst.cpp was edited to look more like the "again"
63 * programming sample that comes with the VST-2.4 SDK from Steinberg.
66 * Relies on automatically generated slider GUI for VST plugins.
67 * - Horizontal and vertical sliders mapped to "vstSlider"
68 * - Numeric Entries similarly converted to "vstSlider"
69 * - No support for bar graphs or additional numeric and text displays
70 * - Tested on the Muse Receptor Pro 1.0, System Version 1.6.20070717,
71 * using Visual C++ 2008 Express Edition
72 * (part of the Microsoft Visual Studio 2008, Beta 2)
74 * http://ccrma.stanford.edu/realsimple/faust/Generating_VST_Plugin_Faust.html
77 * Copyright (C) 2003-2007 GRAME, Centre National de Creation Musicale
78 * http://www.grame.fr/
80 ********************************************************************/
100 // There is a bug with powf() when cross compiling with mingw
101 // the following macro avoid the problem
103 #define powf(x,y) pow(x,y)
104 #define expf(x) exp(x)
107 // On Intel set FZ (Flush to Zero) and DAZ (Denormals Are Zero)
108 // flags to avoid costly denormals
110 #include <xmmintrin.h>
112 #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8040)
114 #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8000)
117 #define AVOIDDENORMALS
120 struct Meta
: std::map
<std::string
, std::string
>
122 void declare(const char* key
, const char* value
)
124 (*this)[key
] = value
;
129 //-------------------------------------------------------------------
130 // Generic min and max using c++ inline
131 //-------------------------------------------------------------------
133 inline int max (unsigned int a
, unsigned int b
) { return (a
>b
) ? a
: b
; }
134 inline int max (int a
, int b
) { return (a
>b
) ? a
: b
; }
136 inline long max (long a
, long b
) { return (a
>b
) ? a
: b
; }
137 inline long max (int a
, long b
) { return (a
>b
) ? a
: b
; }
138 inline long max (long a
, int b
) { return (a
>b
) ? a
: b
; }
140 inline float max (float a
, float b
) { return (a
>b
) ? a
: b
; }
141 inline float max (int a
, float b
) { return (a
>b
) ? a
: b
; }
142 inline float max (float a
, int b
) { return (a
>b
) ? a
: b
; }
143 inline float max (long a
, float b
) { return (a
>b
) ? a
: b
; }
144 inline float max (float a
, long b
) { return (a
>b
) ? a
: b
; }
146 inline double max (double a
, double b
) { return (a
>b
) ? a
: b
; }
147 inline double max (int a
, double b
) { return (a
>b
) ? a
: b
; }
148 inline double max (double a
, int b
) { return (a
>b
) ? a
: b
; }
149 inline double max (long a
, double b
) { return (a
>b
) ? a
: b
; }
150 inline double max (double a
, long b
) { return (a
>b
) ? a
: b
; }
151 inline double max (float a
, double b
) { return (a
>b
) ? a
: b
; }
152 inline double max (double a
, float b
) { return (a
>b
) ? a
: b
; }
154 inline int min (int a
, int b
) { return (a
<b
) ? a
: b
; }
156 inline long min (long a
, long b
) { return (a
<b
) ? a
: b
; }
157 inline long min (int a
, long b
) { return (a
<b
) ? a
: b
; }
158 inline long min (long a
, int b
) { return (a
<b
) ? a
: b
; }
160 inline float min (float a
, float b
) { return (a
<b
) ? a
: b
; }
161 inline float min (int a
, float b
) { return (a
<b
) ? a
: b
; }
162 inline float min (float a
, int b
) { return (a
<b
) ? a
: b
; }
163 inline float min (long a
, float b
) { return (a
<b
) ? a
: b
; }
164 inline float min (float a
, long b
) { return (a
<b
) ? a
: b
; }
166 inline double min (double a
, double b
) { return (a
<b
) ? a
: b
; }
167 inline double min (int a
, double b
) { return (a
<b
) ? a
: b
; }
168 inline double min (double a
, int b
) { return (a
<b
) ? a
: b
; }
169 inline double min (long a
, double b
) { return (a
<b
) ? a
: b
; }
170 inline double min (double a
, long b
) { return (a
<b
) ? a
: b
; }
171 inline double min (float a
, double b
) { return (a
<b
) ? a
: b
; }
172 inline double min (double a
, float b
) { return (a
<b
) ? a
: b
; }
174 // abs is now predefined
175 //template<typename T> T abs (T a) { return (a<T(0)) ? -a : a; }
177 inline int lsr (int x
, int n
) { return int(((unsigned int)x
) >> n
); }
179 inline int int2pow2 (int x
) { int r
=0; while ((1<<r
)<x
) r
++; return r
; }
181 /******************************************************************************
182 *******************************************************************************
186 *******************************************************************************
187 *******************************************************************************/
189 //inline void *aligned_calloc(size_t nmemb, size_t size) { return (void*)((unsigned)(calloc((nmemb*size)+15,sizeof(char)))+15 & 0xfffffff0); }
190 //inline void *aligned_calloc(size_t nmemb, size_t size) { return (void*)((size_t)(calloc((nmemb*size)+15,sizeof(char)))+15 & ~15); }
194 /******************************************************************************
195 *******************************************************************************
199 *******************************************************************************
200 *******************************************************************************/
208 UI() : fStopped(false) {}
211 virtual void addButton(const char* label
, float* zone
) = 0;
212 virtual void addToggleButton(const char* label
, float* zone
) = 0;
213 virtual void addCheckButton(const char* label
, float* zone
) = 0;
214 virtual void addVerticalSlider(const char* label
, float* zone
, float init
, float min
, float max
, float step
) = 0;
215 virtual void addHorizontalSlider(const char* label
, float* zone
, float init
, float min
, float max
, float step
) = 0;
216 virtual void addNumEntry(const char* label
, float* zone
, float init
, float min
, float max
, float step
) = 0;
218 virtual void addNumDisplay(const char* label
, float* zone
, int precision
) = 0;
219 virtual void addTextDisplay(const char* label
, float* zone
, char* names
[], float min
, float max
) = 0;
220 virtual void addHorizontalBargraph(const char* label
, float* zone
, float min
, float max
) = 0;
221 virtual void addVerticalBargraph(const char* label
, float* zone
, float min
, float max
) = 0;
223 virtual void openFrameBox(const char* label
) = 0;
224 virtual void openTabBox(const char* label
) = 0;
225 virtual void openHorizontalBox(const char* label
) = 0;
226 virtual void openVerticalBox(const char* label
) = 0;
227 virtual void closeBox() = 0;
229 virtual void run() {};
231 void stop() { fStopped
= true; }
232 bool stopped() { return fStopped
; }
234 virtual void declare(float* zone
, const char* key
, const char* value
) {}
238 /******************************************************************************
239 *******************************************************************************
243 *******************************************************************************
244 *******************************************************************************/
248 //----------------------------------------------------------------
249 // Base dsp class for this architecture
250 //----------------------------------------------------------------
262 virtual int getNumInputs() = 0;
263 virtual int getNumOutputs() = 0;
264 virtual void buildUserInterface(UI
* interface
) = 0;
265 virtual void init(int samplingRate
) = 0;
266 virtual void compute(int len
, float** inputs
, float** outputs
) = 0;
269 /********************END ARCHITECTURE SECTION (part 1/2)****************/
271 /**************************BEGIN USER SECTION **************************/
275 /***************************END USER SECTION ***************************/
277 /*******************BEGIN ARCHITECTURE SECTION (part 2/2)***************/
280 /******************************************************************************
284 ******************************************************************************/
286 #include "audioeffectx.h"
290 class Faust
: public AudioEffectX
296 char programName
[kVstMaxProgNameLen
+ 1];
300 Faust(audioMasterCallback audioMaster
, mydsp
* dspi
, vstUI
* dspUIi
);
303 virtual void processReplacing(float **inputs
, float **outputs
, VstInt32 sampleFrames
);
305 virtual void setProgramName(char *name
);
306 virtual void getProgramName(char *name
);
308 virtual void setParameter(VstInt32 index
, float value
);
309 virtual float getParameter(VstInt32 index
);
310 virtual void getParameterLabel(VstInt32 index
, char *label
);
311 virtual void getParameterDisplay(VstInt32 index
, char *text
);
312 virtual void getParameterName(VstInt32 index
, char *text
);
314 virtual void setSampleRate(float sampleRate
);
316 virtual bool getEffectName (char* name
);
317 virtual bool getVendorString (char* text
);
318 virtual bool getProductString (char* text
);
319 virtual VstInt32
getVendorVersion ();
321 virtual bool getInputProperties (VstInt32 index
, VstPinProperties
* properties
);
322 virtual bool getOutputProperties (VstInt32 index
, VstPinProperties
* properties
);
325 /*--------------------------------------------------------------------------*/
331 float range(float min
, float max
, float val
)
332 { // VST parameters are normalized in the range [0;1]
333 val
= min
+ val
* (max
- min
);
334 return (val
< min
) ? min
: (val
> max
) ? max
: val
;
338 vstUIObject(const char* label
, float* zone
):fLabel(label
),fZone(zone
) {}
339 virtual ~vstUIObject() {}
341 virtual void GetName(char *text
){std::strcpy(text
,fLabel
.c_str());}
342 virtual void SetValue(double f
) {*fZone
= range(0.0f
,1.0f
,(float)f
);}
343 virtual float GetValue() {return *fZone
;}
344 virtual void GetDisplay(char *text
){std::sprintf(text
,"%f",*fZone
);}
346 { /* returns the sum of all the ASCII characters contained in the parameter's label */
349 for(i
=0,acc
= 0;i
<fLabel
.length();i
++) acc
+= (fLabel
.c_str())[i
];
354 /*--------------------------------------------------------------------------*/
355 class vstToggleButton
: public vstUIObject
{
359 vstToggleButton(const char* label
, float* zone
):vstUIObject(label
,zone
) {}
360 virtual ~vstToggleButton() {}
361 virtual float GetValue() {return *fZone
;}
362 virtual void SetValue(double f
) {*fZone
= (f
>0.5f
)?1.0f
:0.0f
;}
363 virtual void GetDisplay(char *text
){(*fZone
>0.5f
)? std::strcpy(text
,"ON"): std::strcpy(text
,"OFF");}
366 /*--------------------------------------------------------------------------*/
367 class vstCheckButton
: public vstUIObject
{
371 vstCheckButton(const char* label
, float* zone
):vstUIObject(label
,zone
) {}
372 virtual ~vstCheckButton() {}
373 virtual float GetValue() {return *fZone
;}
374 virtual void SetValue(double f
) {*fZone
= (f
>0.5f
)?1.0f
:0.0f
;}
375 virtual void GetDisplay(char *text
){(*fZone
>0.5f
)? std::strcpy(text
,"ON"): std::strcpy(text
,"OFF");}
378 /*--------------------------------------------------------------------------*/
379 class vstButton
: public vstUIObject
{
383 vstButton(const char* label
, float* zone
):vstUIObject(label
,zone
) {}
384 virtual ~vstButton() {}
385 virtual float GetValue() {return *fZone
;}
386 virtual void SetValue(double f
) {*fZone
= (f
>0.5f
)?1.0f
:0.0f
;}
387 virtual void GetDisplay(char *text
){(*fZone
>0.5f
)? std::strcpy(text
,"ON"): std::strcpy(text
,"OFF");}
390 /*--------------------------------------------------------------------------*/
391 class vstSlider
: public vstUIObject
{
402 vstSlider(const char* label
, float* zone
, float init
, float min
, float max
, float step
)
403 :vstUIObject(label
,zone
), fInit(init
), fMin(min
), fMax(max
),fStep(step
) {}
404 virtual ~vstSlider() {}
406 virtual float GetValue() {return (*fZone
-fMin
)/(fMax
-fMin
);} // normalize
407 virtual void SetValue(double f
) {*fZone
= range(fMin
,fMax
,(float)f
);} // expand
410 /*--------------------------------------------------------------------------*/
411 class vstUI
: public UI
415 vector
<vstUIObject
*> fUITable
;
422 for (vector
<vstUIObject
*>::iterator iter
= fUITable
.begin(); iter
!= fUITable
.end(); iter
++) delete *iter
;
425 void addButton(const char* label
, float* zone
) {fUITable
.push_back(new vstButton(label
, zone
));}
427 void addToggleButton(const char* label
, float* zone
) {fUITable
.push_back(new vstToggleButton(label
, zone
));}
429 void addCheckButton(const char* label
, float* zone
) {fUITable
.push_back(new vstCheckButton(label
, zone
));}
431 void addVerticalSlider(const char* label
, float* zone
, float init
, float min
, float max
, float step
)
433 fUITable
.push_back(new vstSlider(label
, zone
, init
, min
, max
, step
));
436 void addHorizontalSlider(const char* label
, float* zone
, float init
, float min
, float max
, float step
)
438 fUITable
.push_back(new vstSlider(label
, zone
, init
, min
, max
, step
));
441 void addNumEntry(const char* label
, float* zone
, float init
, float min
, float max
, float step
)
442 { /* Number entries converted to horizontal sliders */
443 fUITable
.push_back(new vstSlider(label
, zone
, init
, min
, max
, step
));
446 void openFrameBox(const char* label
) {}
447 void openTabBox(const char* label
) {}
448 void openHorizontalBox(const char* label
) {}
449 void openVerticalBox(const char* label
) {}
452 void SetValue(VstInt32 index
, double f
) {assert(index
<fUITable
.size()); fUITable
[index
]->SetValue(f
);}
453 float GetValue(VstInt32 index
) {assert(index
<fUITable
.size()); return fUITable
[index
]->GetValue();}
454 void GetDisplay(VstInt32 index
, char *text
) {assert(index
<fUITable
.size()); fUITable
[index
]->GetDisplay(text
);}
455 void GetName(VstInt32 index
, char *text
) {assert(index
<fUITable
.size()); fUITable
[index
]->GetName(text
);}
456 long GetNumParams() {return fUITable
.size();}
459 /* Creates a (unique?)id by summing all the parameter's labels,
460 * then wrapping it in the range [0;maxNumberOfId] and adding
461 * this number to the offset made by the Four Character ID: 'FAUS'
464 const long maxNumberOfId
= 128;
465 long baseid
= 'FAUS';
467 for(int i
=0;i
<fUITable
.size();i
++) id
+= fUITable
[i
]->GetID();
468 return baseid
+ id
% maxNumberOfId
;
472 void addNumDisplay(const char* label
, float* zone
, int precision
){}
473 void addTextDisplay(const char* label
, float* zone
, char* names
[], float min
, float max
){}
474 void addHorizontalBargraph(const char* label
, float* zone
, float min
, float max
){}
475 void addVerticalBargraph(const char* label
, float* zone
, float min
, float max
){}
478 //-----------------------------------------------------------------------------
479 #define NUM_PROGRAMS 0
481 AudioEffect
* createEffectInstance (audioMasterCallback audioMaster
)
483 // The dsp and its UI need to be allocated now because
484 // AudioEffectX wants the no. parameters available as an instance argument:
485 mydsp
* dspi
= new mydsp();
486 vstUI
* dspUIi
= new vstUI();
487 dspi
->buildUserInterface(dspUIi
);
488 return new Faust(audioMaster
,dspi
,dspUIi
);
491 Faust::Faust(audioMasterCallback audioMaster
, mydsp
* dspi
, vstUI
* dspUIi
)
492 : AudioEffectX(audioMaster
, NUM_PROGRAMS
, dspUIi
->GetNumParams())
494 // Copy the pointers to dsp and dspUI instances and take them over
495 // (we'll also deallocate):
498 dsp
->init(long(getSampleRate()));
499 meta
["name"] = "FaustFx";
500 mydsp::metadata(&meta
);
501 setNumInputs(dsp
->getNumInputs());
502 setNumOutputs(dsp
->getNumOutputs());
503 setUniqueID(dspUI
->makeID());
504 canProcessReplacing();
506 vst_strncpy(programName
, "Default", kVstMaxProgNameLen
); // default program name
509 //----------------------------------------------------------------------------
513 if (dspUI
) delete dspUI
;
516 //-------------------------------------------------------------------------------------------------------
517 void Faust::setProgramName (char* name
)
519 // this template does not use programs yet - just say "Default":
520 vst_strncpy (programName
, name
, kVstMaxProgNameLen
);
523 //-----------------------------------------------------------------------------
524 void Faust::getProgramName(char *name
)
526 vst_strncpy (name
, programName
, kVstMaxProgNameLen
);
529 //-----------------------------------------------------------------------------
530 void Faust::setParameter(VstInt32 index
, float value
)
533 dspUI
->SetValue(index
,value
);
536 //-----------------------------------------------------------------------------
537 float Faust::getParameter(VstInt32 index
)
540 return dspUI
->GetValue(index
);
544 //-----------------------------------------------------------------------------
545 void Faust::getParameterName(VstInt32 index
, char *label
)
548 dspUI
->GetName(index
,label
); // parameter name, including units
550 vst_strncpy (label
, "IndexOutOfRange", kVstMaxParamStrLen
);
552 //-----------------------------------------------------------------------------
553 void Faust::getParameterDisplay(VstInt32 index
, char *text
)
556 dspUI
->GetDisplay(index
,text
); // displayed float value as text
558 vst_strncpy (text
, "IndexOutOfRange", kVstMaxParamStrLen
);
560 //-----------------------------------------------------------------------------
561 void Faust::getParameterLabel(VstInt32 index
, char *label
)
563 vst_strncpy (label
, "", kVstMaxParamStrLen
); // parameter units in Name
566 //-----------------------------------------------------------------------------
567 void Faust::setSampleRate(float sampleRate
)
570 AudioEffect::setSampleRate(sampleRate
);
571 dsp
->init(long(getSampleRate()));
574 //-----------------------------------------------------------------------------------------
575 bool Faust::getEffectName (char* text
)
577 vst_strncpy (text
, meta
["name"].c_str(), kVstMaxProductStrLen
);
581 //-----------------------------------------------------------------------------------------
582 bool Faust::getVendorString (char* text
)
584 if (meta
.count("author") > 0) {
585 vst_strncpy (text
, meta
["author"].c_str(), kVstMaxVendorStrLen
);
592 //-----------------------------------------------------------------------------------------
593 bool Faust::getProductString (char* text
)
595 vst_strncpy (text
, meta
["name"].c_str(), kVstMaxProductStrLen
);
599 //-----------------------------------------------------------------------------------------
600 VstInt32
Faust::getVendorVersion ()
605 //-----------------------------------------------------------------------------
606 void Faust::processReplacing(float **inputs
, float **outputs
, VstInt32 sampleFrames
)
609 dsp
->compute(sampleFrames
, inputs
, outputs
);
612 //-----------------------------------------------------------------------------------------
613 bool Faust::getInputProperties (VstInt32 index
, VstPinProperties
* properties
)
615 if(index
>=0 && index
<dsp
->getNumInputs())
617 sprintf (properties
->label
, "Grame Faust DSP input: %d",index
);
618 sprintf (properties
->shortLabel
, "In %d",index
);
619 properties
->flags
= kVstPinIsActive
;
620 if (dsp
->getNumInputs() == 2) {
621 properties
->flags
|= kVstPinIsStereo
;
629 //-----------------------------------------------------------------------------------------
630 bool Faust::getOutputProperties (VstInt32 index
, VstPinProperties
* properties
)
632 if(index
>=0 && index
<dsp
->getNumOutputs())
634 sprintf (properties
->label
, "Grame Faust DSP output: %d",index
);
635 sprintf (properties
->shortLabel
, "Out %d",index
);
636 properties
->flags
= kVstPinIsActive
;
637 if (dsp
->getNumOutputs() == 2) {
638 properties
->flags
|= kVstPinIsStereo
;
646 /********************END ARCHITECTURE SECTION (part 2/2)****************/