New directory tree, with preprocessor/ inside interpretor/.
[Faustine.git] / interpretor / preprocessor / faust-0.9.47mr3 / tools / faust2oct / octave.cpp
diff --git a/interpretor/preprocessor/faust-0.9.47mr3/tools/faust2oct/octave.cpp b/interpretor/preprocessor/faust-0.9.47mr3/tools/faust2oct/octave.cpp
new file mode 100644 (file)
index 0000000..b649825
--- /dev/null
@@ -0,0 +1,490 @@
+/* octave.cpp
+   Copyright (C) 2009 by Bjoern Anton Erlach. */
+
+// OCTAVE architecture file for faust.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+// 
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+// 02111-1307 USA
+//-------------------------------------------------------------------
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <math.h>
+#include <errno.h>
+#include <time.h>
+#include <vector>
+#include <string>
+#include <map>
+#include <iostream> 
+#include <oct.h>
+
+
+using namespace std;
+
+// TODO: find out what to do with this Meta thing
+struct Meta : map<const char*, const char*>
+{
+    void declare (const char* key, const char* value) { (*this)[key]=value; }
+};
+
+
+#define max(x,y) (((x)>(y)) ? (x) : (y))
+#define min(x,y) (((x)<(y)) ? (x) : (y))
+
+// 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); }
+
+/******************************************************************************
+*******************************************************************************
+
+                                                              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>>
+
+/******************************************************************************
+*******************************************************************************
+
+                       ABSTRACT USER INTERFACE
+
+*******************************************************************************
+*******************************************************************************/
+
+
+class UI
+{
+       bool    fStopped;
+public:
+               
+       UI() : fStopped(false) {}
+       virtual ~UI() {}
+       
+       // -- active widgets
+       
+       virtual void addButton(const char* label, float* zone) = 0;
+       virtual void addToggleButton(const char* label, float* zone) = 0;
+       virtual void addCheckButton(const char* label, float* zone) = 0;
+       virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step) = 0;
+       virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step) = 0;
+       virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step) = 0;
+       
+       // -- passive widgets
+       
+       virtual void addNumDisplay(const char* label, float* zone, int precision) = 0;
+       virtual void addTextDisplay(const char* label, float* zone, char* names[], float min, float max) = 0;
+       virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) = 0;
+       virtual void addVerticalBargraph(const char* label, float* zone, float min, float max) = 0;
+       
+       // -- frames and labels
+       
+       virtual void openFrameBox(const char* label) = 0;
+       virtual void openTabBox(const char* label) = 0;
+       virtual void openHorizontalBox(const char* label) = 0;
+       virtual void openVerticalBox(const char* label) = 0;
+       virtual void closeBox() = 0;
+       
+       virtual void show() = 0;
+       virtual void run() = 0;
+       
+       void stop()             { fStopped = true; }
+       bool stopped()  { return fStopped; }
+
+    virtual void declare(float* zone, const char* key, const char* value) {}
+};
+
+
+struct param {
+       string fName; float *fVals; float* fZone; float fMin; float fMax;
+       param(string name, float* z, float init, float a, float b) : fName(name), fVals(NULL), fZone(z), fMin(a), fMax(b) { *z = init; }
+};
+
+
+class FNUI : public UI
+{
+       vector<param>   fParam;
+       int numOptions;
+
+
+public:
+       FNUI() : UI() { numOptions=0; }
+       virtual ~FNUI() {}
+       
+
+       void addOption(const char* label, float* zone, float init, float min, float max)
+       {
+         string fullname = label;
+         fParam.push_back(param(fullname, zone, init, min, max));
+         numOptions++;
+       }
+
+       virtual vector<param> getOpts () { return fParam; }
+
+       virtual void addButton(const char* label, float* zone)
+       {
+               addOption(label,zone,0,0,1);
+       }
+       
+       virtual int getNumOptions() { return numOptions; }
+
+       virtual void addToggleButton(const char* label, float* zone)
+       {
+               addOption(label,zone,0,0,1);
+       }
+       
+       virtual void addCheckButton(const char* label, float* zone)
+       {
+               addOption(label,zone,0,0,1);
+       }
+               
+       virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step)
+       {
+               addOption(label,zone,init,min,max);
+       }
+               
+       virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step)
+       {
+               addOption(label,zone,init,min,max);
+       }
+
+       virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step)
+       {
+               addOption(label,zone,init,min,max);
+       }
+               
+       // -- passive widgets
+       
+       virtual void addNumDisplay(const char* label, float* zone, int precision) {}
+       virtual void addTextDisplay(const char* label, float* zone, char* names[], float min, float max) {}
+       virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) {}
+       virtual void addVerticalBargraph(const char* label, float* zone, float min, float max) {}
+       
+
+       virtual void openFrameBox(const char* label)            { }
+       virtual void openTabBox(const char* label)              { }
+       virtual void openHorizontalBox(const char* label)       { }
+       virtual void openVerticalBox(const char* label)         { }
+       
+       //      virtual void openFrameBox(const char* label)            { openAnyBox(label); }
+       //virtual void openTabBox(const char* label)              { openAnyBox(label); }
+       //virtual void openHorizontalBox(const char* label)     { openAnyBox(label); }
+       //virtual void openVerticalBox(const char* label)               { openAnyBox(label); }
+       
+       //virtual void closeBox() { fPrefix.pop(); }
+       virtual void closeBox() { }
+       virtual void run()      {}
+       virtual void show()     {}
+
+};
+
+
+
+/******************************************************************************
+*******************************************************************************
+
+                           FAUST DSP
+
+*******************************************************************************
+*******************************************************************************/
+
+
+
+//----------------------------------------------------------------
+//  abstract definition of a signal processor
+//----------------------------------------------------------------
+                       
+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;
+};
+               
+
+//----------------------------------------------------------------------------
+//  FAUST generated signal processor
+//----------------------------------------------------------------------------
+               
+
+<<includeclass>>
+
+
+//----------------------------------------------------------------------------
+//  Octave interface
+//----------------------------------------------------------------------------
+
+// Prefered way to allocate memory
+#define ALLOC(x) alloca(x)
+#define FREE(x) ((void)0)
+// if ALLOCA is not available use MALLOC
+//#define ALLOC(x) malloc(x)
+//#define FREE(x) free(x)
+
+#define QUOTEME(x) #x
+
+#define DEFAULT_SAMPLERATE 44100
+#define DEFAULT_BLOCKSIZE 64
+
+// linear interpolation for vector valued control inputs
+void
+interpolate_ctrlin (float *vals, NDArray in, int n)
+{
+  int nin = in.length();
+  double ratio = (double)(n-1)/(double)(nin-1);
+  int irat = (int) ratio;
+  double frat = ratio - (double) irat;
+  double rest = 0;
+  int i = 0;
+  float x;
+
+  for (int j=0; j<(nin-1); j++) {
+         float del;
+         int seglength = irat; 
+         rest += frat;
+         if (rest >= 1.0) {
+                 seglength ++;
+                 rest -= 1.0;
+         }
+         del = (in(j+1) - in(j)) / (float) seglength;
+         x = in(j);
+         for (int k=0; k<seglength; k++) {
+                 vals[i++] = x;
+                 x += del;
+         }
+  }
+  for (; i<n; i++) {
+         vals[i] = in(nin-1);
+  }
+}
+
+
+
+DEFUN_DLD (FAUST_FUNC_NAME, args, nargout,    
+          "type " QUOTEME(FAUST_FUNC_NAME) "() to see the arguments.\n")
+{
+  int nargin = args.length();
+  int numIn;
+  int numOut;
+  int numOpts;
+  int maxInputLength = 0;
+  mydsp DSP;
+  int ngivenctrls;
+  float **finputs;
+  float **foutputs;
+  float **controlinputs;
+  int ctrllength;
+  int ctrlargoff;
+  int allscalarctrls = 1;
+  // TODO: float **controloutputs;
+  int i;
+  vector<param> opts;
+  int bsize;
+  int srate;
+  octave_value_list retval;
+  octave_value tmp;
+
+  FNUI* interface = new FNUI(); 
+  DSP.buildUserInterface(interface);
+
+  // check if global variable FAUST_BLOCKSIZE is set.
+  tmp = get_global_value ("FAUST_BLOCKSIZE", true);
+  if (tmp.is_defined ()) 
+         bsize = (int) tmp.scalar_value();  
+  else {
+         bsize = DEFAULT_BLOCKSIZE;
+  }
+
+  // check if global variable FAUST_SAMPLERATE is set.
+  tmp = get_global_value ("FAUST_SAMPLERATE", true);
+  if (tmp.is_defined ())
+         srate = (int) tmp.scalar_value();
+  else {
+         srate = DEFAULT_SAMPLERATE;
+  }
+
+  DSP.init(srate);
+  opts = interface->getOpts();
+
+  numIn = DSP.getNumInputs();
+  numOut = DSP.getNumOutputs();
+  numOpts = interface->getNumOptions();
+
+  // print a usage message in case the function is called with too few arguments
+  if (nargin < numIn || nargin == 0) {
+         if (numOut>1) {
+                 octave_stdout << "[out1";
+                 for (i=2; i<=numOut; i++) 
+                         octave_stdout << ",out" << i;
+                 octave_stdout << "] = " << QUOTEME(FAUST_FUNC_NAME) << "(";
+         } else {
+                 octave_stdout << "out = " << QUOTEME(FAUST_FUNC_NAME) << "(";
+         }
+         if (numIn == 0) 
+                 octave_stdout << "numsamps";
+         else
+                 octave_stdout << "in1";
+         for (i=2; i<=numIn; i++) 
+                 octave_stdout << ", in" << i;
+         for (i=0; i<numOpts; i++) 
+                 octave_stdout << ", " << opts[i].fName;
+         octave_stdout << ")\n";
+         delete interface;
+         return retval;
+ }
+
+  // If we have inputs we use the length of the longest input vector
+  // as length of the output to be produced.
+  // If we don't have inputs, the first argument specifies the number of
+  // samples to be produced.
+  if (numIn == 0) {
+         maxInputLength = args(0).scalar_value();
+         ctrlargoff = 1;
+  } else {
+         ctrlargoff = numIn;
+         for (i=0; i<numIn; i++) {
+                 octave_idx_type nr = args(i).matrix_value().rows();
+                 octave_idx_type nc = args(i).matrix_value().columns();
+                 if (nr == 1) {
+                         if (nc > maxInputLength) 
+                                 maxInputLength = nc;
+                 } else if (nc == 1) {
+                         if (nr > maxInputLength) 
+                                 maxInputLength = nr;
+                 } else {
+                         maxInputLength = nc;
+                         octave_stdout << "Argument " << i << " has wrong dimensions " << nr << "x" << nc << "\n";
+                 }
+         }
+  }
+
+
+  ctrllength = (maxInputLength+bsize-1)/bsize;
+
+  // check for arguments that should serve as control inputs 
+  for (i=ctrlargoff; i<nargin; i++) {
+         if ((i-ctrlargoff) < numOpts) {
+                 NDArray v = args(i).array_value(); 
+                 if (v.length() > 1) {
+                         allscalarctrls = 0;
+                         opts[i-ctrlargoff].fVals = (float*) ALLOC(sizeof(float)*ctrllength);
+                         interpolate_ctrlin(opts[i-ctrlargoff].fVals, v, ctrllength);
+                         *opts[i-ctrlargoff].fZone = (float) v(0);
+                 } else {
+                         *opts[i-ctrlargoff].fZone = (float) args(i).scalar_value();
+                 }
+         }
+  }
+         
+  for (i=0; i<numOpts; i++) {
+         octave_stdout << "Parameter " << opts[i].fName << ": " << *opts[i].fZone << "\n";
+  }
+
+  finputs = (float**) ALLOC(sizeof(float*) * numIn);
+  foutputs = (float**) ALLOC(sizeof(float*) * numOut);  
+
+  // Copy the matrix and convert to floats - This is a real slowdown!
+  for (i=0; i<numIn; i++) {
+         Matrix m = args(i).matrix_value();
+         float *p;
+         finputs[i] = (float*) ALLOC(maxInputLength * sizeof(float));
+         memset(finputs[i], 0, sizeof(float)*maxInputLength);
+         p = finputs[i];
+         if (m.rows() > m.columns()) {
+                 for (int j=0; j<m.rows(); j++) {
+                         *p++ = (float) m(j,0); 
+                 }
+         } else {
+                 for (int j=0; j<m.columns(); j++) {
+                         *p++ = (float) m(0,j); 
+                 }
+         }
+  }
+
+  // allocate output vectors
+  for (i=0; i<numOut; i++) {
+         foutputs[i] = (float*) ALLOC(maxInputLength * sizeof(float));
+         memset(foutputs[i], 0, sizeof(float)*maxInputLength);
+  }
+
+  if (allscalarctrls) {
+         DSP.compute(maxInputLength, finputs, foutputs);
+  } else {
+         int nleft = maxInputLength;
+         int k = 0;
+         float **fins;
+         float **fouts;
+         fins = (float**) ALLOC(sizeof(float*) * numIn);
+         fouts = (float**) ALLOC(sizeof(float*) * numOut);
+         memcpy(fins, finputs, sizeof(float*)*numIn);    
+         memcpy(fouts, foutputs, sizeof(float*)*numOut);
+         while (nleft > 0) {
+                 int n = min(bsize, nleft);
+                 for (i=0; i<numOpts; i++) {
+                         if (opts[i].fVals) {
+                                 *opts[i].fZone = opts[i].fVals[k];
+                         }
+                 }
+                 DSP.compute(n, fins, fouts);
+                 nleft -= n;
+                 k++;
+                 for (i=0; i<numIn; i++) 
+                         fins[i] += n;
+                 for (i=0; i<numOut; i++) 
+                         fouts[i] += n;
+         }
+         FREE(fins);
+         FREE(fouts);
+  }
+
+  // copy the output from the float arrays (and free all tmp memory if malloc is used)
+  for (i=0; i<numOut; i++) {
+         Matrix output = Matrix(1, maxInputLength);
+         for (int j=0; j<maxInputLength; j++) 
+                 output(0, j) = (double) foutputs[i][j];
+         FREE(foutputs[i]);
+         retval(i) = output;
+  }
+  for (i=0; i<numOpts; i++) {
+         if (opts[i].fVals) {
+                 FREE(opts[i].fVals);
+         }
+  }
+  for (i=0; i<numIn; i++) {
+         FREE(finputs[i]);
+  }
+  FREE(foutputs);
+  FREE(finputs);
+
+  delete interface;
+  return retval;
+}