685 lines · 17.8 KB · C++
RawDownload
//-----------------------------------------------------------------------------// name: Faust.cpp// desc: Faust ChucK chugin//// authors: Ge Wang (ge@ccrma.stanford.edu)//          Romain Michon (rmichon@ccrma.stanford.edu)// date: Spring 2016//// NOTE: be mindful of chuck/chugin compilation, particularly on OSX//       compiled for 10.5 chuck may not work well with 10.10 chugin!//----------------------------------------------------------------------------- #ifndef MAX_INPUTS  #define MAX_INPUTS 12#endif#ifndef MAX_OUTPUTS  #define MAX_OUTPUTS 12#endif // this should align with the correct versions of these ChucK files#include "chuck_dl.h"#include "chuck_def.h" // general includes#include <stdio.h>#include <limits.h>#include <iostream>#include <string>#include <vector>#include <map>#include <fstream>using namespace std; // faust include#include "faust/dsp/llvm-dsp.h"#include "faust/gui/UI.h"#include "faust/gui/PathBuilder.h" // declaration of chugin constructorCK_DLL_CTOR(faust_ctor);// declaration of chugin desctructorCK_DLL_DTOR(faust_dtor);// multi-channel audio synthesis tick functionCK_DLL_TICKF(faust_tickf); // example of getter/setterCK_DLL_MFUN(faust_eval);CK_DLL_MFUN(faust_compile);CK_DLL_MFUN(faust_v_set);CK_DLL_MFUN(faust_v_get);CK_DLL_MFUN(faust_dump);CK_DLL_MFUN(faust_ok);CK_DLL_MFUN(faust_error);CK_DLL_MFUN(faust_code);CK_DLL_MFUN(faust_test); // this is a special offset reserved for Chugin internal datat_CKINT faust_data_offset = 0; #ifndef FAUSTFLOAT  #define FAUSTFLOAT float#endif //-----------------------------------------------------------------------------// name: class FauckUI// desc: Faust ChucK UI -> map of complete hierarchical path and zones//-----------------------------------------------------------------------------class FauckUI : public UI, public PathBuilder{protected:    // name to pointer map    std::map<std::string, FAUSTFLOAT*> fZoneMap;        // insert into map    void insertMap( std::string label, FAUSTFLOAT * zone )    {        // map        fZoneMap[label] = zone;    }    public:    // constructor    FauckUI() { }    // destructor    virtual ~FauckUI() { }        // -- widget's layouts    void openTabBox(const char* label)    {        fControlsLevel.push_back(label);    }    void openHorizontalBox(const char* label)    {        fControlsLevel.push_back(label);    }    void openVerticalBox(const char* label)    {        fControlsLevel.push_back(label);    }    void closeBox()    {        fControlsLevel.pop_back();    }        // -- active widgets    void addButton(const char* label, FAUSTFLOAT* zone)    {        insertMap(buildPath(label), zone);    }    void addCheckButton(const char* label, FAUSTFLOAT* zone)    {        insertMap(buildPath(label), zone);    }    void addVerticalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT fmin, FAUSTFLOAT fmax, FAUSTFLOAT step)    {        insertMap(buildPath(label), zone);    }    void addHorizontalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT fmin, FAUSTFLOAT fmax, FAUSTFLOAT step)    {        insertMap(buildPath(label), zone);    }    void addNumEntry(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT fmin, FAUSTFLOAT fmax, FAUSTFLOAT step)    {        insertMap(buildPath(label), zone);    }        // -- passive widgets    void addHorizontalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT fmin, FAUSTFLOAT fmax)    {        insertMap(buildPath(label), zone);    }    void addVerticalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT fmin, FAUSTFLOAT fmax)    {        insertMap(buildPath(label), zone);    }     // -- soundfiles    void addSoundfile(const char* label, const char* filename, Soundfile** sf_zone)    {}        // -- metadata declarations    void declare(FAUSTFLOAT* zone, const char* key, const char* val)    {}        // set/get    void setValue( const std::string& path, FAUSTFLOAT value )    {        // append "/chuck/" if necessary        string p = path.length() > 0 && path[0] == '/' ? path : string("/chuck/")+path;         // TODO: should check if path valid?        if( fZoneMap.find(p) == fZoneMap.end() )        {            // error            cerr << "[Faust]: cannot set parameter named: " << path;            if( path != p ) cerr << " OR " << p << endl;            else cerr << endl;            return;        }                // set it!        *fZoneMap[p] = value;    }        float getValue(const std::string& path)    {        // append "/0x00/" if necessary        string p = path.length() > 0 && path[0] == '/' ? path : string("/0x00/")+path;         // TODO: should check if path valid?        if( fZoneMap.find(p) == fZoneMap.end() )        {            // error            cerr << "[Faust]: cannot get parameter named: " << path;            if( path != p ) cerr << " OR " << p << endl;            else cerr << endl;            return 0;        }                return *fZoneMap[path];    }        void dumpParams()    {        // iterator        std::map<std::string, FAUSTFLOAT*>::iterator iter = fZoneMap.begin();        // go        for( ; iter != fZoneMap.end(); iter++ )        {            // print            cerr << iter->first << " : " << *(iter->second) << endl;        }    }        // map access    std::map<std::string, FAUSTFLOAT*>& getMap() { return fZoneMap; }    // get map size    int getParamsCount() { return fZoneMap.size(); }    // get param path    std::string getParamPath(int index)    {        std::map<std::string, FAUSTFLOAT*>::iterator it = fZoneMap.begin();        while (index-- > 0 && it++ != fZoneMap.end()) {}        return (*it).first;    }}; //-----------------------------------------------------------------------------// name: class Faust// desc: class definition of internal chugin data//-----------------------------------------------------------------------------class Faust{public:    // constructor    Faust( t_CKFLOAT fs)    {        // sample rate        m_srate = fs;        // clear        m_factory = NULL;        m_dsp = NULL;        m_ui = NULL;        // zero        m_input = NULL;        m_output = NULL;        // default        m_numInputChannels = 0;        m_numOutputChannels = 0;        // auto import        m_autoImport = "// Faust Chugin auto import:\n \        import(\"stdfaust.lib\");\n";    }        // destructor    ~Faust()    {        // clear        clear();        clearBufs();    }        // clear    void clear()    {        // clean up, possibly        if( m_factory != NULL )        {            deleteDSPFactory( m_factory );            m_factory = NULL;        }        SAFE_DELETE(m_dsp);        SAFE_DELETE(m_ui);    }        // clear    void clearBufs()    {        if( m_input != NULL )        {            for( int i = 0; i < m_numInputChannels; i++ )                SAFE_DELETE_ARRAY(m_input[i]);        }        if( m_output != NULL )        {            for( int i = 0; i < m_numOutputChannels; i++ )                SAFE_DELETE_ARRAY(m_output[i]);        }        SAFE_DELETE_ARRAY(m_input);        SAFE_DELETE_ARRAY(m_output);    }        // allocate    void allocate( int inputChannels, int outputChannels )    {        // clear        clearBufs();                // set        m_numInputChannels = min(inputChannels, MAX_INPUTS);        m_numOutputChannels = min(outputChannels, MAX_OUTPUTS);         // allocate channels        m_input = new FAUSTFLOAT *[m_numInputChannels];        m_output = new FAUSTFLOAT *[m_numOutputChannels];        // allocate buffers for each channel        for( int i = 0; i < m_numInputChannels; i++ )        {            // single sample for each            m_input[i] = new FAUSTFLOAT[1];        }        for( int i = 0; i < m_numOutputChannels; i++ )        {            // single sample for each            m_output[i] = new FAUSTFLOAT[1];        }    }        // eval    bool eval( const string & code )    {        // clean up        clear();                // arguments        const int argc = 0;        const char ** argv = NULL;        // optimization level        const int optimize = -1;                // save        m_code = code;                // auto import        string theCode = m_autoImport + "\n" + code;                // create new factory        m_factory = createDSPFactoryFromString( "chuck", theCode,            argc, argv, "", m_errorString, optimize );                // check for error        if( m_errorString != "" )        {            // output error            cerr << "[Faust]: " << m_errorString << endl;            // clear            clear();            // done            return false;        }                // create DSP instance        m_dsp = m_factory ->createDSPInstance();                // make new UI        m_ui = new FauckUI();        // build ui        m_dsp->buildUserInterface( m_ui );                // get channels        int inputs = m_dsp->getNumInputs();        int outputs = m_dsp->getNumOutputs();                // see if we need to alloc        if( inputs > m_numInputChannels || outputs > m_numOutputChannels )        {            // clear and allocate            allocate( inputs, outputs );        }                // init        m_dsp->init( (int)(m_srate + .5) );                return true;    }     // compile    bool compile( const string & path )    {        // open file        ifstream fin( path.c_str() );        // check        if( !fin.good() )        {            // error            cerr << "[Faust]: ERROR opening file: '" << path << "'" << endl;            return false;        }                // clear code string        m_code = "";        // get it        for( string line; std::getline( fin, line ); )            m_code += line + '\n';                // eval it        return eval( m_code );    }        // dump (snapshot)    void dump()    {        if(m_errorString.empty()){        cerr << "---------------- DUMPING [Faust] PARAMETERS ---------------" << endl;        m_ui->dumpParams();        cerr << "Number of Inputs: " << m_numInputChannels << endl ;        cerr << "Number of Outputs: " << m_numOutputChannels << endl ;        cerr << "-----------------------------------------------------------" << endl;        } else{        cerr << "[Faust]: "<< m_errorString <<endl;        }    }        void tick( SAMPLE * in, SAMPLE * out, int nframes ){      if( m_dsp != NULL ){        for(int f = 0; f < nframes; f++)        {			          for(int c = 0; c < m_numInputChannels; c++)          {            m_input[c][0] = in[f*m_numInputChannels+c];          }          m_dsp->compute( 1, m_input, m_output );          for(int c = 0; c < m_numOutputChannels; c++)          {            out[f*m_numOutputChannels+c] = m_output[c][0];          }        }      }    }        // for Chugins extending UGen    /*    SAMPLE tick( SAMPLE in )    {        // sanity check        if( m_dsp == NULL ) return 0;                // set input        for( int i = 0; i < m_numInputChannels; i++ ) m_input[i][0] = in;        // zero output        for( int i = 0; i < m_numOutputChannels; i++ ) m_output[i][0] = 0;        // compute samples        m_dsp->compute( 1, m_input, m_output );        // average output        t_CKFLOAT avg = 0;        for( int i = 0; i < m_numOutputChannels; i++ ) avg += m_output[i][0];        // return sample        return avg / m_numOutputChannels;    }    */     // set parameter example    t_CKFLOAT setParam( const string & n, t_CKFLOAT p )    {        // sanity check        if( !m_ui ) return 0;         // set the value        m_ui->setValue( n, p );                // return        return p;    }     // get parameter example    t_CKFLOAT getParam( const string & n )    { return m_ui->getValue(n); }        // get code    string code() { return m_code; } private:    // sample rate    t_CKFLOAT m_srate;    // code text (pre any modifications)    string m_code;    // llvm factory    llvm_dsp_factory * m_factory;    // faust DSP object    dsp * m_dsp;    // faust compiler error string    string m_errorString;    // auto import    string m_autoImport;        // faust input buffer    FAUSTFLOAT ** m_input;    FAUSTFLOAT ** m_output;        // input and output    int m_numInputChannels;    int m_numOutputChannels;        // UI    FauckUI * m_ui;};    //-----------------------------------------------------------------------------// query function: chuck calls this when loading the Chugin// NOTE: developer will need to modify this function to// add additional functions to this Chugin//-----------------------------------------------------------------------------CK_DLL_QUERY( Faust ){    // hmm, don't change this...    QUERY->setname(QUERY, "Faust");        // begin the class definition    // can change the second argument to extend a different ChucK class    QUERY->begin_class(QUERY, "Faust", "UGen");     // register the constructor (probably no need to change)    QUERY->add_ctor(QUERY, faust_ctor);    // register the destructor (probably no need to change)    QUERY->add_dtor(QUERY, faust_dtor);        // for UGen's only: add tick function

Lines 1–500 of 685.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t