Logo Search packages:      
Sourcecode: faust version File versions  Download package

octave.cpp

/* 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;
} 

Generated by  Doxygen 1.6.0   Back to index