+++ /dev/null
-// If other than 'faust2sc --prefix Faust' is used, sed this as well:
-#define SC_FAUST_PREFIX "Faust"
-
-//-------------------------------------------------------------------
-// FAUST architecture file for SuperCollider.
-// Copyright (C) 2005-2008 Stefan Kersten.
-//
-// 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 <ctype.h>
-#include <limits.h>
-#include <map>
-#include <string>
-#include <string.h>
-#include <SC_PlugIn.h>
-
-#if defined(__GNUC__) && __GNUC__ >= 4
-# define FAUST_EXPORT __attribute__((visibility("default")))
-#else
-# define FAUST_EXPORT /* NOP */
-#endif
-
-//-------------------------------------------------------------------
-// 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; }
-
-inline int lsr (int x, int n) { return int(((unsigned int)x) >> n); }
-inline int int2pow2 (int x) { int r=0; while ((1<<r)<x) r++; return r; }
-
-
-/******************************************************************************
-*******************************************************************************
-
- 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>>
-
-/******************************************************************************
-*******************************************************************************
-
- META DATA
-
-*******************************************************************************
-*******************************************************************************/
-
-struct Meta : std::map<std::string, std::string>
-{
- void declare(const char* key, const char* value)
- {
- (*this)[key] = value;
- }
-};
-
-/******************************************************************************
-*******************************************************************************
-
- GRAPHIC USER INTERFACE
-
-*******************************************************************************
-*******************************************************************************/
-
-//----------------------------------------------------------------------------
-// Abstract user interface
-//----------------------------------------------------------------------------
-
-class UI
-{
-public:
- 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;
-
- // layout widgets
- 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) {}
-};
-
-//----------------------------------------------------------------------------
-// Control counter
-//----------------------------------------------------------------------------
-
-class ControlCounter : public UI
-{
-public:
- ControlCounter()
- : mNumControlInputs(0),
- mNumControlOutputs(0)
- { }
-
- size_t getNumControls() const { return getNumControlInputs(); }
- size_t getNumControlInputs() const { return mNumControlInputs; }
- size_t getNumControlOutputs() const { return mNumControlOutputs; }
-
- // active widgets
- virtual void addButton(const char* label, float* zone)
- { addControlInput(); }
- virtual void addToggleButton(const char* label, float* zone)
- { addControlInput(); }
- virtual void addCheckButton(const char* label, float* zone)
- { addControlInput(); }
- virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step)
- { addControlInput(); }
- virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step)
- { addControlInput(); }
- virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step)
- { addControlInput(); }
-
- // passive widgets
- virtual void addNumDisplay(const char* label, float* zone, int precision) { addControlOutput(); }
- virtual void addTextDisplay(const char* label, float* zone, char* names[], float min, float max) { addControlOutput(); }
- virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) { addControlOutput(); }
- virtual void addVerticalBargraph(const char* label, float* zone, float min, float max) { addControlOutput(); }
-
- // layout widgets
- 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() { }
-
-protected:
- void addControlInput() { mNumControlInputs++; }
- void addControlOutput() { mNumControlOutputs++; }
-
-private:
- size_t mNumControlInputs;
- size_t mNumControlOutputs;
-};
-
-//----------------------------------------------------------------------------
-// UI control
-//----------------------------------------------------------------------------
-
-struct Control
-{
- typedef void (*UpdateFunction)(Control* self, float value);
-
- UpdateFunction updateFunction;
- float min, max, step;
- float* zone;
-
- inline void update(float value)
- {
- (*updateFunction)(this, value);
- }
-
- static void simpleUpdate(Control* self, float value)
- {
- *self->zone = value;
- }
- static void boundedUpdate(Control* self, float value)
- {
- *self->zone = sc_clip(value, self->min, self->max);
- }
-};
-
-//----------------------------------------------------------------------------
-// Control allocator
-//----------------------------------------------------------------------------
-
-class ControlAllocator : public UI
-{
-public:
- ControlAllocator(Control* controls)
- : mControls(controls)
- { }
-
- // active widgets
- virtual void addButton(const char* label, float* zone)
- { addSimpleControl(zone); }
- virtual void addToggleButton(const char* label, float* zone)
- { addSimpleControl(zone); }
- virtual void addCheckButton(const char* label, float* zone)
- { addSimpleControl(zone); }
- virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step)
- { addBoundedControl(zone, min, max, step); }
- virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step)
- { addBoundedControl(zone, min, max, step); }
- virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step)
- { addBoundedControl(zone, min, max, 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) { }
-
- // layout widgets
- 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() { }
-
-private:
- void addControl(Control::UpdateFunction updateFunction, float* zone, float min, float max, float step)
- {
- Control* ctrl = mControls++;
- ctrl->updateFunction = updateFunction;
- ctrl->min = min;
- ctrl->max = max;
- ctrl->step = step;
- ctrl->zone = zone;
- }
- void addSimpleControl(float* zone)
- {
- addControl(Control::simpleUpdate, zone, 0.f, 0.f, 0.f);
- }
- void addBoundedControl(float* zone, float min, float max, float step)
- {
- addControl(Control::boundedUpdate, zone, min, max, step);
- }
-
-private:
- Control* mControls;
-};
-
-
-/******************************************************************************
-*******************************************************************************
-
- FAUST DSP
-
-*******************************************************************************
-*******************************************************************************/
-
-//----------------------------------------------------------------------------
-// Abstract DSP interface
-//----------------------------------------------------------------------------
-
-class dsp
-{
-public:
- 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;
-
-protected:
- int fSamplingFreq;
-};
-
-dsp::~dsp() { }
-
-//----------------------------------------------------------------------------
-// FAUST generated code
-//----------------------------------------------------------------------------
-
-<<includeclass>>
-
-
-/******************************************************************************
-*******************************************************************************
-
- SUPERCOLLIDER DSP INTERFACE
-
-*******************************************************************************
-*******************************************************************************/
-
-struct Faust : public Unit
-{
- // Faust dsp instance
- mydsp mDSP;
- // Buffers for control to audio rate conversion
- float** mInBufCopy;
- float* mInBufValue;
- // Controls
- size_t mNumControls;
- // NOTE: This needs to be the last field!
- //
- // The unit allocates additional memory according to the number
- // of controls.
- Control mControls[0];
-
- int getNumAudioInputs() { return mDSP.getNumInputs(); }
-};
-
-// Global state
-
-static size_t g_numControls; // Number of controls
-static const char* g_unitName; // Unit name
-
-// Initialize the global state with unit name and sample rate.
-void initState(const std::string& name, int sampleRate);
-
-// Return the unit size in bytes, including static fields and controls.
-static size_t unitSize();
-
-// Convert a file name to a valid unit name.
-static std::string fileNameToUnitName(const std::string& fileName);
-
-// Convert the XML unit name to a valid class name.
-static std::string normalizeClassName(const std::string& name);
-
-void initState(const std::string& name, int sampleRate)
-{
- g_unitName = strdup(name.c_str());
-
- mydsp* dsp = new mydsp;
- ControlCounter* cc = new ControlCounter;
-
- dsp->classInit(sampleRate);
- dsp->buildUserInterface(cc);
- g_numControls = cc->getNumControls();
-
- delete dsp;
- delete cc;
-}
-
-size_t unitSize()
-{
- return sizeof(Faust) + g_numControls * sizeof(Control);
-}
-
-std::string fileNameToUnitName(const std::string& fileName)
-{
- // Extract basename
- size_t lpos = fileName.rfind('/', fileName.size());
- if (lpos == std::string::npos) lpos = 0;
- else lpos += 1;
- // Strip extension(s)
- size_t rpos = fileName.find('.', lpos);
- // Return substring
- return fileName.substr(lpos, rpos > lpos ? rpos - lpos : 0);
-}
-
-// Globals
-
-static InterfaceTable *ft;
-
-// The SuperCollider UGen class name generated here must match
-// that generated by faust2sc:
-static std::string normalizeClassName(const std::string& name)
-{
- std::string s;
- char c;
-
- unsigned int i=0;
- bool upnext=true;
- while (c=name[i++]) {
- if (upnext) { c = toupper(c); upnext=false; }
- if ( (c == '_') || (c == '-') || isspace(c)) { upnext=true; continue; }
- s += c;
- if (i > 31) { break; }
- }
- return s;
-}
-
-extern "C"
-{
-#ifdef SC_API_EXPORT
- int api_version(void);
-#endif
- void load(InterfaceTable*);
- void Faust_next(Faust*, int);
- void Faust_next_copy(Faust*, int);
- void Faust_next_clear(Faust*, int);
- void Faust_Ctor(Faust*);
- void Faust_Dtor(Faust*);
-};
-
-inline static void fillBuffer(float* dst, int n, float v)
-{
- Fill(n, dst, v);
-}
-
-inline static void fillBuffer(float* dst, int n, float v0, float v1)
-{
- Fill(n, dst, v0, (v1 - v0) / n);
-}
-
-inline static void copyBuffer(float* dst, int n, float* src)
-{
- Copy(n, dst, src);
-}
-
-inline static void Faust_updateControls(Faust* unit)
-{
- Control* controls = unit->mControls;
- int numControls = unit->mNumControls;
- int curControl = unit->mDSP.getNumInputs();
- for (int i=0; i < numControls; ++i) {
- float value = IN0(curControl);
- (controls++)->update(value);
- curControl++;
- }
-}
-
-void Faust_next(Faust* unit, int inNumSamples)
-{
- // update controls
- Faust_updateControls(unit);
- // dsp computation
- unit->mDSP.compute(inNumSamples, unit->mInBuf, unit->mOutBuf);
-}
-
-void Faust_next_copy(Faust* unit, int inNumSamples)
-{
- // update controls
- Faust_updateControls(unit);
- // Copy buffers
- for (int i = 0; i < unit->getNumAudioInputs(); ++i) {
- float* b = unit->mInBufCopy[i];
- if (INRATE(i) == calc_FullRate) {
- // Audio rate: copy buffer
- copyBuffer(b, inNumSamples, unit->mInBuf[i]);
- } else {
- // Control rate: linearly interpolate input
- float v1 = IN0(i);
- fillBuffer(b, inNumSamples, unit->mInBufValue[i], v1);
- unit->mInBufValue[i] = v1;
- }
- }
- // dsp computation
- unit->mDSP.compute(inNumSamples, unit->mInBufCopy, unit->mOutBuf);
-}
-
-void Faust_next_clear(Faust* unit, int inNumSamples)
-{
- ClearUnitOutputs(unit, inNumSamples);
-}
-
-void Faust_Ctor(Faust* unit) // module constructor
-{
- // init dsp
- unit->mDSP.instanceInit((int)SAMPLERATE);
-
- // allocate controls
- unit->mNumControls = g_numControls;
- ControlAllocator ca(unit->mControls);
- unit->mDSP.buildUserInterface(&ca);
- unit->mInBufCopy = 0;
- unit->mInBufValue = 0;
-
- // check input/output channel configuration
- const size_t numInputs = unit->mDSP.getNumInputs() + unit->mNumControls;
- const size_t numOutputs = unit->mDSP.getNumOutputs();
-
- bool channelsValid = (numInputs == unit->mNumInputs)
- && (numOutputs == unit->mNumOutputs);
-
- if (channelsValid) {
- bool rateValid = true;
- for (int i = 0; i < unit->getNumAudioInputs(); ++i) {
- if (INRATE(i) != calc_FullRate) {
- rateValid = false;
- break;
- }
- }
- if (rateValid) {
- SETCALC(Faust_next);
- } else {
- unit->mInBufCopy = (float**)RTAlloc(unit->mWorld, unit->getNumAudioInputs()*sizeof(float*));
- // Allocate memory for input buffer copies (numInputs * bufLength)
- // and linear interpolation state (numInputs)
- // = numInputs * (bufLength + 1)
- unit->mInBufValue = (float*)RTAlloc(unit->mWorld, unit->getNumAudioInputs()*sizeof(float));
- float* mem = (float*)RTAlloc(unit->mWorld, unit->getNumAudioInputs()*BUFLENGTH*sizeof(float));
- // Aquire memory for interpolator state.
- for (int i=0; i < unit->getNumAudioInputs(); ++i) {
- // Initialize interpolator.
- unit->mInBufValue[i] = IN0(i);
- // Aquire buffer memory.
- unit->mInBufCopy[i] = mem;
- mem += BUFLENGTH;
- }
- SETCALC(Faust_next_copy);
- }
-#if !defined(NDEBUG)
- Print("Faust[%s]:\n", g_unitName);
- Print(" Inputs: %d\n"
- " Outputs: %d\n"
- " Callback: %s\n",
- numInputs, numOutputs,
- unit->mCalcFunc == (UnitCalcFunc)Faust_next ? "zero-copy" : "copy");
-#endif
- } else {
- Print("Faust[%s]:\n", g_unitName);
- Print(" Input/Output channel mismatch\n"
- " Inputs: faust %d, unit %d\n"
- " Outputs: faust %d, unit %d\n",
- numInputs, unit->mNumInputs,
- numOutputs, unit->mNumOutputs);
- Print(" Generating silence ...\n");
- SETCALC(Faust_next_clear);
- }
-}
-
-void Faust_Dtor(Faust* unit) // module destructor
-{
- if (unit->mInBufValue) {
- RTFree(unit->mWorld, unit->mInBufValue);
- }
- if (unit->mInBufCopy) {
- if (unit->mInBufCopy[0]) {
- RTFree(unit->mWorld, unit->mInBufCopy[0]);
- }
- RTFree(unit->mWorld, unit->mInBufCopy);
- }
-}
-
-#ifdef SC_API_EXPORT
-FAUST_EXPORT int api_version(void) { return sc_api_version; }
-#endif
-
-FAUST_EXPORT void load(InterfaceTable* inTable)
-{
-
- ft = inTable;
-
- Meta meta;
- mydsp::metadata(&meta);
-
- std::string name = meta["name"];
-
- if (name.empty()) {
- name = fileNameToUnitName(__FILE__);
- }
-
- name = normalizeClassName(name);
-
-#if !defined(NDEBUG) & defined(SC_API_EXPORT)
- Print("*** Faust: supercollider.cpp: sc_api_version = %d\n",sc_api_version);
-#endif
-
- if (name.empty()) {
- // Catch empty name
- Print("*** Faust: supercollider.cpp: "
- "Could not create unit-generator module name from filename\n"
- " bailing out ...\n");
- return;
- }
-
- if (strncmp(name.c_str(),SC_FAUST_PREFIX,strlen(SC_FAUST_PREFIX))!=0){
- name = SC_FAUST_PREFIX + name;
- }
-
- // Initialize global data
- // TODO: Use correct sample rate
- initState(name, 48000);
-
- // Register ugen
- (*ft->fDefineUnit)(
- (char*)name.c_str(),
- unitSize(),
- (UnitCtorFunc)&Faust_Ctor,
- (UnitDtorFunc)&Faust_Dtor,
- kUnitDef_CantAliasInputsToOutputs
- );
-
-#if !defined(NDEBUG)
- Print("Faust: %s numControls=%d\n", name.c_str(), g_numControls);
-#endif // NDEBUG
-}
-
-// EOF