Browse Source

Autoformat FaustEngine.cpp.

Add `override` to overridden methods. Ignore override warning in Faust headers.
Remove `using namespace std`, add `std::` to required identifiers.
Move /res/faust to /fause_libraries.
Install Faust to dep instead of using build directory.
faust
Andrew Belt 1 year ago
parent
commit
8b867499dd
4 changed files with 338 additions and 324 deletions
  1. +1
    -0
      .gitignore
  2. +12
    -13
      Makefile
  3. +0
    -0
      faust_libraries/rack.lib
  4. +325
    -311
      src/FaustEngine.cpp

+ 1
- 0
.gitignore View File

@@ -5,3 +5,4 @@
/plugin.dylib
/plugin.dll
.DS_Store
/faust_libraries

+ 12
- 13
Makefile View File

@@ -4,7 +4,7 @@ FLAGS += -Idep/include
CFLAGS +=
CXXFLAGS +=

LDFLAGS +=
LDFLAGS +=
SOURCES += src/Prototype.cpp

DISTRIBUTABLES += res examples
@@ -13,12 +13,12 @@ DISTRIBUTABLES += $(wildcard LICENSE*)
include $(RACK_DIR)/arch.mk

DUKTAPE ?= 0
QUICKJS ?= 0
LUAJIT ?= 0
QUICKJS ?= 1
LUAJIT ?= 1
PYTHON ?= 0
SUPERCOLLIDER ?= 0
VULT ?= 0
LIBPD ?= 0
VULT ?= 1
LIBPD ?= 1
FAUST ?= 1

# Vult depends on both LuaJIT and QuickJS
@@ -223,7 +223,7 @@ FLAGS += -Idep/include/libpd -DHAVE_LIBDL
ifdef ARCH_WIN
# the PD_INTERNAL leaves the function declarations for libpd unchanged
# not specifying that flag would enable the "EXTERN __declspec(dllexport) extern" macro
# which throughs a linker error. I guess this macro should only be used for the windows
# which throughs a linker error. I guess this macro should only be used for the windows
# specific .dll dynamic linking format.
# The corresponding #define resides in "m_pd.h" inside pure data sources
FLAGS += -DPD_INTERNAL
@@ -250,15 +250,13 @@ endif

# Faust
ifeq ($(FAUST), 1)
libfaust := dep/faust/build/lib/libfaust.a
libfaust := dep/lib/libfaust.a
SOURCES += src/FaustEngine.cpp
OBJECTS += $(libfaust)
DEPS += $(libfaust)
FLAGS += -Idep/faust/architecture
FLAGS += -DINTERP
LDFLAGS += dep/faust/build/lib/libfaust.a

# Test using LLVM
# Test using LLVM
#LDFLAGS += -L/usr/local/lib -lfaust

# Test using MIR
@@ -266,10 +264,11 @@ LDFLAGS += dep/faust/build/lib/libfaust.a

$(libfaust):
cd dep && git clone "https://github.com/grame-cncm/faust.git" --recursive
cd dep/faust && git checkout 1dfc452a8250f3123b5100edf8c882e1cea407a1 && cp -rf libraries/* ../../res/faust
cd dep/faust && make -C build cmake BACKENDS=interp.cmake TARGETS=interp.cmake && make -C build
cd dep/faust && git checkout 1dfc452a8250f3123b5100edf8c882e1cea407a1
cd dep/faust/build && make cmake BACKENDS=interp.cmake TARGETS=interp.cmake
cd dep/faust/build && make install PREFIX="$(DEP_PATH)"
cp -rf dep/faust/libraries/* faust_libraries/

endif

include $(RACK_DIR)/plugin.mk


res/faust/rack.lib → faust_libraries/rack.lib View File


+ 325
- 311
src/FaustEngine.cpp View File

@@ -6,15 +6,15 @@
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 <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
@@ -23,10 +23,6 @@

#include "ScriptEngine.hpp"

#include <faust/dsp/libfaust.h>
#include <faust/gui/DecoratorUI.h>
#include <faust/gui/ValueConverter.h>

#include <iostream>
#include <memory>
#include <map>
@@ -34,326 +30,344 @@
#include <algorithm>
#include <functional>

using namespace std;
#pragma GCC diagnostic push
#ifndef __clang__
#pragma GCC diagnostic ignored "-Wsuggest-override"
#endif
#include <faust/dsp/libfaust.h>
#include <faust/gui/DecoratorUI.h>
#include <faust/gui/ValueConverter.h>

#define kBufferSize 64

#ifdef INTERP
#include <faust/dsp/interpreter-dsp.h>
#include <faust/dsp/interpreter-dsp.h>
#else
#include <faust/dsp/llvm-dsp.h>
#include <faust/dsp/llvm-dsp.h>
#endif
#pragma GCC diagnostic pop

extern rack::Plugin* pluginInstance;

// UI handler for switches, knobs and lights
struct RackUI : public GenericUI
{
typedef function<void(ProcessBlock* block)> updateFunction;
vector<ConverterZoneControl*> fConverters;
vector<updateFunction> fUpdateFunIn;
vector<updateFunction> fUpdateFunOut;
// For checkbox handling
struct CheckBox { float fLastButton = 0.0f; };
map <FAUSTFLOAT*, CheckBox> fCheckBoxes;
string fKey, fValue, fScale;
int getIndex(const string& value)
{
try {
int index = stoi(value);
if (index >= 0 && index <= NUM_ROWS) {
return index;
} else {
cerr << "ERROR : incorrect '" << index << "' value !\n";
return -1;
}
} catch (invalid_argument& e) {
return -1;
}
}
RackUI():fScale("lin")
{}
virtual ~RackUI()
{
for (auto& it : fConverters) delete it;
}
void addButton(const char* label, FAUSTFLOAT* zone)
{
int index = getIndex(fValue);
if (fKey == "switch" && (index != -1)) {
fUpdateFunIn.push_back([=] (ProcessBlock* block)
{
*zone = block->switches[index-1];
// And set the color to red when ON
block->switchLights[index-1][0] = *zone;
});
}
fKey = fValue = "";
}
void addCheckButton(const char* label, FAUSTFLOAT* zone)
{
int index = getIndex(fValue);
if (fKey == "switch" && (index != -1)) {
// Add a checkbox
fCheckBoxes[zone] = CheckBox();
// Update function
fUpdateFunIn.push_back([=] (ProcessBlock* block)
{
float button = block->switches[index-1];
// Detect upfront
if (button == 1.0 && (button != fCheckBoxes[zone].fLastButton)) {
// Switch button state
*zone = !*zone;
// And set the color to white when ON
block->switchLights[index-1][0] = *zone;
block->switchLights[index-1][1] = *zone;
block->switchLights[index-1][2] = *zone;
}
// Keep previous button state
fCheckBoxes[zone].fLastButton = button;
});
}
fKey = fValue = "";
}
void addVerticalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step)
{
addNumEntry(label, zone, init, min, max, step);
}
void addHorizontalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step)
{
addNumEntry(label, zone, init, min, max, step);
}
void addNumEntry(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step)
{
int index = getIndex(fValue);
if (fKey == "knob" && (index != -1)) {
ConverterZoneControl* converter;
if (fScale == "log") {
converter = new ConverterZoneControl(zone, new LogValueConverter(0., 1., min, max));
} else if (fScale == "exp") {
converter = new ConverterZoneControl(zone, new ExpValueConverter(0., 1., min, max));
} else {
converter = new ConverterZoneControl(zone, new LinearValueConverter(0., 1., min, max));
}
fUpdateFunIn.push_back([=] (ProcessBlock* block) { converter->update(block->knobs[index-1]); });
fConverters.push_back(converter);
}
fScale = "lin";
fKey = fValue = "";
}
void addBarGraph(FAUSTFLOAT* zone)
{
int index = getIndex(fValue);
if ((fKey == "light_red") && (index != -1)) {
fUpdateFunOut.push_back([=] (ProcessBlock* block) { block->lights[index-1][0] = *zone; });
} else if ((fKey == "light_green") && (index != -1)) {
fUpdateFunOut.push_back([=] (ProcessBlock* block) { block->lights[index-1][1] = *zone; });
} else if ((fKey == "light_blue") && (index != -1)) {
fUpdateFunOut.push_back([=] (ProcessBlock* block) { block->lights[index-1][2] = *zone; });
} else if ((fKey == "switchlight_red") && (index != -1)) {
fUpdateFunOut.push_back([=] (ProcessBlock* block) { block->switchLights[index-1][0] = *zone; });
} else if ((fKey == "switchlight_green") && (index != -1)) {
fUpdateFunOut.push_back([=] (ProcessBlock* block) { block->switchLights[index-1][1] = *zone; });
} else if ((fKey == "switchlight_blue") && (index != -1)) {
fUpdateFunOut.push_back([=] (ProcessBlock* block) { block->switchLights[index-1][2] = *zone; });
}
fKey = fValue = "";
}
void addHorizontalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max)
{
addBarGraph(zone);
}
void addVerticalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max)
{
addBarGraph(zone);
}
void addSoundfile(const char* label, const char* soundpath, Soundfile** sf_zone)
{
WARN("Faust Prototype : 'soundfile' primitive not yet supported", "");
}
void declare(FAUSTFLOAT* zone, const char* key, const char* val)
{
static vector<string> keys = {"switch", "knob", "light_red", "light_green", "light_blue", "switchlight_red", "switchlight_green", "switchlight_blue"};
if (find(keys.begin(), keys.end(), key) != keys.end()) {
fKey = key;
fValue = val;
} else if (string(key) == "scale") {
fScale = val;
}
}
struct RackUI : public GenericUI {
typedef std::function<void(ProcessBlock* block)> updateFunction;

std::vector<ConverterZoneControl*> fConverters;
std::vector<updateFunction> fUpdateFunIn;
std::vector<updateFunction> fUpdateFunOut;

// For checkbox handling
struct CheckBox {
float fLastButton = 0.0f;
};
std::map <FAUSTFLOAT*, CheckBox> fCheckBoxes;

std::string fKey, fValue, fScale;

int getIndex(const std::string& value) {
try {
int index = stoi(value);
if (index >= 0 && index <= NUM_ROWS) {
return index;
}
else {
WARN("ERROR : incorrect '%d' value", index);
return -1;
}
}
catch (std::invalid_argument& e) {
return -1;
}
}

RackUI(): fScale("lin")
{}

virtual ~RackUI() {
for (auto& it : fConverters)
delete it;
}

void addButton(const char* label, FAUSTFLOAT* zone) override {
int index = getIndex(fValue);
if (fKey == "switch" && (index != -1)) {
fUpdateFunIn.push_back([ = ](ProcessBlock * block) {
*zone = block->switches[index - 1];

// And set the color to red when ON
block->switchLights[index - 1][0] = *zone;
});
}
fKey = fValue = "";
}

void addCheckButton(const char* label, FAUSTFLOAT* zone) override {
int index = getIndex(fValue);
if (fKey == "switch" && (index != -1)) {
// Add a checkbox
fCheckBoxes[zone] = CheckBox();
// Update function
fUpdateFunIn.push_back([ = ](ProcessBlock * block) {
float button = block->switches[index - 1];
// Detect upfront
if (button == 1.0 && (button != fCheckBoxes[zone].fLastButton)) {
// Switch button state
*zone = !*zone;
// And set the color to white when ON
block->switchLights[index - 1][0] = *zone;
block->switchLights[index - 1][1] = *zone;
block->switchLights[index - 1][2] = *zone;
}
// Keep previous button state
fCheckBoxes[zone].fLastButton = button;
});
}
fKey = fValue = "";
}

void addVerticalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) override {
addNumEntry(label, zone, init, min, max, step);
}

void addHorizontalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) override {
addNumEntry(label, zone, init, min, max, step);
}

void addNumEntry(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) override {
int index = getIndex(fValue);
if (fKey == "knob" && (index != -1)) {
ConverterZoneControl* converter;
if (fScale == "log") {
converter = new ConverterZoneControl(zone, new LogValueConverter(0., 1., min, max));
}
else if (fScale == "exp") {
converter = new ConverterZoneControl(zone, new ExpValueConverter(0., 1., min, max));
}
else {
converter = new ConverterZoneControl(zone, new LinearValueConverter(0., 1., min, max));
}
fUpdateFunIn.push_back([ = ](ProcessBlock * block) {
converter->update(block->knobs[index - 1]);
});
fConverters.push_back(converter);
}
fScale = "lin";
fKey = fValue = "";
}

void addBarGraph(FAUSTFLOAT* zone) {
int index = getIndex(fValue);
if ((fKey == "light_red") && (index != -1)) {
fUpdateFunOut.push_back([ = ](ProcessBlock * block) {
block->lights[index - 1][0] = *zone;
});
}
else if ((fKey == "light_green") && (index != -1)) {
fUpdateFunOut.push_back([ = ](ProcessBlock * block) {
block->lights[index - 1][1] = *zone;
});
}
else if ((fKey == "light_blue") && (index != -1)) {
fUpdateFunOut.push_back([ = ](ProcessBlock * block) {
block->lights[index - 1][2] = *zone;
});
}
else if ((fKey == "switchlight_red") && (index != -1)) {
fUpdateFunOut.push_back([ = ](ProcessBlock * block) {
block->switchLights[index - 1][0] = *zone;
});
}
else if ((fKey == "switchlight_green") && (index != -1)) {
fUpdateFunOut.push_back([ = ](ProcessBlock * block) {
block->switchLights[index - 1][1] = *zone;
});
}
else if ((fKey == "switchlight_blue") && (index != -1)) {
fUpdateFunOut.push_back([ = ](ProcessBlock * block) {
block->switchLights[index - 1][2] = *zone;
});
}
fKey = fValue = "";
}

void addHorizontalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max) override {
addBarGraph(zone);
}

void addVerticalBargraph(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max) override {
addBarGraph(zone);
}

void addSoundfile(const char* label, const char* soundpath, Soundfile** sf_zone) override {
WARN("Faust Prototype : 'soundfile' primitive not yet supported", "");
}

void declare(FAUSTFLOAT* zone, const char* key, const char* val) override {
static std::vector<std::string> keys = {"switch", "knob", "light_red", "light_green", "light_blue", "switchlight_red", "switchlight_green", "switchlight_blue"};
if (find(keys.begin(), keys.end(), key) != keys.end()) {
fKey = key;
fValue = val;
}
else if (std::string(key) == "scale") {
fScale = val;
}
}
};

// Faust engine using libfaust/LLVM
class FaustEngine : public ScriptEngine {
public:
FaustEngine():
fDSPFactory(nullptr),
fDSP(nullptr),
fInputs(nullptr),
fOutputs(nullptr),
fDSPLibraries(rack::asset::plugin(pluginInstance, "res/faust"))
{}
~FaustEngine()
{
delete [] fInputs;
delete [] fOutputs;
delete fDSP;
#ifdef INTERP
deleteInterpreterDSPFactory(static_cast<interpreter_dsp_factory*>(fDSPFactory));
#else
deleteDSPFactory(static_cast<llvm_dsp_factory*>(fDSPFactory));
#endif
}
string getEngineName() override
{
return "Faust";
}
int run(const string& path, const string& script) override
{
#if defined ARCH_LIN
string temp_cache = "/var/tmp/VCV_" + generateSHA1(script);
#elif defined ARCH_MAC
string temp_cache = "/private/var/tmp/VCV_" + generateSHA1(script);
#elif defined ARCH_WIN
char buf[MAX_PATH+1] = {0};
GetTempPath(sizeof(buf), buf);
string temp_cache = string(buf) + "/VCV_" + generateSHA1(script);
#endif
string error_msg;
// Try to load the machine code cache
#ifdef INTERP
fDSPFactory = readInterpreterDSPFactoryFromBitcodeFile(temp_cache, error_msg);
#else
fDSPFactory = readDSPFactoryFromMachineFile(temp_cache, "", error_msg);
#endif
if (!fDSPFactory) {
// Otherwise recompile the DSP
int argc = 0;
const char* argv[8];
argv[argc++] = "-I";
argv[argc++] = fDSPLibraries.c_str();
argv[argc] = nullptr; // NULL terminated argv
#ifdef INTERP
fDSPFactory = createInterpreterDSPFactoryFromString("FaustDSP", script, argc, argv, error_msg);
#else
fDSPFactory = createDSPFactoryFromString("FaustDSP", script, argc, argv, "", error_msg, -1);
#endif
if (!fDSPFactory) {
display("ERROR : cannot create factory !");
WARN("Faust Prototype : %s", error_msg.c_str());
return -1;
} else {
// And save the cache
display("Compiling factory finished");
#ifdef INTERP
writeInterpreterDSPFactoryToBitcodeFile(static_cast<interpreter_dsp_factory*>(fDSPFactory), temp_cache);
#else
writeDSPFactoryToMachineFile(static_cast<llvm_dsp_factory*>(fDSPFactory), temp_cache, "");
#endif
}
}
// Create DSP
fDSP = fDSPFactory->createDSPInstance();
if (!fDSP) {
display("ERROR: cannot create instance !");
return -1;
} else {
display("Created DSP");
}
// Check inputs/outputs
if (fDSP->getNumInputs() > NUM_ROWS) {
display("ERROR: DSP has " + to_string(fDSP->getNumInputs()) + " inputs !");
return -1;
}
if (fDSP->getNumOutputs() > NUM_ROWS) {
display("ERROR: DSP has " + to_string(fDSP->getNumInputs()) + " outputs !");
return -1;
}
// Prepare buffers for process
ProcessBlock* block = getProcessBlock();
fInputs = new FAUSTFLOAT*[fDSP->getNumInputs()];
for (int chan = 0; chan < fDSP->getNumInputs(); chan++) {
fInputs[chan] = block->inputs[chan];
}
fOutputs = new FAUSTFLOAT*[fDSP->getNumOutputs()];
for (int chan = 0; chan < fDSP->getNumOutputs(); chan++) {
fOutputs[chan] = block->outputs[chan];
}
// Setup UI
fDSP->buildUserInterface(&fRackUI);
setFrameDivider(1);
setBufferSize(kBufferSize);
// Init DSP with default SR
fDSP->init(44100);
return 0;
}
int process() override
{
ProcessBlock* block = getProcessBlock();
// Possibly update SR
if (block->sampleRate != fDSP->getSampleRate()) {
fDSP->init(block->sampleRate);
}
// Update inputs controllers
for (auto& it : fRackUI.fUpdateFunIn) it(block);
// Compute samples
fDSP->compute(block->bufferSize, fInputs, fOutputs);
// Update output controllers
for (auto& it : fRackUI.fUpdateFunOut) it(block);
return 0;
}
private:
dsp_factory* fDSPFactory;
dsp* fDSP;
FAUSTFLOAT** fInputs;
FAUSTFLOAT** fOutputs;
RackUI fRackUI;
string fDSPLibraries;
public:
FaustEngine():
fDSPFactory(nullptr),
fDSP(nullptr),
fInputs(nullptr),
fOutputs(nullptr),
fDSPLibraries(rack::asset::plugin(pluginInstance, "faust_libraries"))
{}
~FaustEngine() {
delete [] fInputs;
delete [] fOutputs;
delete fDSP;
#ifdef INTERP
deleteInterpreterDSPFactory(static_cast<interpreter_dsp_factory*>(fDSPFactory));
#else
deleteDSPFactory(static_cast<llvm_dsp_factory*>(fDSPFactory));
#endif
}
std::string getEngineName() override {
return "Faust";
}
int run(const std::string& path, const std::string& script) override {
#if defined ARCH_LIN
std::string temp_cache = "/var/tmp/VCV_" + generateSHA1(script);
#elif defined ARCH_MAC
std::string temp_cache = "/private/var/tmp/VCV_" + generateSHA1(script);
#elif defined ARCH_WIN
char buf[MAX_PATH + 1] = {0};
GetTempPath(sizeof(buf), buf);
std::string temp_cache = std::string(buf) + "/VCV_" + generateSHA1(script);
#endif
std::string error_msg;
// Try to load the machine code cache
#ifdef INTERP
fDSPFactory = readInterpreterDSPFactoryFromBitcodeFile(temp_cache, error_msg);
#else
fDSPFactory = readDSPFactoryFromMachineFile(temp_cache, "", error_msg);
#endif
if (!fDSPFactory) {
// Otherwise recompile the DSP
int argc = 0;
const char* argv[8];
argv[argc++] = "-I";
argv[argc++] = fDSPLibraries.c_str();
argv[argc] = nullptr; // NULL terminated argv
#ifdef INTERP
fDSPFactory = createInterpreterDSPFactoryFromString("FaustDSP", script, argc, argv, error_msg);
#else
fDSPFactory = createDSPFactoryFromString("FaustDSP", script, argc, argv, "", error_msg, -1);
#endif
if (!fDSPFactory) {
display("ERROR : cannot create factory !");
WARN("Faust Prototype : %s", error_msg.c_str());
return -1;
}
else {
// And save the cache
display("Compiling factory finished");
#ifdef INTERP
writeInterpreterDSPFactoryToBitcodeFile(static_cast<interpreter_dsp_factory*>(fDSPFactory), temp_cache);
#else
writeDSPFactoryToMachineFile(static_cast<llvm_dsp_factory*>(fDSPFactory), temp_cache, "");
#endif
}
}
// Create DSP
fDSP = fDSPFactory->createDSPInstance();
if (!fDSP) {
display("ERROR: cannot create instance !");
return -1;
}
else {
display("Created DSP");
}
// Check inputs/outputs
if (fDSP->getNumInputs() > NUM_ROWS) {
display("ERROR: DSP has " + std::to_string(fDSP->getNumInputs()) + " inputs !");
return -1;
}
if (fDSP->getNumOutputs() > NUM_ROWS) {
display("ERROR: DSP has " + std::to_string(fDSP->getNumInputs()) + " outputs !");
return -1;
}
// Prepare buffers for process
ProcessBlock* block = getProcessBlock();
fInputs = new FAUSTFLOAT*[fDSP->getNumInputs()];
for (int chan = 0; chan < fDSP->getNumInputs(); chan++) {
fInputs[chan] = block->inputs[chan];
}
fOutputs = new FAUSTFLOAT*[fDSP->getNumOutputs()];
for (int chan = 0; chan < fDSP->getNumOutputs(); chan++) {
fOutputs[chan] = block->outputs[chan];
}
// Setup UI
fDSP->buildUserInterface(&fRackUI);
setFrameDivider(1);
setBufferSize(kBufferSize);
// Init DSP with default SR
fDSP->init(44100);
return 0;
}
int process() override {
ProcessBlock* block = getProcessBlock();
// Possibly update SR
if (block->sampleRate != fDSP->getSampleRate()) {
fDSP->init(block->sampleRate);
}
// Update inputs controllers
for (auto& it : fRackUI.fUpdateFunIn)
it(block);
// Compute samples
fDSP->compute(block->bufferSize, fInputs, fOutputs);
// Update output controllers
for (auto& it : fRackUI.fUpdateFunOut)
it(block);
return 0;
}
private:
dsp_factory* fDSPFactory;
dsp* fDSP;
FAUSTFLOAT** fInputs;
FAUSTFLOAT** fOutputs;
RackUI fRackUI;
std::string fDSPLibraries;
};

__attribute__((constructor(1000)))
static void constructor() {
addScriptEngine<FaustEngine>("dsp");
addScriptEngine<FaustEngine>("dsp");
}

Loading…
Cancel
Save