OOP initial commit.
[Faustine.git] / interpretor / faust-0.9.47mr3 / architecture / vst.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) 2004-2011 Remy Muller
14 All rights reserved.
15 ----------------------------BSD License------------------------------
16 Redistribution and use in source and binary forms, with or without
17 modification, are permitted provided that the following conditions
18 are met:
19
20 * Redistributions of source code must retain the above copyright
21 notice, this list of conditions and the following disclaimer.
22 * Redistributions in binary form must reproduce the above
23 copyright notice, this list of conditions and the following
24 disclaimer in the documentation and/or other materials provided
25 with the distribution.
26 * Neither the name of Remy Muller nor the names of its
27 contributors may be used to endorse or promote products derived
28 from this software without specific prior written permission.
29
30 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
33 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
34 COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
35 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
36 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
41 OF THE POSSIBILITY OF SUCH DAMAGE.
42
43 ----------------------------VST SDK----------------------------------
44 In order to compile a VST (TM) plugin with this architecture file
45 you will need the proprietary VST SDK from Steinberg. Please check
46 the corresponding license.
47
48 ************************************************************************
49 ************************************************************************/
50
51
52 /********************************************************************
53 * VST wrapper for the FAUST language.
54 * Author: remy muller remy.muller@ircam.fr
55 * http://www.smartelectronix.com/~mdsp/
56 *
57 * FAUST
58 * Copyright (C) 2003-2004 GRAME, Centre National de Creation Musicale
59 * http://www.grame.fr/
60 *
61 ********************************************************************/
62
63 #include <stdlib.h>
64 #include <stdlib.h>
65 #include <stdio.h>
66 #include <string.h>
67 #include <limits.h>
68 #include <math.h>
69 #include <errno.h>
70 #include <time.h>
71 //#include <unistd.h>
72 #include <fcntl.h>
73 #include <assert.h>
74 #include <string>
75 #include <vector>
76 #include <math.h>
77
78 using namespace std ;
79
80 // There is a bug with powf() when cross compiling with mingw
81 // the following macro avoid the problem
82 #ifdef WIN32
83 #define powf(x,y) pow(x,y)
84 #define expf(x) exp(x)
85 #endif
86
87 // On Intel set FZ (Flush to Zero) and DAZ (Denormals Are Zero)
88 // flags to avoid costly denormals
89 #ifdef __SSE__
90 #include <xmmintrin.h>
91 #ifdef __SSE2__
92 #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8040)
93 #else
94 #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8000)
95 #endif
96 #else
97 #define AVOIDDENORMALS
98 #endif
99
100 struct Meta
101 {
102 void declare (const char* key, const char* value) { }
103 };
104
105
106 #ifdef __GNUC__
107
108 //-------------------------------------------------------------------
109 // Generic min and max using gcc extensions
110 //-------------------------------------------------------------------
111
112 #define max(x,y) ((x)>?(y))
113 #define min(x,y) ((x)<?(y))
114
115 //abs(x) should be already predefined
116
117 #else
118
119 //-------------------------------------------------------------------
120 // Generic min and max using c++ inline
121 //-------------------------------------------------------------------
122
123 inline int max (unsigned int a, unsigned int b) { return (a>b) ? a : b; }
124 inline int max (int a, int b) { return (a>b) ? a : b; }
125
126 inline long max (long a, long b) { return (a>b) ? a : b; }
127 inline long max (int a, long b) { return (a>b) ? a : b; }
128 inline long max (long a, int b) { return (a>b) ? a : b; }
129
130 inline float max (float a, float b) { return (a>b) ? a : b; }
131 inline float max (int a, float b) { return (a>b) ? a : b; }
132 inline float max (float a, int b) { return (a>b) ? a : b; }
133 inline float max (long a, float b) { return (a>b) ? a : b; }
134 inline float max (float a, long b) { return (a>b) ? a : b; }
135
136 inline double max (double a, double b) { return (a>b) ? a : b; }
137 inline double max (int a, double b) { return (a>b) ? a : b; }
138 inline double max (double a, int b) { return (a>b) ? a : b; }
139 inline double max (long a, double b) { return (a>b) ? a : b; }
140 inline double max (double a, long b) { return (a>b) ? a : b; }
141 inline double max (float a, double b) { return (a>b) ? a : b; }
142 inline double max (double a, float b) { return (a>b) ? a : b; }
143
144
145 inline int min (int a, int b) { return (a<b) ? a : b; }
146
147 inline long min (long a, long b) { return (a<b) ? a : b; }
148 inline long min (int a, long b) { return (a<b) ? a : b; }
149 inline long min (long a, int b) { return (a<b) ? a : b; }
150
151 inline float min (float a, float b) { return (a<b) ? a : b; }
152 inline float min (int a, float b) { return (a<b) ? a : b; }
153 inline float min (float a, int b) { return (a<b) ? a : b; }
154 inline float min (long a, float b) { return (a<b) ? a : b; }
155 inline float min (float a, long b) { return (a<b) ? a : b; }
156
157 inline double min (double a, double b) { return (a<b) ? a : b; }
158 inline double min (int a, double b) { return (a<b) ? a : b; }
159 inline double min (double a, int b) { return (a<b) ? a : b; }
160 inline double min (long a, double b) { return (a<b) ? a : b; }
161 inline double min (double a, long b) { return (a<b) ? a : b; }
162 inline double min (float a, double b) { return (a<b) ? a : b; }
163 inline double min (double a, float b) { return (a<b) ? a : b; }
164
165 #endif
166
167 // abs is now predefined
168 //template<typename T> T abs (T a) { return (a<T(0)) ? -a : a; }
169
170
171 inline int lsr (int x, int n) { return int(((unsigned int)x) >> n); }
172
173 inline int int2pow2 (int x) { int r=0; while ((1<<r)<x) r++; return r; }
174
175
176 /******************************************************************************
177 *******************************************************************************
178 *
179 * VECTOR INTRINSICS
180 *
181 *******************************************************************************
182 *******************************************************************************/
183
184 //inline void *aligned_calloc(size_t nmemb, size_t size) { return (void*)((unsigned)(calloc((nmemb*size)+15,sizeof(char)))+15 & 0xfffffff0); }
185 //inline void *aligned_calloc(size_t nmemb, size_t size) { return (void*)((size_t)(calloc((nmemb*size)+15,sizeof(char)))+15 & ~15); }
186
187 <<includeIntrinsic>>
188
189 /******************************************************************************
190 *******************************************************************************
191 *
192 * USER INTERFACE
193 *
194 *******************************************************************************
195 *******************************************************************************/
196
197 class UI
198 {
199 bool fStopped;
200
201 public:
202
203 UI() : fStopped(false) {}
204 virtual ~UI() {}
205
206 virtual void addButton(char* label, float* zone) = 0;
207 virtual void addToggleButton(char* label, float* zone) = 0;
208 virtual void addCheckButton(char* label, float* zone) = 0;
209 virtual void addVerticalSlider(char* label, float* zone, float init, float min, float max, float step) = 0;
210 virtual void addHorizontalSlider(char* label, float* zone, float init, float min, float max, float step) = 0;
211 virtual void addNumEntry(char* label, float* zone, float init, float min, float max, float step) = 0;
212
213 virtual void addNumDisplay(char* label, float* zone, int precision) = 0;
214 virtual void addTextDisplay(char* label, float* zone, char* names[], float min, float max) = 0;
215 virtual void addHorizontalBargraph(char* label, float* zone, float min, float max) = 0;
216 virtual void addVerticalBargraph(char* label, float* zone, float min, float max) = 0;
217
218 virtual void openFrameBox(char* label) = 0;
219 virtual void openTabBox(char* label) = 0;
220 virtual void openHorizontalBox(char* label) = 0;
221 virtual void openVerticalBox(char* label) = 0;
222 virtual void closeBox() = 0;
223
224 virtual void run() {};
225
226 void stop() { fStopped = true; }
227 bool stopped() { return fStopped; }
228
229 virtual void declare(float* zone, const char* key, const char* value) {}
230 };
231
232
233 /******************************************************************************
234 *******************************************************************************
235 *
236 * FAUST DSP
237 *
238 *******************************************************************************
239 *******************************************************************************/
240
241
242
243 //----------------------------------------------------------------
244 // definition du processeur de signal
245 //----------------------------------------------------------------
246
247 class dsp {
248
249 protected:
250
251 int fSamplingFreq;
252
253 public:
254
255 dsp() {}
256 virtual ~dsp() {}
257 virtual int getNumInputs() = 0;
258 virtual int getNumOutputs() = 0;
259 virtual void buildUserInterface(UI* interface) = 0;
260 virtual void init(int samplingRate) = 0;
261 virtual void compute(int len, float** inputs, float** outputs) = 0;
262 };
263
264 /********************END ARCHITECTURE SECTION (part 1/2)****************/
265
266 /**************************BEGIN USER SECTION **************************/
267
268 <<includeclass>>
269
270 /***************************END USER SECTION ***************************/
271
272 /*******************BEGIN ARCHITECTURE SECTION (part 2/2)***************/
273
274 /******************************************************************************
275 *
276 * VST wrapper
277 *
278 ******************************************************************************/
279
280 #include "audioeffectx.h"
281
282 class vstUI;
283
284 class Faust : public AudioEffectX
285 {
286 public:
287 Faust(audioMasterCallback audioMaster);
288 virtual ~Faust();
289
290 virtual void process(float **inputs, float **outputs, long sampleFrames);
291 virtual void processReplacing(float **inputs, float **outputs, long sampleFrames);
292
293 virtual void setProgramName(char *name);
294 virtual void setProgram(long index);
295 virtual void getProgramName(char *name);
296
297 virtual void setParameter(long index, float value);
298 virtual float getParameter(long index);
299 virtual void getParameterLabel(long index, char *label);
300 virtual void getParameterDisplay(long index, char *text);
301 virtual void getParameterName(long index, char *text);
302
303 virtual void setSampleRate(float sampleRate);
304
305 virtual bool getEffectName (char* name);
306 virtual bool getVendorString (char* text);
307 virtual bool getProductString (char* text);
308
309 virtual bool getInputProperties (long index, VstPinProperties* properties);
310 virtual bool getOutputProperties (long index, VstPinProperties* properties);
311
312 private:
313 mydsp* dsp;
314 vstUI* dspUI;
315 };
316
317 /*--------------------------------------------------------------------------*/
318 class vstUIObject {
319 protected:
320 string fLabel;
321 float* fZone;
322
323 float range(float min, float max, float val)
324 { // VST parameters are normalized in the range [0;1]
325 val = min + val * (max - min);
326 return (val < min) ? min : (val > max) ? max : val;
327 }
328
329 public:
330 vstUIObject(char* label, float* zone):fLabel(label),fZone(zone) {}
331 virtual ~vstUIObject() {}
332
333 virtual void GetName(char *text){std::strcpy(text,fLabel.c_str());}
334 virtual void SetValue(double f) {*fZone = range(0.0f,1.0f,(float)f);}
335 virtual float GetValue() {return *fZone;}
336 virtual void GetDisplay(char *text){std::sprintf(text,"%f",*fZone);}
337 virtual long GetID()
338 { /* returns the sum of all the ASCII characters contained in the parameter's label */
339 int i;
340 long acc;
341 for(i=0,acc = 0;i<fLabel.length();i++) acc += (fLabel.c_str())[i];
342 return acc;
343 }
344 };
345
346 /*--------------------------------------------------------------------------*/
347 class vstToggleButton : public vstUIObject {
348
349 public:
350
351 vstToggleButton(char* label, float* zone):vstUIObject(label,zone) {}
352 virtual ~vstToggleButton() {}
353 virtual float GetValue() {return *fZone;}
354 virtual void SetValue(double f) {*fZone = (f>0.5f)?1.0f:0.0f;}
355 virtual void GetDisplay(char *text){(*fZone>0.5f)? std::strcpy(text,"ON"): std::strcpy(text,"OFF");}
356 };
357
358 /*--------------------------------------------------------------------------*/
359 class vstCheckButton : public vstUIObject {
360
361 public:
362
363 vstCheckButton(char* label, float* zone):vstUIObject(label,zone) {}
364 virtual ~vstCheckButton() {}
365 virtual float GetValue() {return *fZone;}
366 virtual void SetValue(double f) {*fZone = (f>0.5f)?1.0f:0.0f;}
367 virtual void GetDisplay(char *text){(*fZone>0.5f)? std::strcpy(text,"ON"): std::strcpy(text,"OFF");}
368 };
369
370 /*--------------------------------------------------------------------------*/
371 class vstButton : public vstUIObject {
372
373 public:
374
375 vstButton(char* label, float* zone):vstUIObject(label,zone) {}
376 virtual ~vstButton() {}
377 virtual float GetValue() {return *fZone;}
378 virtual void SetValue(double f) {*fZone = (f>0.5f)?1.0f:0.0f;}
379 virtual void GetDisplay(char *text){(*fZone>0.5f)? std::strcpy(text,"ON"): std::strcpy(text,"OFF");}
380 };
381
382 /*--------------------------------------------------------------------------*/
383 class vstSlider : public vstUIObject{
384
385 private:
386
387 float fInit;
388 float fMin;
389 float fMax;
390 float fStep;
391
392 public:
393
394 vstSlider(char* label, float* zone, float init, float min, float max, float step)
395 :vstUIObject(label,zone), fInit(init), fMin(min), fMax(max),fStep(step) {}
396 virtual ~vstSlider() {}
397
398 virtual float GetValue() {return (*fZone-fMin)/(fMax-fMin);} // normalize
399 virtual void SetValue(double f) {*fZone = range(fMin,fMax,(float)f);} // expand
400 };
401
402 /*--------------------------------------------------------------------------*/
403 class vstUI : public UI
404 {
405 private:
406
407 vector<vstUIObject*> fUITable;
408
409 public:
410
411 vstUI(){}
412 virtual ~vstUI()
413 {
414 for (vector<vstUIObject*>::iterator iter = fUITable.begin(); iter != fUITable.end(); iter++) delete *iter;
415 }
416
417 void addButton(char* label, float* zone) {fUITable.push_back(new vstButton(label, zone));}
418
419 void addToggleButton(char* label, float* zone) {fUITable.push_back(new vstToggleButton(label, zone));}
420
421 void addCheckButton(char* label, float* zone) {fUITable.push_back(new vstCheckButton(label, zone));}
422
423 void addVerticalSlider(char* label, float* zone, float init, float min, float max, float step)
424 {
425 fUITable.push_back(new vstSlider(label, zone, init, min, max, step));
426 }
427
428 void addHorizontalSlider(char* label, float* zone, float init, float min, float max, float step)
429 {
430 fUITable.push_back(new vstSlider(label, zone, init, min, max, step));
431 }
432
433 void addNumEntry(char* label, float* zone, float init, float min, float max, float step) {}
434
435 void openFrameBox(char* label) {}
436 void openTabBox(char* label) {}
437 void openHorizontalBox(char* label) {}
438 void openVerticalBox(char* label) {}
439 void closeBox() {}
440
441 void SetValue(int index, double f) {assert(index<fUITable.size()); fUITable[index]->SetValue(f);}
442 float GetValue(long index) {assert(index<fUITable.size()); return fUITable[index]->GetValue();}
443 void GetDisplay(long index, char *text) {assert(index<fUITable.size()); fUITable[index]->GetDisplay(text);}
444 void GetName(long index, char *text) {assert(index<fUITable.size()); fUITable[index]->GetName(text);}
445 long GetNumParams() {return fUITable.size();}
446
447 long makeID()
448 /* Creates a (unique?)id by summing all the parameter's labels,
449 * then wrapping it in the range [0;maxNumberOfId] and adding
450 * this number to the offset made by the Four Character ID: 'FAUS'
451 */
452 {
453 const long maxNumberOfId = 128;
454 long baseid = 'FAUS';
455 long id=0;
456 for(int i=0;i<fUITable.size();i++) id += fUITable[i]->GetID();
457 return baseid + id % maxNumberOfId;
458 }
459
460 // To be implemented
461 void addNumDisplay(char* label, float* zone, int precision){}
462 void addTextDisplay(char* label, float* zone, char* names[], float min, float max){}
463 void addHorizontalBargraph(char* label, float* zone, float min, float max){}
464 void addVerticalBargraph(char* label, float* zone, float min, float max){}
465 };
466
467 //-----------------------------------------------------------------------------
468 #define NUM_PROGRAMS 0
469 #define FAKE_NUM_PARAMS 16
470
471 Faust::Faust(audioMasterCallback audioMaster)
472 :AudioEffectX(audioMaster, NUM_PROGRAMS,FAKE_NUM_PARAMS)
473 {
474 dsp = new mydsp();
475 dspUI= new vstUI();
476 dsp->buildUserInterface(dspUI);
477 dsp->init(long(getSampleRate()));
478
479 /* we override here the fake number of parameters with the real one*/
480 this->cEffect.numParams = this->numParams = dspUI->GetNumParams();
481
482 setNumInputs(dsp->getNumInputs());
483 setNumOutputs(dsp->getNumOutputs());
484 setUniqueID(dspUI->makeID());
485 canProcessReplacing();//?
486 }
487
488 //----------------------------------------------------------------------------
489 Faust::~Faust()
490 {
491 if (dsp) delete dsp;
492 if (dspUI) delete dspUI;
493 }
494
495 //-----------------------------------------------------------------------------
496 void Faust::setParameter(long index, float value)
497 {
498 if(index<numParams)
499 dspUI->SetValue(index,value);
500 }
501 //-----------------------------------------------------------------------------
502 float Faust::getParameter(long index)
503 {
504 if(index<numParams)
505 return dspUI->GetValue(index);
506 else
507 return 0.0f;
508 }
509 //-----------------------------------------------------------------------------
510 void Faust::getParameterName(long index, char *label)
511 {
512 if(index<numParams)
513 dspUI->GetName(index,label);
514 else
515 strcpy(label,"");
516 }
517 //-----------------------------------------------------------------------------
518 void Faust::getParameterDisplay(long index, char *text)
519 {
520 if(index<numParams)
521 dspUI->GetDisplay(index,text);
522 else
523 strcpy(text,"");
524 }
525 //-----------------------------------------------------------------------------
526 void Faust::getParameterLabel(long index, char *label)
527 {
528 strcpy(label,"");
529 }
530
531 //-----------------------------------------------------------------------------
532 void Faust::setProgramName(char *name)
533 {
534 // this template does not use programs yet
535 }
536 //-----------------------------------------------------------------------------
537 void Faust::setProgram(long index)
538 {
539 // this template does not use programs yet
540 };
541 //-----------------------------------------------------------------------------
542 void Faust::getProgramName(char *name)
543 {
544 // this template does not use programs yet
545 strcpy(name, "");
546 }
547 //-----------------------------------------------------------------------------
548 void Faust::process(float **inputs, float **outputs, long sampleFrames)
549 {
550 AVOIDDENORMALS;
551 dsp->compute(sampleFrames, inputs, outputs);
552 }
553 //-----------------------------------------------------------------------------
554 void Faust::processReplacing(float **inputs, float **outputs, long sampleFrames)
555 {
556 AVOIDDENORMALS;
557 dsp->compute(sampleFrames, inputs, outputs);
558 }
559 //-----------------------------------------------------------------------------
560 void Faust::setSampleRate(float sampleRate)
561 {
562 // allways call this
563 AudioEffect::setSampleRate(sampleRate);
564 dsp->init(long(getSampleRate()));
565 }
566 //-----------------------------------------------------------------------------------------
567 bool Faust::getEffectName (char* name)
568 {
569 return false;
570 }
571 //-----------------------------------------------------------------------------------------
572 bool Faust::getVendorString (char* text)
573 {
574 strcpy (text, "Grame");
575 return true;
576 }
577 //-----------------------------------------------------------------------------------------
578 bool Faust::getProductString (char* text)
579 {
580 strcpy (text, "Faust DSP");
581 return true;
582 }
583 //-----------------------------------------------------------------------------------------
584 bool Faust::getInputProperties (long index, VstPinProperties* properties)
585 {
586 if(index>=0 && index<dsp->getNumOutputs())
587 {
588 sprintf (properties->label , "Grame Faust DSP: %d",index);
589 sprintf (properties->shortLabel, "Faust: %d",index);
590 properties->flags = kVstPinIsActive;
591 return true;
592 }
593 else
594 return false;
595 }
596 //-----------------------------------------------------------------------------------------
597 bool Faust::getOutputProperties (long index, VstPinProperties* properties)
598 {
599 if(index>=0 && index<dsp->getNumInputs())
600 {
601 sprintf (properties->label , "Grame Faust DSP: %d",index);
602 sprintf (properties->shortLabel, "Faust: %d",index);
603 properties->flags = kVstPinIsActive;
604 return true;
605 }
606 else
607 return false;
608 }
609
610 /*****************************************************************************
611 *
612 * DLL Entry Point
613 *
614 ******************************************************************************/
615 bool oome = false;
616
617 #if MAC
618 #pragma export on
619 #endif
620
621 // prototype of the export function main
622 #if BEOS
623 #define main main_plugin
624 extern "C" __declspec(dllexport) AEffect *main_plugin (audioMasterCallback audioMaster);
625
626 #elif MACX
627 #define main main_macho
628 extern "C" AEffect *main_macho (audioMasterCallback audioMaster);
629
630 #else
631 AEffect *main (audioMasterCallback audioMaster);
632 #endif
633
634 AEffect *main (audioMasterCallback audioMaster)
635 {
636 // get vst version
637 if (!audioMaster (0, audioMasterVersion, 0, 0, 0, 0))
638 return 0; // old version
639
640 AudioEffect* effect = new Faust(audioMaster);
641 if (!effect)
642 return 0;
643 if (oome)
644 {
645 delete effect;
646 return 0;
647 }
648 return effect->getAeffect ();
649 }
650
651 #if MAC
652 #pragma export off
653 #endif
654
655 #if WIN32
656 #include <windows.h>
657 void* hInstance;
658 BOOL WINAPI DllMain (HINSTANCE hInst, DWORD dwReason, LPVOID lpvReserved)
659 {
660 hInstance = hInst;
661 return 1;
662 }
663 #endif
664
665 /********************END ARCHITECTURE SECTION (part 2/2)****************/
666
667