X-Git-Url: https://scm.cri.ensmp.fr/git/Faustine.git/blobdiff_plain/1059e1cc0c2ecfa237406949aa26155b6a5b9154..66f23d4fabf89ad09adbd4dfc15ac6b5b2b7da83:/interpreter/preprocessor/faust-0.9.47mr3/architecture/jack-internal.cpp diff --git a/interpreter/preprocessor/faust-0.9.47mr3/architecture/jack-internal.cpp b/interpreter/preprocessor/faust-0.9.47mr3/architecture/jack-internal.cpp new file mode 100644 index 0000000..0df7fd0 --- /dev/null +++ b/interpreter/preprocessor/faust-0.9.47mr3/architecture/jack-internal.cpp @@ -0,0 +1,825 @@ +/************************************************************************ + + 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) 2003-2011 GRAME, Centre National de Creation Musicale + --------------------------------------------------------------------- + This Architecture section 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 3 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, see . + + EXCEPTION : As a special exception, you may create a larger work + that contains this FAUST architecture section and distribute + that work under terms of your choice, so long as this FAUST + architecture section is not modified. + + + ************************************************************************ + ************************************************************************/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +using namespace std; + +// On Intel set FZ (Flush to Zero) and DAZ (Denormals Are Zero) +// flags to avoid costly denormals +#ifdef __SSE__ + #include + #ifdef __SSE2__ + #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8040) + #else + #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8000) + #endif +#else + #define AVOIDDENORMALS +#endif + +struct Meta : map +{ + 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 T abs (T a) { return (a> 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); } + +<> + + +/****************************************************************************** +******************************************************************************* + + GRAPHIC USER INTERFACE (v2) + abstract interfaces + +******************************************************************************* +*******************************************************************************/ + +using namespace std; + + +struct uiItem; +typedef void (*uiCallback)(float val, void* data); + +/** + * Graphic User Interface : abstract definition + */ + +class UI +{ + typedef list clist; + typedef map zmap; + + private: + static list fGuiList; + zmap fZoneMap; + bool fStopped; + + public: + + UI() : fStopped(false) { + fGuiList.push_back(this); + } + + virtual ~UI() { + // suppression de this dans fGuiList + } + + // -- zone management + + void registerZone(float* z, uiItem* c) + { + if (fZoneMap.find(z) == fZoneMap.end()) fZoneMap[z] = new clist(); + fZoneMap[z]->push_back(c); + } + + void updateAllZones(); + + void updateZone(float* z); + + static void updateAllGuis() + { + list::iterator g; + for (g = fGuiList.begin(); g != fGuiList.end(); g++) { + (*g)->updateAllZones(); + } + } + + // -- 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; + + void addCallback(float* zone, uiCallback foo, void* data); + + // -- widget's layouts + + 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 declare(float* zone, const char* key, const char* value) {} +}; + +class OSCUI : public UI +{ + public: + + OSCUI() : UI() + {} + + virtual ~OSCUI() { + // suppression de this dans fGuiList + } + + + // -- active widgets + + virtual void addButton(const char* label, float* zone) {} + virtual void addToggleButton(const char* label, float* zone) {} + virtual void addCheckButton(const char* label, float* zone) {} + virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step) {} + virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step) {} + virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step) {} + + // -- 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) {} + + void addCallback(float* zone, uiCallback foo, void* data); + + // -- widget's layouts + + 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 closeBox() {} + + virtual void declare(float* zone, const char* key, const char* value) {} +}; + +list UI::fGuiList; + +/** + * User Interface Item: abstract definition + */ + +class uiItem +{ + protected : + + UI* fGUI; + float* fZone; + float fCache; + + uiItem (UI* ui, float* zone) : fGUI(ui), fZone(zone), fCache(-123456.654321) + { + ui->registerZone(zone, this); + } + + public : + + virtual ~uiItem() {} + + void modifyZone(float v) + { + fCache = v; + if (*fZone != v) { + *fZone = v; + fGUI->updateZone(fZone); + } + } + + float cache() { return fCache; } + virtual void reflectZone() = 0; +}; + + +/** + * Callback Item + */ + +struct uiCallbackItem : public uiItem +{ + uiCallback fCallback; + void* fData; + + uiCallbackItem(UI* ui, float* zone, uiCallback foo, void* data) + : uiItem(ui, zone), fCallback(foo), fData(data) {} + + virtual void reflectZone() { + float v = *fZone; + fCache = v; + fCallback(v, fData); + } +}; + +/** + * Update all user items reflecting zone z + */ + +inline void UI::updateZone(float* z) +{ + float v = *z; + clist* l = fZoneMap[z]; + for (clist::iterator c = l->begin(); c != l->end(); c++) { + if ((*c)->cache() != v) (*c)->reflectZone(); + } +} + +/** + * Update all user items not up to date + */ + +inline void UI::updateAllZones() +{ + for (zmap::iterator m = fZoneMap.begin(); m != fZoneMap.end(); m++) { + float* z = m->first; + clist* l = m->second; + float v = *z; + for (clist::iterator c = l->begin(); c != l->end(); c++) { + if ((*c)->cache() != v) (*c)->reflectZone(); + } + } +} + +inline void UI::addCallback(float* zone, uiCallback foo, void* data) +{ + new uiCallbackItem(this, zone, foo, data); +}; + +//---------------------------------------------------------------- +// definition du processeur de signal +//---------------------------------------------------------------- + +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; + virtual void conclude() {} +}; + + +/********************END ARCHITECTURE SECTION (part 1/2)****************/ + +/**************************BEGIN USER SECTION **************************/ + +<> + +/***************************END USER SECTION ***************************/ + +/*******************BEGIN ARCHITECTURE SECTION (part 2/2)***************/ + + +/****************************************************************************** +******************************************************************************* + + JACK AUDIO INTERFACE + +******************************************************************************* +*******************************************************************************/ + +#define JACK_DRIVER_NAME_MAX 15 +#define JACK_DRIVER_PARAM_NAME_MAX 15 +#define JACK_DRIVER_PARAM_STRING_MAX 63 +#define JACK_DRIVER_PARAM_DESC 255 +#define JACK_PATH_MAX 511 + +/** Driver parameter types */ +typedef enum +{ + JackDriverParamInt = 1, + JackDriverParamUInt, + JackDriverParamChar, + JackDriverParamString, + JackDriverParamBool +} jack_driver_param_type_t; + +/** Driver parameter value */ +typedef union +{ + uint32_t ui; + int32_t i; + char c; + char str[JACK_DRIVER_PARAM_STRING_MAX + 1]; +} jack_driver_param_value_t; + + +/** A driver parameter descriptor */ +typedef struct { + char name[JACK_DRIVER_NAME_MAX + 1]; /**< The parameter's name */ + char character; /**< The parameter's character (for getopt, etc) */ + jack_driver_param_type_t type; /**< The parameter's type */ + jack_driver_param_value_t value; /**< The parameter's (default) value */ + char short_desc[64]; /**< A short (~30 chars) description for the user */ + char long_desc[1024]; /**< A longer description for the user */ +} +jack_driver_param_desc_t; + +/** A driver parameter */ +typedef struct { + char character; + jack_driver_param_value_t value; +} +jack_driver_param_t; + +/** A struct for describing a jack driver */ +typedef struct { + char name[JACK_DRIVER_NAME_MAX + 1]; /**< The driver's canonical name */ + char desc[JACK_DRIVER_PARAM_DESC + 1]; /**< The driver's extended description */ + char file[JACK_PATH_MAX + 1]; /**< The filename of the driver's shared object file */ + uint32_t nparams; /**< The number of parameters the driver has */ + jack_driver_param_desc_t * params; /**< An array of parameter descriptors */ +} +jack_driver_desc_t; + +// class JackArgParser *************************************************** +class JackArgParser +{ + private: + + std::string fArgString; + int fArgc; + std::vector fArgv; + + public: + + JackArgParser (const char* arg); + ~JackArgParser(); + std::string GetArgString(); + int GetNumArgv(); + int GetArgc(); + int GetArgv (std::vector& argv); + int GetArgv (char** argv); + void DeleteArgv (const char** argv); + void ParseParams (jack_driver_desc_t* desc, JSList** param_list); + void FreeParams (JSList* param_list); +}; + +JackArgParser::JackArgParser (const char* arg) +{ + printf ("JackArgParser::JackArgParser, arg_string : '%s' \n", arg); + + fArgc = 0; + //if empty string + if (strlen(arg) == 0) + return; + fArgString = string(arg); + //else parse the arg string + const size_t arg_len = fArgString.length(); + unsigned int i = 0; + size_t pos = 0; + size_t start = 0; + size_t copy_start = 0; + size_t copy_length = 0; + //we need a 'space terminated' string + fArgString += " "; + //first fill a vector with args + do { + //find the first non-space character from the actual position + start = fArgString.find_first_not_of (' ', start); + //get the next quote or space position + pos = fArgString.find_first_of (" \"" , start); + //no more quotes or spaces, consider the end of the string + if (pos == string::npos) + pos = arg_len; + //if double quote + if (fArgString[pos] == '\"') { + //first character : copy the substring + if (pos == start) { + copy_start = start + 1; + pos = fArgString.find ('\"', ++pos); + copy_length = pos - copy_start; + start = pos + 1; + } + //else there is someting before the quote, first copy that + else { + copy_start = start; + copy_length = pos - copy_start; + start = pos; + } + } + //if space + if (fArgString[pos] == ' ') { + //short option descriptor + if ((fArgString[start] == '-') && (fArgString[start + 1] != '-')) { + copy_start = start; + copy_length = 2; + start += copy_length; + } + //else copy all the space delimitated string + else { + copy_start = start; + copy_length = pos - copy_start; + start = pos + 1; + } + } + //then push the substring to the args vector + fArgv.push_back (fArgString.substr (copy_start, copy_length)); + printf("JackArgParser::JackArgParser, add : '%s' \n", (*fArgv.rbegin()).c_str()); + } while (start < arg_len); + + //finally count the options + for (i = 0; i < fArgv.size(); i++) + if (fArgv[i].at(0) == '-') + fArgc++; +} + +JackArgParser::~JackArgParser() +{} + +string JackArgParser::GetArgString() +{ + return fArgString; +} + +int JackArgParser::GetNumArgv() +{ + return fArgv.size(); +} + +int JackArgParser::GetArgc() +{ + return fArgc; +} + +int JackArgParser::GetArgv(vector& argv) +{ + argv = fArgv; + return 0; +} + +int JackArgParser::GetArgv(char** argv) +{ + //argv must be NULL + if (argv) + return -1; + //else allocate and fill it + argv = (char**)calloc(fArgv.size(), sizeof(char*)); + for (unsigned int i = 0; i < fArgv.size(); i++) { + argv[i] = (char*)calloc(fArgv[i].length(), sizeof(char)); + fill_n(argv[i], fArgv[i].length() + 1, 0); + fArgv[i].copy(argv[i], fArgv[i].length()); + } + return 0; +} + +void JackArgParser::DeleteArgv(const char** argv) +{ + unsigned int i; + for (i = 0; i < fArgv.size(); i++) + free((void*)argv[i]); + free((void*)argv); +} + +void JackArgParser::ParseParams(jack_driver_desc_t* desc, JSList** param_list) +{ + string options_list; + unsigned long i = 0; + unsigned int param = 0; + size_t param_id = 0; + JSList* params = NULL; + jack_driver_param_t* intclient_param; + + for (i = 0; i < desc->nparams; i++) + options_list += desc->params[i].character; + + for (param = 0; param < fArgv.size(); param++) + { + if (fArgv[param][0] == '-') + { + //valid option + if ((param_id = options_list.find_first_of(fArgv[param].at(1))) != string::npos) + { + intclient_param = static_cast(calloc(1, sizeof(jack_driver_param_t))); + intclient_param->character = desc->params[param_id].character; + + switch (desc->params[param_id].type) + { + case JackDriverParamInt: + if (param + 1 < fArgv.size()) // something to parse + intclient_param->value.i = atoi(fArgv[param + 1].c_str()); + break; + + case JackDriverParamUInt: + if (param + 1 < fArgv.size()) // something to parse + intclient_param->value.ui = strtoul(fArgv[param + 1].c_str(), NULL, 10); + break; + + case JackDriverParamChar: + if (param + 1 < fArgv.size()) // something to parse + intclient_param->value.c = fArgv[param + 1][0]; + break; + + case JackDriverParamString: + if (param + 1 < fArgv.size()) // something to parse + fArgv[param + 1].copy(intclient_param->value.str, min(static_cast(fArgv[param + 1].length()), JACK_DRIVER_PARAM_STRING_MAX)); + break; + + case JackDriverParamBool: + intclient_param->value.i = true; + break; + } + //add to the list + params = jack_slist_append(params, intclient_param); + } + //invalid option + else + printf("Invalid option '%c'\n", fArgv[param][1]); + } + } + + assert(param_list); + *param_list = params; +} + +void JackArgParser::FreeParams(JSList* param_list) +{ + JSList *node_ptr = param_list; + JSList *next_node_ptr; + + while (node_ptr) { + next_node_ptr = node_ptr->next; + free(node_ptr->data); + free(node_ptr); + node_ptr = next_node_ptr; + } +} + +struct JackFaustInternal { + + //---------------------------------------------------------------------------- + // number of input and output channels + //---------------------------------------------------------------------------- + + int fNumInChans; + int fNumOutChans; + + //---------------------------------------------------------------------------- + // Jack ports + //---------------------------------------------------------------------------- + + jack_port_t* fInputPorts[256]; + jack_port_t* fOutputPorts[256]; + + //---------------------------------------------------------------------------- + // tables of noninterleaved input and output channels for FAUST + //---------------------------------------------------------------------------- + + float* fInChannel[256]; + float* fOutChannel[256]; + + jack_client_t* fClient; + UI* fInterface; + mydsp fDSP; + + JackFaustInternal(jack_client_t* client, const JSList* params) + :fClient(client) + {} + + ~JackFaustInternal() + { + delete fInterface; + } + + int Open() + { + char** physicalInPorts; + char** physicalOutPorts; + + fInterface = new OSCUI(); + fDSP.buildUserInterface(fInterface); + + jack_set_process_callback(fClient, process, this); + jack_set_sample_rate_callback(fClient, srate, this); + + fNumInChans = fDSP.getNumInputs(); + fNumOutChans = fDSP.getNumOutputs(); + + for (int i = 0; i < fNumInChans; i++) { + char buf[256]; + snprintf(buf, 256, "in_%d", i); + fInputPorts[i] = jack_port_register(fClient, buf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); + } + for (int i = 0; i < fNumOutChans; i++) { + char buf[256]; + snprintf(buf, 256, "out_%d", i); + fOutputPorts[i] = jack_port_register(fClient, buf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); + } + + fDSP.init(jack_get_sample_rate(fClient)); + + physicalInPorts = (char **)jack_get_ports(fClient, NULL, NULL, JackPortIsPhysical|JackPortIsInput); + physicalOutPorts = (char **)jack_get_ports(fClient, NULL, NULL, JackPortIsPhysical|JackPortIsOutput); + + if (jack_activate(fClient)) { + fprintf(stderr, "cannot activate client"); + return -1; + } + + if (physicalOutPorts != NULL) { + for (int i = 0; i < fNumInChans && physicalOutPorts[i]; i++) { + jack_connect(fClient, physicalOutPorts[i], jack_port_name(fInputPorts[i])); + } + } + + if (physicalInPorts != NULL) { + for (int i = 0; i < fNumOutChans && physicalInPorts[i]; i++) { + jack_connect(fClient, jack_port_name(fOutputPorts[i]), physicalInPorts[i]); + } + } + + return 0; + } + + //---------------------------------------------------------------------------- + // Jack Callbacks + //---------------------------------------------------------------------------- + + static int srate(jack_nframes_t nframes, void *arg) + { + printf("the sample rate is now %u/sec\n", nframes); + return 0; + } + + static int process(jack_nframes_t nframes, void *arg) + { + JackFaustInternal* obj = (JackFaustInternal*)arg; + AVOIDDENORMALS; + + for (int i = 0; i < obj->fNumInChans; i++) { + obj->fInChannel[i] = (float *)jack_port_get_buffer(obj->fInputPorts[i], nframes); + } + for (int i = 0; i < obj->fNumOutChans; i++) { + obj->fOutChannel[i] = (float *)jack_port_get_buffer(obj->fOutputPorts[i], nframes); + } + obj->fDSP.compute(nframes, obj->fInChannel, obj->fOutChannel); + + return 0; + } + +}; + +#ifdef __cplusplus +extern "C" +{ +#endif + +jack_driver_desc_t* jack_get_descriptor() +{ + jack_driver_desc_t *desc; + unsigned int i; + desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t)); + + strcpy(desc->name, "faust"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 + strcpy(desc->desc, " Faust generated internal"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 + + desc->nparams = 0; + /* + desc->nparams = 2; + desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t)); + + i = 0; + strcpy(desc->params[i].name, "channels"); + desc->params[i].character = 'c'; + desc->params[i].type = JackDriverParamInt; + desc->params[i].value.ui = 0; + strcpy(desc->params[i].short_desc, "Maximum number of channels"); + strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + + i++; + strcpy(desc->params[i].name, "inchannels"); + desc->params[i].character = 'i'; + desc->params[i].type = JackDriverParamInt; + desc->params[i].value.ui = 0; + strcpy(desc->params[i].short_desc, "Maximum number of input channels"); + strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + */ + + return desc; +} + +int jack_internal_initialize(jack_client_t* client, const JSList* params) +{ + try { + + JackFaustInternal* internal = new JackFaustInternal(client, params); + if (internal->Open() == 0) { + return 0; + } else { + delete internal; + return 1; + } + + } catch (...) { + return 1; + } +} + +int jack_initialize(jack_client_t* client, const char* load_init) +{ + JSList* params = NULL; + jack_driver_desc_t *desc = jack_get_descriptor(); + + JackArgParser parser(load_init); + if (parser.GetArgc() > 0) + parser.ParseParams(desc, ¶ms); + + int res = jack_internal_initialize(client, params); + parser.FreeParams(params); + return res; +} + +void jack_finish(void* arg) +{ + JackFaustInternal* internal = static_cast(arg); + + if (internal) { + printf("Unloading internal\n"); + delete internal; + } +} + +#ifdef __cplusplus +} +#endif + + +/********************END ARCHITECTURE SECTION (part 2/2)****************/ + +