Rename interpretor to interpreter.
[Faustine.git] / interpreter / preprocessor / faust-0.9.47mr3 / architecture / vsti-mono.cpp
diff --git a/interpreter/preprocessor/faust-0.9.47mr3/architecture/vsti-mono.cpp b/interpreter/preprocessor/faust-0.9.47mr3/architecture/vsti-mono.cpp
new file mode 100644 (file)
index 0000000..51fc0f9
--- /dev/null
@@ -0,0 +1,1072 @@
+/************************************************************************
+
+       IMPORTANT NOTE : this file contains two clearly delimited sections : 
+       the ARCHITECTURE section (in two parts) and the USER section. Each section 
+       is governed by its own copyright and license. Please check individually 
+       each section for license and copyright information.
+*************************************************************************/
+
+/*******************BEGIN ARCHITECTURE SECTION (part 1/2)****************/
+
+/************************************************************************
+ ************************************************************************
+    FAUST Architecture File
+       Copyright (C) 2007-2011 Julius Smith
+       All rights reserved.
+    ----------------------------BSD License------------------------------
+       Redistribution and use in source and binary forms, with or without 
+       modification, are permitted provided that the following conditions 
+       are met:
+
+       * Redistributions of source code must retain the above copyright 
+                 notice, this list of conditions and the following disclaimer.
+       * Redistributions in binary form must reproduce the above 
+                 copyright notice, this list of conditions and the following 
+                 disclaimer in the documentation and/or other materials provided 
+                 with the distribution.
+       * Neither the name of Julius Smith nor the names of its 
+                 contributors may be used to endorse or promote products derived 
+                 from this software without specific prior written permission.
+
+       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+       "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+       LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+       FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+       COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
+       INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+       BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+       LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
+       CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+       STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+       ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
+       OF THE POSSIBILITY OF SUCH DAMAGE.
+
+    ----------------------------VST SDK----------------------------------
+       In order to compile a VST (TM) plugin with this architecture file 
+       you will need the proprietary VST SDK from Steinberg. Please check 
+       the corresponding license.
+
+ ************************************************************************
+ ************************************************************************/
+
+/********************************************************************
+ * vsti-mono.cpp - Monaural VSTi-2.4 wrapper for the FAUST language. 
+ *
+ * Usage: faust -a vsti-mono.cpp myfaustprog.dsp
+ *
+ * By Julius Smith (http://ccrma.stanford.edu/~jos/), based on vst.cpp
+ * by remy muller <remy.muller at ircam.fr>
+ * (http://www.smartelectronix.com/~mdsp/).  Essentially, vst.cpp was
+ * first edited to look more like the "again" programming sample that
+ * comes with the VST-2.4 SDK from Steinberg. Next, features from the
+ * "vstxsynth" program sample were added to give simple MIDI synth
+ * support analogous to that of faust2pd, except that only one voice
+ * is supported.  (If the Faust patch has any input signals, this
+ * architecture file should reduce to vst2p4.cpp --- i.e., basic VST
+ * plugin support.)  As with faust2pd, to obtain MIDI control via
+ * NoteOn/Off, Velocity, and KeyNumber, there must be a button named
+ * "gate" and sliders (or numeric entries) named "gain" and "freq" in
+ * the Faust patch specified in myfaustprog.dsp.
+ *
+ * NOTES:
+ *  Relies on automatically generated slider GUI for VST plugins.
+ *   - Horizontal and vertical sliders mapped to "vstSlider"
+ *   - Numeric Entries similarly converted to "vstSlider"
+ *   - No support for bar graphs or additional numeric and text displays
+ *   - Tested on the Muse Receptor Pro 1.0, System Version 1.6.20070717,
+ *     using Visual C++ 2008 Express Edition 
+ *     (part of the Microsoft Visual Studio 2008, Beta 2)
+ *   - Reference: 
+ * http://ccrma.stanford.edu/realsimple/faust/Generating_VST_Plugin_Faust.html
+ *
+ * FAUST 
+ * Copyright (C) 2003-2007 GRAME, Centre National de Creation Musicale
+ * http://www.grame.fr/                             
+ *
+ ********************************************************************/
+
+// Suggestion: Faust could replace all leading comments in this file
+// by the following shorter comment:
+
+/********************************************************************
+ * C++ source generated by the following command line:
+ *
+ *   faust -a vsti.cpp name.dsp -o name-vsti.cpp
+ *
+ ********************************************************************/
+
+// (where the filenames could be really right, and the path to vsti.cpp
+// could be included as well.)
+
+#include <stdlib.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <math.h>
+#include <errno.h>
+#include <time.h>
+//#include <unistd.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <string>
+#include <vector>
+#include <math.h>
+
+using namespace std ;
+
+// There is a bug with powf() when cross compiling with mingw
+// the following macro avoid the problem
+#ifdef WIN32
+#define powf(x,y) pow(x,y)
+#define expf(x) exp(x)
+#endif
+
+// On Intel set FZ (Flush to Zero) and DAZ (Denormals Are Zero)
+// flags to avoid costly denormals
+#ifdef __SSE__
+    #include <xmmintrin.h>
+    #ifdef __SSE2__
+        #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8040)
+    #else
+        #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8000)
+    #endif
+#else
+    #define AVOIDDENORMALS 
+#endif
+
+struct Meta
+{
+    void declare (const char* key, const char* value) {  }
+};
+       
+       
+#ifdef __GNUC__
+
+//-------------------------------------------------------------------
+// Generic min and max using gcc extensions
+//-------------------------------------------------------------------
+
+#define max(x,y) ((x)>?(y))
+#define min(x,y) ((x)<?(y))
+
+//abs(x) should be already predefined
+
+#else
+
+//-------------------------------------------------------------------
+// Generic min and max using c++ inline
+//-------------------------------------------------------------------
+
+inline int     max (unsigned int a, unsigned int b) { return (a>b) ? a : b; }
+inline int     max (int a, int b)              { return (a>b) ? a : b; }
+
+inline long    max (long a, long b)            { return (a>b) ? a : b; }
+inline long    max (int a, long b)             { return (a>b) ? a : b; }
+inline long    max (long a, int b)             { return (a>b) ? a : b; }
+
+inline float   max (float a, float b)          { return (a>b) ? a : b; }
+inline float   max (int a, float b)            { return (a>b) ? a : b; }
+inline float   max (float a, int b)            { return (a>b) ? a : b; }
+inline float   max (long a, float b)           { return (a>b) ? a : b; }
+inline float   max (float a, long b)           { return (a>b) ? a : b; }
+
+inline double  max (double a, double b)        { return (a>b) ? a : b; }
+inline double  max (int a, double b)           { return (a>b) ? a : b; }
+inline double  max (double a, int b)           { return (a>b) ? a : b; }
+inline double  max (long a, double b)          { return (a>b) ? a : b; }
+inline double  max (double a, long b)          { return (a>b) ? a : b; }
+inline double  max (float a, double b)         { return (a>b) ? a : b; }
+inline double  max (double a, float b)         { return (a>b) ? a : b; }
+
+inline int     min (int a, int b)              { return (a<b) ? a : b; }
+
+inline long    min (long a, long b)            { return (a<b) ? a : b; }
+inline long    min (int a, long b)             { return (a<b) ? a : b; }
+inline long    min (long a, int b)             { return (a<b) ? a : b; }
+
+inline float   min (float a, float b)          { return (a<b) ? a : b; }
+inline float   min (int a, float b)            { return (a<b) ? a : b; }
+inline float   min (float a, int b)            { return (a<b) ? a : b; }
+inline float   min (long a, float b)           { return (a<b) ? a : b; }
+inline float   min (float a, long b)           { return (a<b) ? a : b; }
+
+inline double  min (double a, double b)        { return (a<b) ? a : b; }
+inline double  min (int a, double b)           { return (a<b) ? a : b; }
+inline double  min (double a, int b)           { return (a<b) ? a : b; }
+inline double  min (long a, double b)          { return (a<b) ? a : b; }
+inline double  min (double a, long b)          { return (a<b) ? a : b; }
+inline double  min (float a, double b)         { return (a<b) ? a : b; }
+inline double  min (double a, float b)         { return (a<b) ? a : b; }
+               
+#endif
+
+// abs is now predefined
+//template<typename T> T abs (T a) { return (a<T(0)) ? -a : a; }
+
+inline int lsr (int x, int n) { return int(((unsigned int)x) >> n); }
+
+inline int int2pow2 (int x) { int r=0; while ((1<<r)<x) r++; return r; }
+
+/******************************************************************************
+*******************************************************************************
+*
+*                                                             VECTOR INTRINSICS
+*
+*******************************************************************************
+*******************************************************************************/
+
+//inline void *aligned_calloc(size_t nmemb, size_t size) { return (void*)((unsigned)(calloc((nmemb*size)+15,sizeof(char)))+15 & 0xfffffff0); }
+//inline void *aligned_calloc(size_t nmemb, size_t size) { return (void*)((size_t)(calloc((nmemb*size)+15,sizeof(char)))+15 & ~15); }
+
+<<includeIntrinsic>>
+
+/******************************************************************************
+*******************************************************************************
+*
+*                                                              USER INTERFACE
+*
+*******************************************************************************
+*******************************************************************************/
+
+class UI
+{
+  bool fStopped;
+
+public:
+                       
+  UI() : fStopped(false) {}
+  virtual ~UI() {}
+               
+  virtual void addButton(char* label, float* zone) = 0;
+  virtual void addToggleButton(char* label, float* zone) = 0;
+  virtual void addCheckButton(char* label, float* zone) = 0;
+  virtual void addVerticalSlider(char* label, float* zone, float init, float min, float max, float step) = 0;
+  virtual void addHorizontalSlider(char* label, float* zone, float init, float min, float max, float step) = 0;
+  virtual void addNumEntry(char* label, float* zone, float init, float min, float max, float step) = 0;
+       
+  virtual void addNumDisplay(char* label, float* zone, int precision) = 0;
+  virtual void addTextDisplay(char* label, float* zone, char* names[], float min, float max) = 0;
+  virtual void addHorizontalBargraph(char* label, float* zone, float min, float max) = 0;
+  virtual void addVerticalBargraph(char* label, float* zone, float min, float max) = 0;
+               
+  virtual void openFrameBox(char* label) = 0;
+  virtual void openTabBox(char* label) = 0;
+  virtual void openHorizontalBox(char* label) = 0;
+  virtual void openVerticalBox(char* label) = 0;
+  virtual void closeBox() = 0;
+               
+  virtual void run() {};
+               
+  void stop()          { fStopped = true; }
+  bool stopped()       { return fStopped; }
+
+  virtual void declare(float* zone, const char* key, const char* value) {}
+};
+
+
+/******************************************************************************
+*******************************************************************************
+*
+*                                                              FAUST DSP
+*
+*******************************************************************************
+*******************************************************************************/
+
+
+
+//----------------------------------------------------------------
+//  Base dsp class for this architecture
+//----------------------------------------------------------------
+                       
+class dsp {
+
+protected:
+        
+  int fSamplingFreq;
+               
+public:
+        
+  dsp() {}
+  virtual ~dsp() {}
+  virtual int getNumInputs() = 0;
+  virtual int getNumOutputs() = 0;
+  virtual void buildUserInterface(UI* interface) = 0;
+  virtual void init(int samplingRate) = 0;
+  virtual void compute(int len, float** inputs, float** outputs) = 0;
+};
+               
+/********************END ARCHITECTURE SECTION (part 1/2)****************/
+
+/**************************BEGIN USER SECTION **************************/
+               
+<<includeclass>>
+
+/***************************END USER SECTION ***************************/
+
+/*******************BEGIN ARCHITECTURE SECTION (part 2/2)***************/
+                                       
+/******************************************************************************
+ *
+ * VST wrapper
+ * 
+ ******************************************************************************/
+
+#include "audioeffectx.h" 
+
+class vstUI;
+
+//------------------------------------------------------------------------------
+// Faust class prototype
+//------------------------------------------------------------------------------
+class Faust : public AudioEffectX
+{
+public:
+  Faust(audioMasterCallback audioMaster, mydsp* dspi, vstUI* dspUIi);
+  virtual ~Faust();
+
+  virtual void processReplacing (float **inputs, float **outputs, VstInt32 sampleFrames);
+  virtual VstInt32 processEvents (VstEvents* events);
+
+  virtual void setProgram (VstInt32 program);
+  virtual void setProgramName (char *name);
+  virtual void getProgramName (char *name);
+  virtual bool getProgramNameIndexed (VstInt32 category, VstInt32 index, char *text);
+
+  virtual void setParameter (VstInt32 index, float value);
+  virtual float getParameter (VstInt32 index);
+  virtual void getParameterLabel (VstInt32 index, char *label);
+  virtual void getParameterDisplay (VstInt32 index, char *text);
+  virtual void getParameterName (VstInt32 index, char *text);
+
+  virtual void setSampleRate (float sampleRate);
+
+  virtual bool getInputProperties (VstInt32 index, VstPinProperties *properties);
+  virtual bool getOutputProperties (VstInt32 index, VstPinProperties *properties);
+
+  virtual bool getEffectName (char *name);
+  virtual bool getVendorString (char *text);
+  virtual bool getProductString (char *text);
+  virtual VstInt32 getVendorVersion ();
+  virtual VstInt32 canDo (char *text);
+
+  virtual VstInt32 getNumMidiInputChannels ();
+  virtual VstInt32 getNumMidiOutputChannels ();
+
+  virtual VstInt32 getMidiProgramName (VstInt32 channel, MidiProgramName *midiProgramName);
+  virtual VstInt32 getCurrentMidiProgram (VstInt32 channel, MidiProgramName *currentProgram);
+  virtual VstInt32 getMidiProgramCategory (VstInt32 channel, MidiProgramCategory *category);
+
+private:
+  mydsp*       dsp;
+  vstUI*       dspUI;
+
+  // For synths:
+  bool noteIsOn;
+  VstInt32 currentNote;
+  VstInt32 currentVelocity;
+  VstInt32 currentDelta;
+
+  void initProcess ();
+  void noteOn (VstInt32 note, VstInt32 velocity, VstInt32 delta);
+  void noteOff ();
+  void fillProgram (VstInt32 channel, VstInt32 prg, MidiProgramName* mpn);
+
+  char programName[kVstMaxProgNameLen + 1];
+};
+
+/*--------------------------------------------------------------------------*/
+class vstUIObject { /* superclass of all VST UI widgets */
+protected:
+  string fLabel;
+  float* fZone;
+               
+  inline float clip(float min, float max, float val) 
+  {
+    return (val < min) ? min : (val > max) ? max : val;
+  }
+        
+  inline float normalize(float min, float max, float val) 
+  { // VST parameters are normalized to the range [0;1] on the host
+    val = min + val * (max - min);
+    return (val < min) ? min : (val > max) ? max : val;
+  }
+        
+public:                        
+  vstUIObject(char* label, float* zone):fLabel(label),fZone(zone) {}
+  virtual ~vstUIObject() {}
+
+  virtual void  GetName(char *text){std::strcpy(text,fLabel.c_str());}
+  virtual void  SetValue(double f) {*fZone = normalize(0.0f,1.0f,(float)f);}
+  virtual void  SetValueNoNormalization(double f) {*fZone = clip(0.0f,1.0f,(float)f);}
+  virtual float GetValue() {return *fZone;}
+  virtual void  GetDisplay(char *text){std::sprintf(text,"%f",*fZone);}
+  virtual long  GetID() 
+  {    /* returns the sum of all the ASCII characters  contained in the parameter's label */
+    unsigned int i;
+    long acc;
+    for(i=0,acc = 0;i<fLabel.length();i++) acc += (fLabel.c_str())[i];
+    return acc;
+  }
+};
+
+/*--------------------------------------------------------------------------*/
+class vstToggleButton : public vstUIObject {
+       
+public:        
+       
+  vstToggleButton(char* label, float* zone):vstUIObject(label,zone) {}
+  virtual ~vstToggleButton() {}
+  virtual float GetValue() {return *fZone;}
+  virtual void SetValue(double f) {*fZone = (f>0.5f)?1.0f:0.0f;}
+  virtual void  GetDisplay(char *text){(*fZone>0.5f)? std::strcpy(text,"ON"): std::strcpy(text,"OFF");}
+};
+
+/*--------------------------------------------------------------------------*/
+class vstCheckButton : public vstUIObject {
+       
+public:
+       
+  vstCheckButton(char* label, float* zone):vstUIObject(label,zone) {}  
+  virtual ~vstCheckButton() {}
+  virtual float GetValue() {return *fZone;}
+  virtual void SetValue(double f) {*fZone = (f>0.5f)?1.0f:0.0f;}
+  virtual void  GetDisplay(char *text){(*fZone>0.5f)? std::strcpy(text,"ON"): std::strcpy(text,"OFF");}                
+};
+
+/*--------------------------------------------------------------------------*/
+class vstButton : public vstUIObject {
+       
+public:
+       
+  vstButton(char* label, float* zone):vstUIObject(label,zone) {}
+  virtual ~vstButton() {}              
+  virtual float GetValue() {return *fZone;}
+  virtual void SetValue(double f) {*fZone = (f>0.5f)?1.0f:0.0f;}               
+  virtual void  GetDisplay(char *text){(*fZone>0.5f)? std::strcpy(text,"ON"): std::strcpy(text,"OFF");}
+};
+
+/*--------------------------------------------------------------------------*/
+class vstSlider : public vstUIObject{
+
+private:
+       
+  float fInit;
+  float fMin;
+  float fMax;
+  float fStep;
+       
+public:        
+       
+  vstSlider(char* label, float* zone, float init, float min, float max, float step)
+    :vstUIObject(label,zone), fInit(init), fMin(min), fMax(max),fStep(step) {}
+  virtual ~vstSlider() {}      
+
+  // The VST host calls GetValue() and expects a result in [0,1].
+  // The VST host calls SetValue(f) with f in [0,1]. We convert to real units.
+  // When we process MIDI controls, we call SetValueNoNormalization(f) with f in real units.
+  virtual float GetValue() {return (*fZone-fMin)/(fMax-fMin);} // normalize
+  virtual void SetValue(double f) {*fZone = normalize(fMin,fMax,(float)f);} // denormalize
+  virtual void SetValueNoNormalization(double f) {*fZone = clip(fMin,fMax,(float)f);} // raw
+};
+
+/*--------------------------------------------------------------------------*/
+class vstUI : public UI
+{
+private:
+       
+  vector<vstUIObject*> fUITable;
+
+public:
+                       
+  int freqIndex;
+  int gainIndex;
+  int gateIndex;
+
+  vstUI(){   
+    freqIndex = gainIndex = gateIndex = -1;
+  }
+  virtual ~vstUI() 
+  {
+    for (vector<vstUIObject*>::iterator iter = fUITable.begin(); iter != fUITable.end(); iter++) delete *iter;
+  }
+
+  void setAny(int anyIndex, float val, char *str) {
+    if (anyIndex<0) {
+#ifdef DEBUG
+      // On the Receptor, and perhaps other hosts, output to stderr is logged in a file.
+      fprintf(stderr,"*** Faust vsti: %sIndex = %d never set!\n",str,anyIndex);
+#endif
+      return;
+    }
+    if (anyIndex >= fUITable.size()) {
+#ifdef DEBUG
+        fprintf(stderr,"*** Faust vsti: %sIndex = %d too large!\n",str,anyIndex);
+#endif
+       return;
+    }
+#ifdef DEBUG
+    fprintf(stderr,"*** Faust vsti: Setting %sIndex = %d to %f\n",str,anyIndex,val);
+#endif
+    fUITable[anyIndex]->SetValueNoNormalization(val);
+  }
+               
+  void setFreq(float val) {
+    setAny(freqIndex, val, "freq");
+  }
+               
+  void setGate(float val) {
+    setAny(gateIndex, val, "gate");
+  }
+               
+  void setGain(float val) {
+    setAny(gainIndex, val, "gain");
+  }
+
+  bool ckAnyMatch(char* label, char* indexName, int *index) {
+    if (_stricmp(label,indexName)==0) { 
+#ifdef DEBUG
+      fprintf(stderr,"=== Faust vsti: label '%s' matches '%s'\n",label,indexName);
+#endif
+      *index = fUITable.size() - 1; 
+      return true;
+    }
+    return false;
+  }
+
+  void ckAllMatches(char* label) {
+    ckAnyMatch(label,"gain",&gainIndex);
+    ckAnyMatch(label,"gate",&gateIndex);
+    ckAnyMatch(label,"freq",&freqIndex);
+  }
+
+  void addButton(char* label, float* zone) {
+    vstButton* theButton = new vstButton(label, zone);
+    fUITable.push_back(theButton);
+#ifdef DEBUG
+    fprintf(stderr,"=== Faust vsti: Adding Button with label '%s'\n",label);
+#endif
+    ckAnyMatch(label,"gate",&gateIndex);
+  }
+               
+  void addToggleButton(char* label, float* zone) {fUITable.push_back(new vstToggleButton(label, zone));}
+               
+  void addCheckButton(char* label, float* zone) {fUITable.push_back(new vstCheckButton(label, zone));}
+               
+  void addVerticalSlider(char* label, float* zone, float init, float min, float max, float step) 
+  {    
+    vstSlider* theSlider = new vstSlider(label, zone, init, min, max, step);
+    fUITable.push_back(theSlider);
+#ifdef DEBUG
+    fprintf(stderr,"=== Faust vsti: Adding VSlider (HSlider) with label '%s'\n",label);
+#endif
+    ckAllMatches(label);
+  }
+               
+  void addHorizontalSlider(char* label, float* zone, float init, float min, float max, float step) 
+  {
+    vstSlider* theSlider = new vstSlider(label, zone, init, min, max, step);
+    fUITable.push_back(theSlider);
+#ifdef DEBUG
+    fprintf(stderr,"=== Faust vsti: Adding HSlider with label '%s'\n",label);
+#endif
+    ckAllMatches(label);
+  }
+               
+  void addNumEntry(char* label, float* zone, float init, float min, float max, float step)
+  { /* Number entries converted to horizontal sliders */
+    vstSlider* theSlider = new vstSlider(label, zone, init, min, max, step);
+    fUITable.push_back(theSlider);
+#ifdef DEBUG
+    fprintf(stderr,"=== Faust vsti: Adding NumEntry (HSlider) with label '%s'\n",label);
+#endif
+    ckAllMatches(label);
+  }
+               
+  void openFrameBox(char* label) {}
+  void openTabBox(char* label) {}
+  void openHorizontalBox(char* label) {}
+  void openVerticalBox(char* label) {}
+  void closeBox() {}
+               
+  void  SetValue(VstInt32 index, double f) {assert(index<fUITable.size()); fUITable[index]->SetValue(f);}
+  float GetValue(VstInt32 index) {assert(index<fUITable.size()); return fUITable[index]->GetValue();}
+  void  GetDisplay(VstInt32 index, char *text) {assert(index<fUITable.size()); fUITable[index]->GetDisplay(text);}
+  void  GetName(VstInt32 index, char *text) {assert(index<fUITable.size()); fUITable[index]->GetName(text);}
+  long  GetNumParams() {return fUITable.size();}
+
+  long  makeID()
+    /* Creates a (unique?)id by summing all the parameter's labels, 
+     * then wrapping it in the range [0;maxNumberOfId] and adding 
+     * this number to the offset made by the Four Character ID: 'FAUS'
+     */
+  {   
+    const long maxNumberOfId = 128;
+    long baseid = 'FAUS';
+    long id=0;
+    for(int i=0;i<fUITable.size();i++) id += fUITable[i]->GetID();
+    return baseid + id % maxNumberOfId;
+  }
+               
+  // To be implemented
+  void addNumDisplay(char* label, float* zone, int precision){}
+  void addTextDisplay(char* label, float* zone, char* names[], float min, float max){}
+  void addHorizontalBargraph(char* label, float* zone, float min, float max){}
+  void addVerticalBargraph(char* label, float* zone, float min, float max){}
+};
+
+//-----------------------------------------------------------------------------
+// Class Implementations 
+//-----------------------------------------------------------------------------
+
+#define kNumPrograms 1
+
+AudioEffect* createEffectInstance (audioMasterCallback audioMaster)
+{
+  // The dsp and its UI need to be allocated now because
+  // AudioEffectX wants the no. parameters available as an instance argument:
+  mydsp* dspi = new mydsp();
+  vstUI* dspUIi = new vstUI(); 
+  dspi->buildUserInterface(dspUIi);
+#ifdef DEBUG
+  fprintf(stderr,"=== Faust vsti: created\n"); // look for this in the system log
+#endif
+  return new Faust(audioMaster,dspi,dspUIi);
+}
+
+//-----------------------------------------------------------------------------
+// Faust
+//-----------------------------------------------------------------------------
+Faust::Faust(audioMasterCallback audioMaster, mydsp* dspi, vstUI* dspUIi)
+  :AudioEffectX(audioMaster, kNumPrograms,dspUIi->GetNumParams())
+{
+  // Copy the pointers to dsp and dspUI instances and take them over 
+  // (we'll also deallocate):
+  dsp = dspi;
+  dspUI = dspUIi;
+
+#ifdef DEBUG
+  fprintf(stderr,"=== Faust vsti: classInit:\n");
+#endif
+
+  dsp->classInit((int)getSampleRate()); // Ask AudioEffect for sample-rate
+
+  setProgram(0);
+  setProgramName("Default");
+
+  if (audioMaster) {
+    setNumInputs(dsp->getNumInputs());
+    setNumOutputs(dsp->getNumOutputs());               
+    canProcessReplacing();
+    if (dsp->getNumInputs() == 0) {
+      isSynth(); // at least let's hope so!
+      if (dsp->getNumOutputs() < 1) {
+       fprintf(stderr,"*** faust: vsti: No signal inputs or outputs, and Faust has no MIDI outputs!\n");
+      }
+    }
+    setUniqueID(dspUI->makeID());                                      
+  }
+  initProcess();
+  if (dsp->getNumInputs() == 0) {
+    suspend(); //  Synths start out quiet
+  }
+}
+
+//----------------------------------------------------------------------------
+Faust::~Faust()
+{
+  if (dsp) delete dsp;
+  if (dspUI) delete dspUI;
+}
+
+//-----------------------------------------------------------------------------
+void Faust::setProgram (VstInt32 program)
+// Override this method of AudioEffect in order to set 
+// local instance variables corresponding to the current MIDI program.
+// Here there is only one program.
+{
+  if (program < 0 || program >= kNumPrograms) {
+    fprintf(stderr,"*** Faust vsti: setting program to %d is OUT OF RANGE\n",program);
+    return;
+  }  
+#ifdef DEBUG
+  fprintf(stderr,"=== Faust vsti: setting program to %d\n",program);
+#endif
+  curProgram = program; // curProgram defined in audioeffect.h
+}
+
+//------------------------------------------------------------------------------
+void Faust::setProgramName (char* name)
+{
+  vst_strncpy (programName, name, kVstMaxProgNameLen);
+}
+
+//-----------------------------------------------------------------------------
+void Faust::getProgramName(char *name)
+{
+  vst_strncpy (name, programName, kVstMaxProgNameLen);
+}
+
+//-----------------------------------------------------------------------------
+void Faust::getParameterLabel(VstInt32 index, char *label)
+{
+  // We are not using parameter "units" display:
+  vst_strncpy (label, "", kVstMaxParamStrLen); // parameter units in Name
+}
+
+//-----------------------------------------------------------------------------
+void Faust::getParameterDisplay(VstInt32 index, char *text)
+{
+  if(index<numParams)
+    dspUI->GetDisplay(index,text); // get displayed float value as text
+  else
+    vst_strncpy (text, "IndexOutOfRange", kVstMaxParamStrLen);
+}
+
+//-----------------------------------------------------------------------------
+void Faust::getParameterName(VstInt32 index, char *label)
+{
+  if(index<numParams)
+    dspUI->GetName(index,label); // parameter name, including units
+  else
+    vst_strncpy (label, "IndexOutOfRange", kVstMaxParamStrLen);
+}
+
+//-----------------------------------------------------------------------------
+void Faust::setParameter(VstInt32 index, float value)
+{
+  if(index<numParams)
+    dspUI->SetValue(index,value);
+}
+
+//-----------------------------------------------------------------------------
+float Faust::getParameter(VstInt32 index)
+{
+  if(index<numParams)
+    return dspUI->GetValue(index);
+  else
+    return 0.0f;
+}
+
+//-----------------------------------------------------------------------------
+bool Faust::getInputProperties (VstInt32 index, VstPinProperties* properties)
+{
+  if(index>=0 && index<dsp->getNumInputs())
+  {
+    sprintf (properties->label, "Grame Faust DSP input: %d",index);
+    sprintf (properties->shortLabel, "In %d",index);
+    properties->flags = kVstPinIsActive;
+    if (dsp->getNumInputs() == 2) {
+      properties->flags |= kVstPinIsStereo;
+    }
+    return true;
+  }
+  else
+    return false;
+}
+
+//-----------------------------------------------------------------------------
+bool Faust::getOutputProperties (VstInt32 index, VstPinProperties* properties)
+{
+  if(index>=0 && index<dsp->getNumOutputs())
+  {
+    sprintf (properties->label, "Grame Faust DSP output: %d",index);
+    sprintf (properties->shortLabel, "Out %d",index);
+    properties->flags = kVstPinIsActive;
+    if (dsp->getNumOutputs() == 2) {
+      properties->flags |= kVstPinIsStereo;
+    }
+    return true;
+  }
+  else
+    return false;
+}
+
+//-----------------------------------------------------------------------------
+bool Faust::getProgramNameIndexed (VstInt32 category, VstInt32 index, char* text)
+{
+  if (index < kNumPrograms) {
+      vst_strncpy (text, programName, kVstMaxProgNameLen);
+      return true;
+  }
+  return false;
+}
+
+//-----------------------------------------------------------------------------
+bool Faust::getEffectName (char* name)
+{
+  // Get from Faust-supplied metadata?
+  vst_strncpy (name, "Effect Name goes here", kVstMaxEffectNameLen);
+  return true;
+}
+
+//-----------------------------------------------------------------------------
+bool Faust::getVendorString (char* text)
+{
+  vst_strncpy (text, "Vendor String goes here", kVstMaxVendorStrLen);
+  return true;
+}
+
+//-----------------------------------------------------------------------------
+bool Faust::getProductString (char* text)
+{
+  vst_strncpy (text, "Product String goes here", kVstMaxProductStrLen);
+  return true;
+}
+
+//-----------------------------------------------------------------------------
+VstInt32 Faust::getVendorVersion ()
+{ 
+  return 1000; 
+}
+
+//-----------------------------------------------------------------------------
+VstInt32 Faust::canDo (char* text)
+{
+  if (!strcmp (text, "receiveVstEvents"))
+    return 1;
+  if (!strcmp (text, "receiveVstMidiEvent"))
+    return 1;
+  if (!strcmp (text, "midiProgramNames"))
+    return 1;
+  return -1;   // explicitly can't do; 0 => don't know
+}
+
+//-----------------------------------------------------------------------------
+VstInt32 Faust::getNumMidiInputChannels ()
+{
+  return 1; // one MIDI-in channel
+}
+
+//-----------------------------------------------------------------------------
+VstInt32 Faust::getNumMidiOutputChannels ()
+{
+  return 0; // no MIDI-outs
+}
+
+//-----------------------------------------------------------------------------
+VstInt32 Faust::getMidiProgramName (VstInt32 channel, MidiProgramName* mpn)
+{
+  VstInt32 prg = mpn->thisProgramIndex;
+  if (prg < 0 || prg > 0) return 0;
+  fillProgram (channel, prg, mpn);
+  return 1; // we have only 1 "MIDI program"
+}
+
+//------------------------------------------------------------------------
+VstInt32 Faust::getCurrentMidiProgram (VstInt32 channel, MidiProgramName* mpn)
+{
+  // There is only one MIDI program here, so return it regardless of MIDI channel:
+  if (channel < 0 || channel >= 16 || !mpn) return -1;
+  VstInt32 prg = 0;
+  mpn->thisProgramIndex = prg;
+  fillProgram (channel, prg, mpn);
+  return prg;
+}
+
+//------------------------------------------------------------------------
+void Faust::fillProgram (VstInt32 channel, VstInt32 prg, MidiProgramName* mpn)
+// Fill mpn struct for given channel.  Here there should be only one.
+{
+  mpn->midiBankMsb = mpn->midiBankLsb = -1;
+  mpn->reserved = 0;
+  mpn->flags = 0;
+  vst_strncpy (mpn->name, programName, kVstMaxProgNameLen);
+  mpn->midiProgram = (char)prg; // prg should only be 0
+  mpn->parentCategoryIndex = -1;
+}
+
+//------------------------------------------------------------------------
+VstInt32 Faust::getMidiProgramCategory (VstInt32 channel, MidiProgramCategory* cat)
+// VST host wants to fill cat struct for given channel.  We have only one category.
+{
+  cat->parentCategoryIndex = -1;       // -1:no parent category
+  cat->flags = 0;                      // reserved, none defined yet, zero.
+  VstInt32 category = cat->thisCategoryIndex;
+  vst_strncpy (cat->name, "Faust Patch", kVstMaxProgNameLen);
+  return 1; // one category
+}
+
+//***********************************************************************
+
+//-----------------------------------------------------------------------------
+void Faust::setSampleRate(float sampleRate)
+{
+  AudioEffect::setSampleRate(sampleRate);
+  dsp->instanceInit((int)getSampleRate()); // in case AudioEffect altered it
+}
+
+//-----------------------------------------------------------------------------
+void Faust::initProcess ()
+{
+  noteIsOn = false;
+  currentDelta = currentNote = currentDelta = 0;
+  dsp->instanceInit((int)getSampleRate());
+}
+
+//-----------------------------------------------------------------------------
+void Faust::processReplacing(float **inputs, float **outputs, VstInt32 sampleFrames)
+{
+    AVOIDDENORMALS;
+#ifdef DEBUG
+    fprintf(stderr,"=== Faust vsti: processReplacing . . .\n");
+#endif
+
+  if (dsp->getNumInputs() > 0) { // We're an effect . . . keep going:
+
+    dsp->compute(sampleFrames, inputs, outputs);
+
+  } else { // We're a synth . . . 
+    int i, nouts = dsp->getNumOutputs();
+
+    if (noteIsOn) { // we're synthesizing . . .
+
+      if (currentDelta > 0) {  // but waiting out a timestamp delay . . .
+       if (currentDelta >= sampleFrames) { // start time is after this chunk
+         currentDelta -= sampleFrames;
+         // According to the VST programming sample, we DON'T clear the output buffers yet.
+         // Could this be a bug in the sample program?  I would like to add the following:
+         // for (i=0; i<nouts; i++) { memset (outptr[i], 0, sampleFrames * sizeof (float)); }
+         return;
+       } else {
+         // float* outptr[nouts];
+         float** outptr = (float **)malloc(nouts * sizeof(float*));
+
+#ifdef DEBUG
+         fprintf(stderr,"*** Faust vsti: currentDelta = %d\n",currentDelta);
+#endif
+
+         for (i=0; i<nouts; i++) {
+           outptr[i] = outputs[i]; // leaving caller's pointers alone
+           // According to the VST programming sample, we DO clear the output buffers now
+           // (since the start-time for the note is somewhere within the current chunk buf).
+           memset (outptr[i], 0, currentDelta * sizeof (float));
+           outptr[i] += currentDelta;
+         }
+         sampleFrames -= currentDelta;
+         currentDelta = 0;
+         dsp->compute(sampleFrames, inputs, outptr);
+         free(outptr);
+       }
+      } else {
+       dsp->compute(sampleFrames, inputs, outputs);
+      }
+
+    } else { // silence until NoteOn . . .
+      for (i=0; i<nouts; i++) {        memset (outputs[i], 0, sampleFrames * sizeof (float)); }
+    }
+  }
+}
+
+//-----------------------------------------------------------------------------
+VstInt32 Faust::processEvents (VstEvents* ev)
+{
+  if (ev->numEvents > 0) {
+#ifdef DEBUG
+    fprintf(stderr,"=== Faust vsti: processEvents processing %d events\n",
+           ev->numEvents);
+#endif
+  }
+
+  for (VstInt32 i = 0; i < ev->numEvents; i++)
+    {
+#ifdef DEBUG
+      fprintf(stderr,"=== Faust vsti: event type = %d\n", 
+             (ev->events[i])->type);
+#endif
+      if ((ev->events[i])->type != kVstMidiType) {
+#ifdef DEBUG
+       fprintf(stderr,"=== Faust vsti: EVENT IGNORED!\n");
+#endif
+       continue;
+      }
+      VstMidiEvent* event = (VstMidiEvent*)ev->events[i];
+      char* midiData = event->midiData;
+      VstInt32 chan = midiData[0] & 0xf;
+      VstInt32 status = midiData[0] & 0xf0;
+#ifdef DEBUG
+      fprintf(stderr,"\n=== Faust vsti: event->midiData[0] = 0x%x\n", 
+             event->midiData[0]);
+      fprintf(stderr,"=== Faust vsti: midi channel = 0x%x\n", chan);
+      fprintf(stderr,"=== Faust vsti: midi status = 0x%x\n", status);
+      fprintf(stderr,"=== Faust vsti: event->midiData[1] = 0x%x\n", 
+             event->midiData[1]);
+      fprintf(stderr,"=== Faust vsti: event->midiData[2] = 0x%x\n", 
+             event->midiData[2]);
+#endif
+
+      if (status == 0x90) { // note on
+       VstInt32 note = midiData[1] & 0x7f;
+       VstInt32 velocity = midiData[2] & 0x7f;
+#ifdef DEBUG
+       fprintf(stderr,
+               "=== Faust vsti: note = %d, velocity = %d, delay = %d\n",
+               note,velocity,event->deltaFrames);
+#endif
+       if (velocity>0) {
+         noteOn(note, velocity, event->deltaFrames);
+       } else {
+         noteOff();
+       }
+      } else if (status == 0x80) { // note off
+       noteOff();
+       //      } else if (status == 0xA0) { // poly aftertouch
+      } else if (status == 0xB0) { // control change
+       /* DO SOMETHING WITH THE CONTROLLER DATA */
+       fprintf(stderr,"=== Faust vsti: CONTROL CHANGE (status 0xB0)!\n");
+       if (midiData[1] == 0x7e || midiData[1] == 0x7b) { // all notes off
+         fprintf(stderr,"=== Faust vsti: ALL NOTES OFF!\n");
+         noteOff (); // why is all-notes-off inside a "control change" event?
+       }
+       //      } else if (status == 0xC0) { // program change
+       //      } else if (status == 0xD0) { // mono aftertouch
+       //      } else if (status == 0xE0) { // pitch change
+       //      } else if (status == 0xF0) { // SYSX ...
+      }
+      // For a list, see 
+      // http://www.alfred-j-faust.de/rft/midi%20status%20types.html
+
+#ifdef DEBUG
+      fprintf(stderr,"=== Faust vsti: Going to next event\n", event->midiData[2]);
+#endif
+
+      event++;
+    }
+  return 1;
+}
+
+//-----------------------------------------------------------------------------
+void Faust::noteOn (VstInt32 note, VstInt32 velocity, VstInt32 delta)
+{
+#ifdef DEBUG
+  fprintf(stderr,"=== Faust vsti: noteOn: note = %d, vel = %d, del = %d\n",note,velocity,delta);
+#endif
+  currentNote = note;
+  currentVelocity = velocity;
+  currentDelta = delta;
+  noteIsOn = true;
+  float freq = 440.0f * powf(2.0f,(((float)note)-69.0f)/12.0f);
+  float gain = velocity/127.0f;
+  dspUI->setFreq(freq); // Hz - requires Faust control-signal "freq"
+  dspUI->setGain(gain); // 0-1 - requires Faust control-signal "gain"
+  dspUI->setGate(1.0f); // 0 or 1 - requires Faust button-signal "gate"
+}
+
+//-----------------------------------------------------------------------------
+void Faust::noteOff ()
+{
+  if (noteIsOn) {
+#ifdef DEBUG
+    fprintf(stderr,"=== Faust vsti: noteOff\n");
+#endif
+    dspUI->setGate(0);
+  } else {
+#ifdef DEBUG
+    fprintf(stderr,"=== Faust vsti: noteOff IGNORED (note was not on)\n");
+#endif
+  }
+}
+
+
+/********************END ARCHITECTURE SECTION (part 2/2)****************/
+