//-----------------------------------------------------------------------------// 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 functionLines 1–500 of 685. Load more
//----------------------------------------------------------------------------- // 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 constructor CK_DLL_CTOR(faust_ctor); // declaration of chugin desctructor CK_DLL_DTOR(faust_dtor); // multi-channel audio synthesis tick function CK_DLL_TICKF(faust_tickf); // example of getter/setter CK_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 data t_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