-/************************************************************************
-
- 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) 2004-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 Lesser 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 Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program; If not, see <http://www.gnu.org/licenses/>.
-
- 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.
-
- MAX MSP SDK : in order to compile a MaxMSP external with this
- architecture file you will need the official MaxMSP SDK from
- cycling'74. Please check the corresponding license.
-
- ************************************************************************
- ************************************************************************/
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <limits.h>
-#include <math.h>
-#include <errno.h>
-#include <time.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <assert.h>
-#include <string>
-#include <vector>
-#include <map>
-#include <math.h>
-
-#ifdef __APPLE__
-#include <Carbon/Carbon.h>
-#include <unistd.h>
-#endif
-
-#include "gui/GUI.h"
-#include "audio/dsp.h"
-#include "misc.h"
-
-using namespace std ;
-
-// There is a bug with powf() when cross compiling with mingw
-// the following macro avoid the problem
-#ifdef WIN32
-#define powf(x,y) pow(x,y)
-#define expf(x) exp(x)
-#endif
-
-#ifdef __GNUC__
-
-//-------------------------------------------------------------------
-// Generic min and max using gcc extensions
-//-------------------------------------------------------------------
-
-#define max(x,y) (((x)>(y)) ? (x) : (y))
-#define min(x,y) (((x)<(y)) ? (x) : (y))
-
-#else
-
-//-------------------------------------------------------------------
-// Generic min and max using c++ inline
-//-------------------------------------------------------------------
-
-inline int max(unsigned int a, unsigned int b) { return (a>b) ? a : b; }
-inline int max(int a, int b) { return (a>b) ? a : b; }
-
-inline long max(long a, long b) { return (a>b) ? a : b; }
-inline long max(int a, long b) { return (a>b) ? a : b; }
-inline long max(long a, int b) { return (a>b) ? a : b; }
-
-inline float max(float a, float b) { return (a>b) ? a : b; }
-inline float max(int a, float b) { return (a>b) ? a : b; }
-inline float max(float a, int b) { return (a>b) ? a : b; }
-inline float max(long a, float b) { return (a>b) ? a : b; }
-inline float max(float a, long b) { return (a>b) ? a : b; }
-
-inline double max(double a, double b) { return (a>b) ? a : b; }
-inline double max(int a, double b) { return (a>b) ? a : b; }
-inline double max(double a, int b) { return (a>b) ? a : b; }
-inline double max(long a, double b) { return (a>b) ? a : b; }
-inline double max(double a, long b) { return (a>b) ? a : b; }
-inline double max(float a, double b) { return (a>b) ? a : b; }
-inline double max(double a, float b) { return (a>b) ? a : b; }
-
-
-inline int min(int a, int b) { return (a<b) ? a : b; }
-
-inline long min(long a, long b) { return (a<b) ? a : b; }
-inline long min(int a, long b) { return (a<b) ? a : b; }
-inline long min(long a, int b) { return (a<b) ? a : b; }
-
-inline float min(float a, float b) { return (a<b) ? a : b; }
-inline float min(int a, float b) { return (a<b) ? a : b; }
-inline float min(float a, int b) { return (a<b) ? a : b; }
-inline float min(long a, float b) { return (a<b) ? a : b; }
-inline float min(float a, long b) { return (a<b) ? a : b; }
-
-inline double min(double a, double b) { return (a<b) ? a : b; }
-inline double min(int a, double b) { return (a<b) ? a : b; }
-inline double min(double a, int b) { return (a<b) ? a : b; }
-inline double min(long a, double b) { return (a<b) ? a : b; }
-inline double min(double a, long b) { return (a<b) ? a : b; }
-inline double min(float a, double b) { return (a<b) ? a : b; }
-inline double min(double a, float b) { return (a<b) ? a : b; }
-
-#endif
-
-/******************************************************************************
-*******************************************************************************
-
- VECTOR INTRINSICS
-
-*******************************************************************************
-*******************************************************************************/
-
-<<includeIntrinsic>>
-
-/********************END ARCHITECTURE SECTION (part 1/2)****************/
-
-/**************************BEGIN USER SECTION **************************/
-
-<<includeclass>>
-
-/***************************END USER SECTION ***************************/
-
-/*******************BEGIN ARCHITECTURE SECTION (part 2/2)***************/
-
-
-/* Faust code wrapper ------- */
-
-#include "ext.h"
-#include "z_dsp.h"
-#include <string.h>
-
-#define ASSIST_INLET 1 /* should be defined somewhere ?? */
-#define ASSIST_OUTLET 2 /* should be defined somewhere ?? */
-
-class mspUI;
-
-/*--------------------------------------------------------------------------*/
-typedef struct faust
-{
- t_pxobject m_ob;
- t_atom *m_seen,*m_want;
- short m_where;
- void** args;
- mspUI* dspUI;
- mydsp* dsp;
-} t_faust;
-
-void *faust_class;
-
-/*--------------------------------------------------------------------------*/
-class mspUIObject {
-
- protected:
-
- string fLabel;
- float* fZone;
-
- float range(float min, float max, float val) {return (val < min) ? min : (val > max) ? max : val;}
-
- public:
-
- mspUIObject(const char* label, float* zone):fLabel(label),fZone(zone) {}
- virtual ~mspUIObject() {}
-
- virtual void SetValue(double f) {*fZone = range(0.0,1.0,f);}
- virtual void toString(char* buffer) {}
- virtual string GetName() {return fLabel;}
-};
-
-/*--------------------------------------------------------------------------*/
-class mspToggleButton : public mspUIObject {
-
- public:
-
- mspToggleButton(const char* label, float* zone):mspUIObject(label,zone) {}
- virtual ~mspToggleButton() {}
-
- void toString(char* buffer)
- {
- #ifdef WIN32
- sprintf(buffer, "ToggleButton(float): %s", fLabel.c_str());
- #else
- std::sprintf(buffer, "ToggleButton(float): %s", fLabel.c_str());
- #endif
- }
-};
-
-/*--------------------------------------------------------------------------*/
-class mspCheckButton : public mspUIObject {
-
- public:
-
- mspCheckButton(const char* label, float* zone):mspUIObject(label,zone) {}
- virtual ~mspCheckButton() {}
-
- void toString(char* buffer)
- {
- #ifdef WIN32
- sprintf(buffer, "CheckButton(float): %s", fLabel.c_str());
- #else
- std::sprintf(buffer, "CheckButton(float): %s", fLabel.c_str());
- #endif
- }
-};
-
-/*--------------------------------------------------------------------------*/
-class mspButton : public mspUIObject {
-
- public:
-
- mspButton(const char* label, float* zone):mspUIObject(label,zone) {}
- virtual ~mspButton() {}
-
- void toString(char* buffer)
- {
- #ifdef WIN32
- sprintf(buffer, "Button(float): %s", fLabel.c_str());
- #else
- std::sprintf(buffer, "Button(float): %s", fLabel.c_str());
- #endif
- }
-};
-
-/*--------------------------------------------------------------------------*/
-class mspSlider : public mspUIObject{
-
- private:
-
- float fInit;
- float fMin;
- float fMax;
- float fStep;
-
- public:
-
- mspSlider(const char* label, float* zone, float init, float min, float max, float step)
- :mspUIObject(label,zone),fInit(init),fMin(min),fMax(max),fStep(step) {}
- virtual ~mspSlider() {}
-
- void toString(char* buffer)
- {
- #ifdef WIN32
- sprintf(buffer, "Slider(float): %s [%.1f:%.1f:%.1f]", fLabel.c_str(), fMin, fInit, fMax);
- #else
- std::sprintf(buffer, "Slider(float): %s [%.1f:%.1f:%.1f]", fLabel.c_str(), fMin, fInit, fMax);
- #endif
- }
-
- void SetValue(double f) {*fZone = range(fMin,fMax,f);}
-};
-
-/*--------------------------------------------------------------------------*/
-class mspUI : public UI
-{
- private:
-
- map<string,mspUIObject*> fUITable;
-
- public:
- typedef map<string,mspUIObject*>::iterator iterator;
-
- mspUI(){}
- virtual ~mspUI()
- {
- for (iterator iter = fUITable.begin(); iter != fUITable.end(); iter++)
- delete (iter->second);
- }
-
- void addButton(const char* label, float* zone) {fUITable[string(label)] = new mspButton(label, zone);}
-
- void addToggleButton(const char* label, float* zone) {fUITable[string(label)] = new mspToggleButton(label, zone);}
-
- void addCheckButton(const char* label, float* zone) {fUITable[string(label)] = new mspCheckButton(label, zone);}
-
- void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step)
- {
- fUITable[string(label)] = new mspSlider(label, zone, init, min, max, step);
- }
-
- void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step)
- {
- fUITable[string(label)] = new mspSlider(label, zone, init, min, max, step);
- }
-
- void addNumEntry(const char* label, float* zone, float init, float min, float max, float step)
- {
- fUITable[string(label)] = new mspSlider(label, zone, init, min, max, step);
- }
-
- void openFrameBox(const char* label) {}
- void openTabBox(const char* label) {}
- void openHorizontalBox(const char* label) {}
- void openVerticalBox(const char* label) {}
- void closeBox() {}
-
- void SetValue(string name, double f)
- {
- if(fUITable.count(name))
- fUITable[name]->SetValue(f);
- }
- iterator begin() {return fUITable.begin();}
- iterator end() {return fUITable.end();}
-
- // To be implemented
- void addNumDisplay(const char* label, float* zone, int precision) {}
- void addTextDisplay(const char* label, float* zone, const char* names[], float min, float max) {}
- void addHorizontalBargraph(const char* label, float* zone, float min, float max) {}
- void addVerticalBargraph(const char* label, float* zone, float min, float max) {}
-};
-
-//--------------------------------------------------------------------------
-void faust_method(t_faust *obj, t_symbol *s, short ac, t_atom *at)
-{
- if(ac < 0) return;
- if(at[0].a_type != A_FLOAT) return;
-
- string name = string( (s)->s_name );
- float value = at[0].a_w.w_float;
-
- // lookup du nom dans une std::map<string,mspUIObject *>
- // ou une std::map<string,float *>
- // et affectation de value;
- obj->dspUI->SetValue(name,value); // doesn't have any effect if name is unknown
-}
-
-/*--------------------------------------------------------------------------*/
-void *faust_new(t_symbol *s, short ac, t_atom *av)
-{
- t_faust *x = (t_faust *)newobject(faust_class);
-
- x->dsp = new mydsp();
- x->dspUI= new mspUI();
-
- x->dsp->init(long(sys_getsr()));
- x->dsp->buildUserInterface(x->dspUI);
-
- x->args = (void**)calloc((x->dsp->getNumInputs()+x->dsp->getNumOutputs())+2, sizeof(void*));
-
- /* Multi in */
- dsp_setup((t_pxobject *)x, x->dsp->getNumInputs());
-
- /* Multi out */
- for (int i = 0; i< x->dsp->getNumOutputs(); i++)
- outlet_new((t_pxobject *)x, (char*)"signal");
-
- ((t_pxobject *)x)->z_misc = Z_NO_INPLACE; // To assure input and output buffers are actually different
- return x;
-}
-
-/*--------------------------------------------------------------------------*/
-void faust_assist(t_faust *x, void *b, long msg, long a, char *dst)
-{
- if (msg == ASSIST_INLET) {
- if (a == 0) {
- if (x->dsp->getNumInputs() == 0) {
- #ifdef WIN32
- sprintf(dst, "(signal) : Unused Input");
- #else
- std::sprintf(dst, "(signal) : Unused Input");
- #endif
- } else {
- #ifdef WIN32
- sprintf(dst, "(signal) : Audio Input %ld", (a+1));
- #else
- std::sprintf(dst, "(signal) : Audio Input %ld", (a+1));
- #endif
- }
- post((char*)"------------------");
- for (mspUI::iterator it = x->dspUI->begin(); it != x->dspUI->end(); ++it) {
- char param[64];
- it->second->toString(param);
- post(param);
- }
- } else if (a < x->dsp->getNumInputs()) {
- #ifdef WIN32
- sprintf(dst, "(signal) : Audio Input %ld", (a+1));
- #else
- std::sprintf(dst, "(signal) : Audio Input %ld", (a+1));
- #endif
- }
- } else if (msg == ASSIST_OUTLET) {
- #ifdef WIN32
- sprintf(dst, "(signal) : Audio Output %ld", (a+1));
- #else
- std::sprintf(dst, "(signal) : Audio Output %ld", (a+1));
- #endif
- }
-}
-
-/*--------------------------------------------------------------------------*/
-void faust_free(t_faust *x)
-{
- dsp_free((t_pxobject *)x);
- if (x->dsp) delete x->dsp;
- if (x->dspUI) delete x->dspUI;
- if (x->args)free(x->args);
-}
-
-/*--------------------------------------------------------------------------*/
-t_int *faust_perform(t_int *w)
-{
- t_faust* x = (t_faust*) (w[1]);
- long n = w[2];
- int offset = 3;
- AVOIDDENORMALS;
- x->dsp->compute(n, ((float**)&w[offset]), ((float**)&w[offset+x->dsp->getNumInputs()]));
- return (w + (x->dsp->getNumInputs()+x->dsp->getNumOutputs())+2+1);
-}
-
-/*--------------------------------------------------------------------------*/
-void faust_dsp(t_faust *x, t_signal **sp, short *count)
-{
- x->args[0] = x;
- x->args[1] = (void*)sp[0]->s_n;
- for (int i = 0; i<(x->dsp->getNumInputs()+x->dsp->getNumOutputs()); i++)
- x->args[i+2] = sp[i]->s_vec;
- dsp_addv(faust_perform, (x->dsp->getNumInputs()+x->dsp->getNumOutputs())+2, x->args);
-}
-
-/*--------------------------------------------------------------------------*/
-int main()
-{
- setup((t_messlist **)&faust_class, (method)faust_new, (method)faust_free,
- (short)sizeof(t_faust), 0L, A_DEFFLOAT, 0);
-
- dsp *thedsp = new mydsp();
- mspUI *dspUI= new mspUI();
- thedsp->buildUserInterface(dspUI);
-
- // Add the same method for every parameters and use the symbol as a selector
- // inside thid method
- for (mspUI::iterator it = dspUI->begin(); it != dspUI->end(); ++it) {
- char *name = const_cast<char *>(it->second->GetName().c_str());
- addmess((method)faust_method, name, A_GIMME, 0);
- }
-
- addmess((method)faust_dsp, (char*)"dsp", A_CANT, 0);
- addmess((method)faust_assist, (char*)"assist", A_CANT, 0);
- dsp_initclass();
-
- delete(dspUI);
- delete(thedsp);
- post((char*)"Faust DSP object");
- return 0;
-}
-
-/********************END ARCHITECTURE SECTION (part 2/2)****************/
-
-
-
-