+++ /dev/null
-/************************************************************************
-
- 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) 2007-2011 Julius Smith
- All rights reserved.
- ----------------------------BSD License------------------------------
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials provided
- with the distribution.
- * Neither the name of Julius Smith nor the names of its
- contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- OF THE POSSIBILITY OF SUCH DAMAGE.
-
- ----------------------------VST SDK----------------------------------
- In order to compile a VST (TM) plugin with this architecture file
- you will need the proprietary VST SDK from Steinberg. Please check
- the corresponding license.
-
- ************************************************************************
- ************************************************************************/
-
-/********************************************************************
- * vsti-mono.cpp - Monaural VSTi-2.4 wrapper for the FAUST language.
- *
- * Usage: faust -a vsti-mono.cpp myfaustprog.dsp
- *
- * By Julius Smith (http://ccrma.stanford.edu/~jos/), based on vst.cpp
- * by remy muller <remy.muller at ircam.fr>
- * (http://www.smartelectronix.com/~mdsp/). Essentially, vst.cpp was
- * first edited to look more like the "again" programming sample that
- * comes with the VST-2.4 SDK from Steinberg. Next, features from the
- * "vstxsynth" program sample were added to give simple MIDI synth
- * support analogous to that of faust2pd, except that only one voice
- * is supported. (If the Faust patch has any input signals, this
- * architecture file should reduce to vst2p4.cpp --- i.e., basic VST
- * plugin support.) As with faust2pd, to obtain MIDI control via
- * NoteOn/Off, Velocity, and KeyNumber, there must be a button named
- * "gate" and sliders (or numeric entries) named "gain" and "freq" in
- * the Faust patch specified in myfaustprog.dsp.
- *
- * NOTES:
- * Relies on automatically generated slider GUI for VST plugins.
- * - Horizontal and vertical sliders mapped to "vstSlider"
- * - Numeric Entries similarly converted to "vstSlider"
- * - No support for bar graphs or additional numeric and text displays
- * - Tested on the Muse Receptor Pro 1.0, System Version 1.6.20070717,
- * using Visual C++ 2008 Express Edition
- * (part of the Microsoft Visual Studio 2008, Beta 2)
- * - Reference:
- * http://ccrma.stanford.edu/realsimple/faust/Generating_VST_Plugin_Faust.html
- *
- * FAUST
- * Copyright (C) 2003-2007 GRAME, Centre National de Creation Musicale
- * http://www.grame.fr/
- *
- ********************************************************************/
-
-// Suggestion: Faust could replace all leading comments in this file
-// by the following shorter comment:
-
-/********************************************************************
- * C++ source generated by the following command line:
- *
- * faust -a vsti.cpp name.dsp -o name-vsti.cpp
- *
- ********************************************************************/
-
-// (where the filenames could be really right, and the path to vsti.cpp
-// could be included as well.)
-
-#include <stdlib.h>
-#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 <math.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
-
-// On Intel set FZ (Flush to Zero) and DAZ (Denormals Are Zero)
-// flags to avoid costly denormals
-#ifdef __SSE__
- #include <xmmintrin.h>
- #ifdef __SSE2__
- #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8040)
- #else
- #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8000)
- #endif
-#else
- #define AVOIDDENORMALS
-#endif
-
-struct Meta
-{
- void declare (const char* key, const char* value) { }
-};
-
-
-#ifdef __GNUC__
-
-//-------------------------------------------------------------------
-// Generic min and max using gcc extensions
-//-------------------------------------------------------------------
-
-#define max(x,y) ((x)>?(y))
-#define min(x,y) ((x)<?(y))
-
-//abs(x) should be already predefined
-
-#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
-
-// abs is now predefined
-//template<typename T> T abs (T a) { return (a<T(0)) ? -a : a; }
-
-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>>
-
-/******************************************************************************
-*******************************************************************************
-*
-* USER INTERFACE
-*
-*******************************************************************************
-*******************************************************************************/
-
-class UI
-{
- bool fStopped;
-
-public:
-
- UI() : fStopped(false) {}
- virtual ~UI() {}
-
- virtual void addButton(char* label, float* zone) = 0;
- virtual void addToggleButton(char* label, float* zone) = 0;
- virtual void addCheckButton(char* label, float* zone) = 0;
- virtual void addVerticalSlider(char* label, float* zone, float init, float min, float max, float step) = 0;
- virtual void addHorizontalSlider(char* label, float* zone, float init, float min, float max, float step) = 0;
- virtual void addNumEntry(char* label, float* zone, float init, float min, float max, float step) = 0;
-
- virtual void addNumDisplay(char* label, float* zone, int precision) = 0;
- virtual void addTextDisplay(char* label, float* zone, char* names[], float min, float max) = 0;
- virtual void addHorizontalBargraph(char* label, float* zone, float min, float max) = 0;
- virtual void addVerticalBargraph(char* label, float* zone, float min, float max) = 0;
-
- virtual void openFrameBox(char* label) = 0;
- virtual void openTabBox(char* label) = 0;
- virtual void openHorizontalBox(char* label) = 0;
- virtual void openVerticalBox(char* label) = 0;
- virtual void closeBox() = 0;
-
- virtual void run() {};
-
- void stop() { fStopped = true; }
- bool stopped() { return fStopped; }
-
- virtual void declare(float* zone, const char* key, const char* value) {}
-};
-
-
-/******************************************************************************
-*******************************************************************************
-*
-* FAUST DSP
-*
-*******************************************************************************
-*******************************************************************************/
-
-
-
-//----------------------------------------------------------------
-// Base dsp class for this architecture
-//----------------------------------------------------------------
-
-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;
-};
-
-/********************END ARCHITECTURE SECTION (part 1/2)****************/
-
-/**************************BEGIN USER SECTION **************************/
-
-<<includeclass>>
-
-/***************************END USER SECTION ***************************/
-
-/*******************BEGIN ARCHITECTURE SECTION (part 2/2)***************/
-
-/******************************************************************************
- *
- * VST wrapper
- *
- ******************************************************************************/
-
-#include "audioeffectx.h"
-
-class vstUI;
-
-//------------------------------------------------------------------------------
-// Faust class prototype
-//------------------------------------------------------------------------------
-class Faust : public AudioEffectX
-{
-public:
- Faust(audioMasterCallback audioMaster, mydsp* dspi, vstUI* dspUIi);
- virtual ~Faust();
-
- virtual void processReplacing (float **inputs, float **outputs, VstInt32 sampleFrames);
- virtual VstInt32 processEvents (VstEvents* events);
-
- virtual void setProgram (VstInt32 program);
- virtual void setProgramName (char *name);
- virtual void getProgramName (char *name);
- virtual bool getProgramNameIndexed (VstInt32 category, VstInt32 index, char *text);
-
- virtual void setParameter (VstInt32 index, float value);
- virtual float getParameter (VstInt32 index);
- virtual void getParameterLabel (VstInt32 index, char *label);
- virtual void getParameterDisplay (VstInt32 index, char *text);
- virtual void getParameterName (VstInt32 index, char *text);
-
- virtual void setSampleRate (float sampleRate);
-
- virtual bool getInputProperties (VstInt32 index, VstPinProperties *properties);
- virtual bool getOutputProperties (VstInt32 index, VstPinProperties *properties);
-
- virtual bool getEffectName (char *name);
- virtual bool getVendorString (char *text);
- virtual bool getProductString (char *text);
- virtual VstInt32 getVendorVersion ();
- virtual VstInt32 canDo (char *text);
-
- virtual VstInt32 getNumMidiInputChannels ();
- virtual VstInt32 getNumMidiOutputChannels ();
-
- virtual VstInt32 getMidiProgramName (VstInt32 channel, MidiProgramName *midiProgramName);
- virtual VstInt32 getCurrentMidiProgram (VstInt32 channel, MidiProgramName *currentProgram);
- virtual VstInt32 getMidiProgramCategory (VstInt32 channel, MidiProgramCategory *category);
-
-private:
- mydsp* dsp;
- vstUI* dspUI;
-
- // For synths:
- bool noteIsOn;
- VstInt32 currentNote;
- VstInt32 currentVelocity;
- VstInt32 currentDelta;
-
- void initProcess ();
- void noteOn (VstInt32 note, VstInt32 velocity, VstInt32 delta);
- void noteOff ();
- void fillProgram (VstInt32 channel, VstInt32 prg, MidiProgramName* mpn);
-
- char programName[kVstMaxProgNameLen + 1];
-};
-
-/*--------------------------------------------------------------------------*/
-class vstUIObject { /* superclass of all VST UI widgets */
-protected:
- string fLabel;
- float* fZone;
-
- inline float clip(float min, float max, float val)
- {
- return (val < min) ? min : (val > max) ? max : val;
- }
-
- inline float normalize(float min, float max, float val)
- { // VST parameters are normalized to the range [0;1] on the host
- val = min + val * (max - min);
- return (val < min) ? min : (val > max) ? max : val;
- }
-
-public:
- vstUIObject(char* label, float* zone):fLabel(label),fZone(zone) {}
- virtual ~vstUIObject() {}
-
- virtual void GetName(char *text){std::strcpy(text,fLabel.c_str());}
- virtual void SetValue(double f) {*fZone = normalize(0.0f,1.0f,(float)f);}
- virtual void SetValueNoNormalization(double f) {*fZone = clip(0.0f,1.0f,(float)f);}
- virtual float GetValue() {return *fZone;}
- virtual void GetDisplay(char *text){std::sprintf(text,"%f",*fZone);}
- virtual long GetID()
- { /* returns the sum of all the ASCII characters contained in the parameter's label */
- unsigned int i;
- long acc;
- for(i=0,acc = 0;i<fLabel.length();i++) acc += (fLabel.c_str())[i];
- return acc;
- }
-};
-
-/*--------------------------------------------------------------------------*/
-class vstToggleButton : public vstUIObject {
-
-public:
-
- vstToggleButton(char* label, float* zone):vstUIObject(label,zone) {}
- virtual ~vstToggleButton() {}
- virtual float GetValue() {return *fZone;}
- virtual void SetValue(double f) {*fZone = (f>0.5f)?1.0f:0.0f;}
- virtual void GetDisplay(char *text){(*fZone>0.5f)? std::strcpy(text,"ON"): std::strcpy(text,"OFF");}
-};
-
-/*--------------------------------------------------------------------------*/
-class vstCheckButton : public vstUIObject {
-
-public:
-
- vstCheckButton(char* label, float* zone):vstUIObject(label,zone) {}
- virtual ~vstCheckButton() {}
- virtual float GetValue() {return *fZone;}
- virtual void SetValue(double f) {*fZone = (f>0.5f)?1.0f:0.0f;}
- virtual void GetDisplay(char *text){(*fZone>0.5f)? std::strcpy(text,"ON"): std::strcpy(text,"OFF");}
-};
-
-/*--------------------------------------------------------------------------*/
-class vstButton : public vstUIObject {
-
-public:
-
- vstButton(char* label, float* zone):vstUIObject(label,zone) {}
- virtual ~vstButton() {}
- virtual float GetValue() {return *fZone;}
- virtual void SetValue(double f) {*fZone = (f>0.5f)?1.0f:0.0f;}
- virtual void GetDisplay(char *text){(*fZone>0.5f)? std::strcpy(text,"ON"): std::strcpy(text,"OFF");}
-};
-
-/*--------------------------------------------------------------------------*/
-class vstSlider : public vstUIObject{
-
-private:
-
- float fInit;
- float fMin;
- float fMax;
- float fStep;
-
-public:
-
- vstSlider(char* label, float* zone, float init, float min, float max, float step)
- :vstUIObject(label,zone), fInit(init), fMin(min), fMax(max),fStep(step) {}
- virtual ~vstSlider() {}
-
- // The VST host calls GetValue() and expects a result in [0,1].
- // The VST host calls SetValue(f) with f in [0,1]. We convert to real units.
- // When we process MIDI controls, we call SetValueNoNormalization(f) with f in real units.
- virtual float GetValue() {return (*fZone-fMin)/(fMax-fMin);} // normalize
- virtual void SetValue(double f) {*fZone = normalize(fMin,fMax,(float)f);} // denormalize
- virtual void SetValueNoNormalization(double f) {*fZone = clip(fMin,fMax,(float)f);} // raw
-};
-
-/*--------------------------------------------------------------------------*/
-class vstUI : public UI
-{
-private:
-
- vector<vstUIObject*> fUITable;
-
-public:
-
- int freqIndex;
- int gainIndex;
- int gateIndex;
-
- vstUI(){
- freqIndex = gainIndex = gateIndex = -1;
- }
- virtual ~vstUI()
- {
- for (vector<vstUIObject*>::iterator iter = fUITable.begin(); iter != fUITable.end(); iter++) delete *iter;
- }
-
- void setAny(int anyIndex, float val, char *str) {
- if (anyIndex<0) {
-#ifdef DEBUG
- // On the Receptor, and perhaps other hosts, output to stderr is logged in a file.
- fprintf(stderr,"*** Faust vsti: %sIndex = %d never set!\n",str,anyIndex);
-#endif
- return;
- }
- if (anyIndex >= fUITable.size()) {
-#ifdef DEBUG
- fprintf(stderr,"*** Faust vsti: %sIndex = %d too large!\n",str,anyIndex);
-#endif
- return;
- }
-#ifdef DEBUG
- fprintf(stderr,"*** Faust vsti: Setting %sIndex = %d to %f\n",str,anyIndex,val);
-#endif
- fUITable[anyIndex]->SetValueNoNormalization(val);
- }
-
- void setFreq(float val) {
- setAny(freqIndex, val, "freq");
- }
-
- void setGate(float val) {
- setAny(gateIndex, val, "gate");
- }
-
- void setGain(float val) {
- setAny(gainIndex, val, "gain");
- }
-
- bool ckAnyMatch(char* label, char* indexName, int *index) {
- if (_stricmp(label,indexName)==0) {
-#ifdef DEBUG
- fprintf(stderr,"=== Faust vsti: label '%s' matches '%s'\n",label,indexName);
-#endif
- *index = fUITable.size() - 1;
- return true;
- }
- return false;
- }
-
- void ckAllMatches(char* label) {
- ckAnyMatch(label,"gain",&gainIndex);
- ckAnyMatch(label,"gate",&gateIndex);
- ckAnyMatch(label,"freq",&freqIndex);
- }
-
- void addButton(char* label, float* zone) {
- vstButton* theButton = new vstButton(label, zone);
- fUITable.push_back(theButton);
-#ifdef DEBUG
- fprintf(stderr,"=== Faust vsti: Adding Button with label '%s'\n",label);
-#endif
- ckAnyMatch(label,"gate",&gateIndex);
- }
-
- void addToggleButton(char* label, float* zone) {fUITable.push_back(new vstToggleButton(label, zone));}
-
- void addCheckButton(char* label, float* zone) {fUITable.push_back(new vstCheckButton(label, zone));}
-
- void addVerticalSlider(char* label, float* zone, float init, float min, float max, float step)
- {
- vstSlider* theSlider = new vstSlider(label, zone, init, min, max, step);
- fUITable.push_back(theSlider);
-#ifdef DEBUG
- fprintf(stderr,"=== Faust vsti: Adding VSlider (HSlider) with label '%s'\n",label);
-#endif
- ckAllMatches(label);
- }
-
- void addHorizontalSlider(char* label, float* zone, float init, float min, float max, float step)
- {
- vstSlider* theSlider = new vstSlider(label, zone, init, min, max, step);
- fUITable.push_back(theSlider);
-#ifdef DEBUG
- fprintf(stderr,"=== Faust vsti: Adding HSlider with label '%s'\n",label);
-#endif
- ckAllMatches(label);
- }
-
- void addNumEntry(char* label, float* zone, float init, float min, float max, float step)
- { /* Number entries converted to horizontal sliders */
- vstSlider* theSlider = new vstSlider(label, zone, init, min, max, step);
- fUITable.push_back(theSlider);
-#ifdef DEBUG
- fprintf(stderr,"=== Faust vsti: Adding NumEntry (HSlider) with label '%s'\n",label);
-#endif
- ckAllMatches(label);
- }
-
- void openFrameBox(char* label) {}
- void openTabBox(char* label) {}
- void openHorizontalBox(char* label) {}
- void openVerticalBox(char* label) {}
- void closeBox() {}
-
- void SetValue(VstInt32 index, double f) {assert(index<fUITable.size()); fUITable[index]->SetValue(f);}
- float GetValue(VstInt32 index) {assert(index<fUITable.size()); return fUITable[index]->GetValue();}
- void GetDisplay(VstInt32 index, char *text) {assert(index<fUITable.size()); fUITable[index]->GetDisplay(text);}
- void GetName(VstInt32 index, char *text) {assert(index<fUITable.size()); fUITable[index]->GetName(text);}
- long GetNumParams() {return fUITable.size();}
-
- long makeID()
- /* Creates a (unique?)id by summing all the parameter's labels,
- * then wrapping it in the range [0;maxNumberOfId] and adding
- * this number to the offset made by the Four Character ID: 'FAUS'
- */
- {
- const long maxNumberOfId = 128;
- long baseid = 'FAUS';
- long id=0;
- for(int i=0;i<fUITable.size();i++) id += fUITable[i]->GetID();
- return baseid + id % maxNumberOfId;
- }
-
- // To be implemented
- void addNumDisplay(char* label, float* zone, int precision){}
- void addTextDisplay(char* label, float* zone, char* names[], float min, float max){}
- void addHorizontalBargraph(char* label, float* zone, float min, float max){}
- void addVerticalBargraph(char* label, float* zone, float min, float max){}
-};
-
-//-----------------------------------------------------------------------------
-// Class Implementations
-//-----------------------------------------------------------------------------
-
-#define kNumPrograms 1
-
-AudioEffect* createEffectInstance (audioMasterCallback audioMaster)
-{
- // The dsp and its UI need to be allocated now because
- // AudioEffectX wants the no. parameters available as an instance argument:
- mydsp* dspi = new mydsp();
- vstUI* dspUIi = new vstUI();
- dspi->buildUserInterface(dspUIi);
-#ifdef DEBUG
- fprintf(stderr,"=== Faust vsti: created\n"); // look for this in the system log
-#endif
- return new Faust(audioMaster,dspi,dspUIi);
-}
-
-//-----------------------------------------------------------------------------
-// Faust
-//-----------------------------------------------------------------------------
-Faust::Faust(audioMasterCallback audioMaster, mydsp* dspi, vstUI* dspUIi)
- :AudioEffectX(audioMaster, kNumPrograms,dspUIi->GetNumParams())
-{
- // Copy the pointers to dsp and dspUI instances and take them over
- // (we'll also deallocate):
- dsp = dspi;
- dspUI = dspUIi;
-
-#ifdef DEBUG
- fprintf(stderr,"=== Faust vsti: classInit:\n");
-#endif
-
- dsp->classInit((int)getSampleRate()); // Ask AudioEffect for sample-rate
-
- setProgram(0);
- setProgramName("Default");
-
- if (audioMaster) {
- setNumInputs(dsp->getNumInputs());
- setNumOutputs(dsp->getNumOutputs());
- canProcessReplacing();
- if (dsp->getNumInputs() == 0) {
- isSynth(); // at least let's hope so!
- if (dsp->getNumOutputs() < 1) {
- fprintf(stderr,"*** faust: vsti: No signal inputs or outputs, and Faust has no MIDI outputs!\n");
- }
- }
- setUniqueID(dspUI->makeID());
- }
- initProcess();
- if (dsp->getNumInputs() == 0) {
- suspend(); // Synths start out quiet
- }
-}
-
-//----------------------------------------------------------------------------
-Faust::~Faust()
-{
- if (dsp) delete dsp;
- if (dspUI) delete dspUI;
-}
-
-//-----------------------------------------------------------------------------
-void Faust::setProgram (VstInt32 program)
-// Override this method of AudioEffect in order to set
-// local instance variables corresponding to the current MIDI program.
-// Here there is only one program.
-{
- if (program < 0 || program >= kNumPrograms) {
- fprintf(stderr,"*** Faust vsti: setting program to %d is OUT OF RANGE\n",program);
- return;
- }
-#ifdef DEBUG
- fprintf(stderr,"=== Faust vsti: setting program to %d\n",program);
-#endif
- curProgram = program; // curProgram defined in audioeffect.h
-}
-
-//------------------------------------------------------------------------------
-void Faust::setProgramName (char* name)
-{
- vst_strncpy (programName, name, kVstMaxProgNameLen);
-}
-
-//-----------------------------------------------------------------------------
-void Faust::getProgramName(char *name)
-{
- vst_strncpy (name, programName, kVstMaxProgNameLen);
-}
-
-//-----------------------------------------------------------------------------
-void Faust::getParameterLabel(VstInt32 index, char *label)
-{
- // We are not using parameter "units" display:
- vst_strncpy (label, "", kVstMaxParamStrLen); // parameter units in Name
-}
-
-//-----------------------------------------------------------------------------
-void Faust::getParameterDisplay(VstInt32 index, char *text)
-{
- if(index<numParams)
- dspUI->GetDisplay(index,text); // get displayed float value as text
- else
- vst_strncpy (text, "IndexOutOfRange", kVstMaxParamStrLen);
-}
-
-//-----------------------------------------------------------------------------
-void Faust::getParameterName(VstInt32 index, char *label)
-{
- if(index<numParams)
- dspUI->GetName(index,label); // parameter name, including units
- else
- vst_strncpy (label, "IndexOutOfRange", kVstMaxParamStrLen);
-}
-
-//-----------------------------------------------------------------------------
-void Faust::setParameter(VstInt32 index, float value)
-{
- if(index<numParams)
- dspUI->SetValue(index,value);
-}
-
-//-----------------------------------------------------------------------------
-float Faust::getParameter(VstInt32 index)
-{
- if(index<numParams)
- return dspUI->GetValue(index);
- else
- return 0.0f;
-}
-
-//-----------------------------------------------------------------------------
-bool Faust::getInputProperties (VstInt32 index, VstPinProperties* properties)
-{
- if(index>=0 && index<dsp->getNumInputs())
- {
- sprintf (properties->label, "Grame Faust DSP input: %d",index);
- sprintf (properties->shortLabel, "In %d",index);
- properties->flags = kVstPinIsActive;
- if (dsp->getNumInputs() == 2) {
- properties->flags |= kVstPinIsStereo;
- }
- return true;
- }
- else
- return false;
-}
-
-//-----------------------------------------------------------------------------
-bool Faust::getOutputProperties (VstInt32 index, VstPinProperties* properties)
-{
- if(index>=0 && index<dsp->getNumOutputs())
- {
- sprintf (properties->label, "Grame Faust DSP output: %d",index);
- sprintf (properties->shortLabel, "Out %d",index);
- properties->flags = kVstPinIsActive;
- if (dsp->getNumOutputs() == 2) {
- properties->flags |= kVstPinIsStereo;
- }
- return true;
- }
- else
- return false;
-}
-
-//-----------------------------------------------------------------------------
-bool Faust::getProgramNameIndexed (VstInt32 category, VstInt32 index, char* text)
-{
- if (index < kNumPrograms) {
- vst_strncpy (text, programName, kVstMaxProgNameLen);
- return true;
- }
- return false;
-}
-
-//-----------------------------------------------------------------------------
-bool Faust::getEffectName (char* name)
-{
- // Get from Faust-supplied metadata?
- vst_strncpy (name, "Effect Name goes here", kVstMaxEffectNameLen);
- return true;
-}
-
-//-----------------------------------------------------------------------------
-bool Faust::getVendorString (char* text)
-{
- vst_strncpy (text, "Vendor String goes here", kVstMaxVendorStrLen);
- return true;
-}
-
-//-----------------------------------------------------------------------------
-bool Faust::getProductString (char* text)
-{
- vst_strncpy (text, "Product String goes here", kVstMaxProductStrLen);
- return true;
-}
-
-//-----------------------------------------------------------------------------
-VstInt32 Faust::getVendorVersion ()
-{
- return 1000;
-}
-
-//-----------------------------------------------------------------------------
-VstInt32 Faust::canDo (char* text)
-{
- if (!strcmp (text, "receiveVstEvents"))
- return 1;
- if (!strcmp (text, "receiveVstMidiEvent"))
- return 1;
- if (!strcmp (text, "midiProgramNames"))
- return 1;
- return -1; // explicitly can't do; 0 => don't know
-}
-
-//-----------------------------------------------------------------------------
-VstInt32 Faust::getNumMidiInputChannels ()
-{
- return 1; // one MIDI-in channel
-}
-
-//-----------------------------------------------------------------------------
-VstInt32 Faust::getNumMidiOutputChannels ()
-{
- return 0; // no MIDI-outs
-}
-
-//-----------------------------------------------------------------------------
-VstInt32 Faust::getMidiProgramName (VstInt32 channel, MidiProgramName* mpn)
-{
- VstInt32 prg = mpn->thisProgramIndex;
- if (prg < 0 || prg > 0) return 0;
- fillProgram (channel, prg, mpn);
- return 1; // we have only 1 "MIDI program"
-}
-
-//------------------------------------------------------------------------
-VstInt32 Faust::getCurrentMidiProgram (VstInt32 channel, MidiProgramName* mpn)
-{
- // There is only one MIDI program here, so return it regardless of MIDI channel:
- if (channel < 0 || channel >= 16 || !mpn) return -1;
- VstInt32 prg = 0;
- mpn->thisProgramIndex = prg;
- fillProgram (channel, prg, mpn);
- return prg;
-}
-
-//------------------------------------------------------------------------
-void Faust::fillProgram (VstInt32 channel, VstInt32 prg, MidiProgramName* mpn)
-// Fill mpn struct for given channel. Here there should be only one.
-{
- mpn->midiBankMsb = mpn->midiBankLsb = -1;
- mpn->reserved = 0;
- mpn->flags = 0;
- vst_strncpy (mpn->name, programName, kVstMaxProgNameLen);
- mpn->midiProgram = (char)prg; // prg should only be 0
- mpn->parentCategoryIndex = -1;
-}
-
-//------------------------------------------------------------------------
-VstInt32 Faust::getMidiProgramCategory (VstInt32 channel, MidiProgramCategory* cat)
-// VST host wants to fill cat struct for given channel. We have only one category.
-{
- cat->parentCategoryIndex = -1; // -1:no parent category
- cat->flags = 0; // reserved, none defined yet, zero.
- VstInt32 category = cat->thisCategoryIndex;
- vst_strncpy (cat->name, "Faust Patch", kVstMaxProgNameLen);
- return 1; // one category
-}
-
-//***********************************************************************
-
-//-----------------------------------------------------------------------------
-void Faust::setSampleRate(float sampleRate)
-{
- AudioEffect::setSampleRate(sampleRate);
- dsp->instanceInit((int)getSampleRate()); // in case AudioEffect altered it
-}
-
-//-----------------------------------------------------------------------------
-void Faust::initProcess ()
-{
- noteIsOn = false;
- currentDelta = currentNote = currentDelta = 0;
- dsp->instanceInit((int)getSampleRate());
-}
-
-//-----------------------------------------------------------------------------
-void Faust::processReplacing(float **inputs, float **outputs, VstInt32 sampleFrames)
-{
- AVOIDDENORMALS;
-#ifdef DEBUG
- fprintf(stderr,"=== Faust vsti: processReplacing . . .\n");
-#endif
-
- if (dsp->getNumInputs() > 0) { // We're an effect . . . keep going:
-
- dsp->compute(sampleFrames, inputs, outputs);
-
- } else { // We're a synth . . .
- int i, nouts = dsp->getNumOutputs();
-
- if (noteIsOn) { // we're synthesizing . . .
-
- if (currentDelta > 0) { // but waiting out a timestamp delay . . .
- if (currentDelta >= sampleFrames) { // start time is after this chunk
- currentDelta -= sampleFrames;
- // According to the VST programming sample, we DON'T clear the output buffers yet.
- // Could this be a bug in the sample program? I would like to add the following:
- // for (i=0; i<nouts; i++) { memset (outptr[i], 0, sampleFrames * sizeof (float)); }
- return;
- } else {
- // float* outptr[nouts];
- float** outptr = (float **)malloc(nouts * sizeof(float*));
-
-#ifdef DEBUG
- fprintf(stderr,"*** Faust vsti: currentDelta = %d\n",currentDelta);
-#endif
-
- for (i=0; i<nouts; i++) {
- outptr[i] = outputs[i]; // leaving caller's pointers alone
- // According to the VST programming sample, we DO clear the output buffers now
- // (since the start-time for the note is somewhere within the current chunk buf).
- memset (outptr[i], 0, currentDelta * sizeof (float));
- outptr[i] += currentDelta;
- }
- sampleFrames -= currentDelta;
- currentDelta = 0;
- dsp->compute(sampleFrames, inputs, outptr);
- free(outptr);
- }
- } else {
- dsp->compute(sampleFrames, inputs, outputs);
- }
-
- } else { // silence until NoteOn . . .
- for (i=0; i<nouts; i++) { memset (outputs[i], 0, sampleFrames * sizeof (float)); }
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-VstInt32 Faust::processEvents (VstEvents* ev)
-{
- if (ev->numEvents > 0) {
-#ifdef DEBUG
- fprintf(stderr,"=== Faust vsti: processEvents processing %d events\n",
- ev->numEvents);
-#endif
- }
-
- for (VstInt32 i = 0; i < ev->numEvents; i++)
- {
-#ifdef DEBUG
- fprintf(stderr,"=== Faust vsti: event type = %d\n",
- (ev->events[i])->type);
-#endif
- if ((ev->events[i])->type != kVstMidiType) {
-#ifdef DEBUG
- fprintf(stderr,"=== Faust vsti: EVENT IGNORED!\n");
-#endif
- continue;
- }
- VstMidiEvent* event = (VstMidiEvent*)ev->events[i];
- char* midiData = event->midiData;
- VstInt32 chan = midiData[0] & 0xf;
- VstInt32 status = midiData[0] & 0xf0;
-#ifdef DEBUG
- fprintf(stderr,"\n=== Faust vsti: event->midiData[0] = 0x%x\n",
- event->midiData[0]);
- fprintf(stderr,"=== Faust vsti: midi channel = 0x%x\n", chan);
- fprintf(stderr,"=== Faust vsti: midi status = 0x%x\n", status);
- fprintf(stderr,"=== Faust vsti: event->midiData[1] = 0x%x\n",
- event->midiData[1]);
- fprintf(stderr,"=== Faust vsti: event->midiData[2] = 0x%x\n",
- event->midiData[2]);
-#endif
-
- if (status == 0x90) { // note on
- VstInt32 note = midiData[1] & 0x7f;
- VstInt32 velocity = midiData[2] & 0x7f;
-#ifdef DEBUG
- fprintf(stderr,
- "=== Faust vsti: note = %d, velocity = %d, delay = %d\n",
- note,velocity,event->deltaFrames);
-#endif
- if (velocity>0) {
- noteOn(note, velocity, event->deltaFrames);
- } else {
- noteOff();
- }
- } else if (status == 0x80) { // note off
- noteOff();
- // } else if (status == 0xA0) { // poly aftertouch
- } else if (status == 0xB0) { // control change
- /* DO SOMETHING WITH THE CONTROLLER DATA */
- fprintf(stderr,"=== Faust vsti: CONTROL CHANGE (status 0xB0)!\n");
- if (midiData[1] == 0x7e || midiData[1] == 0x7b) { // all notes off
- fprintf(stderr,"=== Faust vsti: ALL NOTES OFF!\n");
- noteOff (); // why is all-notes-off inside a "control change" event?
- }
- // } else if (status == 0xC0) { // program change
- // } else if (status == 0xD0) { // mono aftertouch
- // } else if (status == 0xE0) { // pitch change
- // } else if (status == 0xF0) { // SYSX ...
- }
- // For a list, see
- // http://www.alfred-j-faust.de/rft/midi%20status%20types.html
-
-#ifdef DEBUG
- fprintf(stderr,"=== Faust vsti: Going to next event\n", event->midiData[2]);
-#endif
-
- event++;
- }
- return 1;
-}
-
-//-----------------------------------------------------------------------------
-void Faust::noteOn (VstInt32 note, VstInt32 velocity, VstInt32 delta)
-{
-#ifdef DEBUG
- fprintf(stderr,"=== Faust vsti: noteOn: note = %d, vel = %d, del = %d\n",note,velocity,delta);
-#endif
- currentNote = note;
- currentVelocity = velocity;
- currentDelta = delta;
- noteIsOn = true;
- float freq = 440.0f * powf(2.0f,(((float)note)-69.0f)/12.0f);
- float gain = velocity/127.0f;
- dspUI->setFreq(freq); // Hz - requires Faust control-signal "freq"
- dspUI->setGain(gain); // 0-1 - requires Faust control-signal "gain"
- dspUI->setGate(1.0f); // 0 or 1 - requires Faust button-signal "gate"
-}
-
-//-----------------------------------------------------------------------------
-void Faust::noteOff ()
-{
- if (noteIsOn) {
-#ifdef DEBUG
- fprintf(stderr,"=== Faust vsti: noteOff\n");
-#endif
- dspUI->setGate(0);
- } else {
-#ifdef DEBUG
- fprintf(stderr,"=== Faust vsti: noteOff IGNORED (note was not on)\n");
-#endif
- }
-}
-
-
-/********************END ARCHITECTURE SECTION (part 2/2)****************/
-