|
|
@@ -29,6 +29,9 @@ |
|
|
|
#include <faust/gui/ValueConverter.h> |
|
|
|
|
|
|
|
#include <iostream> |
|
|
|
#include <memory> |
|
|
|
|
|
|
|
using namespace std; |
|
|
|
|
|
|
|
#define kBufferSize 64 |
|
|
|
|
|
|
@@ -37,87 +40,42 @@ extern rack::Plugin* pluginInstance; |
|
|
|
// UI handler for switches, knobs and leds |
|
|
|
struct RackUI : public GenericUI |
|
|
|
{ |
|
|
|
// 0|1 switches |
|
|
|
FAUSTFLOAT* fSwitches[NUM_ROWS]; |
|
|
|
|
|
|
|
// Knobs with [0..1] <==> [min..max] mapping and medata 'scale' handling |
|
|
|
ConverterZoneControl* fKnobs[NUM_ROWS]; |
|
|
|
|
|
|
|
// Leds |
|
|
|
FAUSTFLOAT* fLedRed[NUM_ROWS]; |
|
|
|
FAUSTFLOAT* fLedGreen[NUM_ROWS]; |
|
|
|
FAUSTFLOAT* fLedBlue[NUM_ROWS]; |
|
|
|
typedef function<void(ProcessBlock* block)> updateFunction; |
|
|
|
|
|
|
|
// Switch Leds |
|
|
|
FAUSTFLOAT* fSwitchRed[NUM_ROWS]; |
|
|
|
FAUSTFLOAT* fSwitchGreen[NUM_ROWS]; |
|
|
|
FAUSTFLOAT* fSwitchBlue[NUM_ROWS]; |
|
|
|
vector<ConverterZoneControl*> fConverters; |
|
|
|
vector<updateFunction> fUpdateFunIn; |
|
|
|
vector<updateFunction> fUpdateFunOut; |
|
|
|
string fKey, fValue, fScale; |
|
|
|
|
|
|
|
std::string fKey, fValue, fScale; |
|
|
|
|
|
|
|
void addItem(FAUSTFLOAT* table[NUM_ROWS], FAUSTFLOAT* zone, const std::string& value) |
|
|
|
int getIndex(const string& value) |
|
|
|
{ |
|
|
|
try { |
|
|
|
int index = std::stoi(value); |
|
|
|
int index = stoi(value); |
|
|
|
if (index >= 0 && index <= NUM_ROWS) { |
|
|
|
table[index-1] = zone; |
|
|
|
return index; |
|
|
|
} else { |
|
|
|
std::cerr << "ERROR : incorrect '" << index << "' value !\n"; |
|
|
|
} |
|
|
|
} catch (std::invalid_argument& e) { |
|
|
|
std::cerr << "ERROR : " << e.what() << std::endl; |
|
|
|
} |
|
|
|
fValue = fKey = fScale = ""; |
|
|
|
} |
|
|
|
|
|
|
|
void addItemConverter(ConverterZoneControl* table[NUM_ROWS], FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max, const std::string& value) |
|
|
|
{ |
|
|
|
try { |
|
|
|
int index = std::stoi(value); |
|
|
|
if (index >= 0 && index <= NUM_ROWS) { |
|
|
|
// Select appropriate converter according to scale mode |
|
|
|
if (fScale == "log") { |
|
|
|
table[index-1] = new ConverterZoneControl(zone, new LogValueConverter(0., 1., min, max)); |
|
|
|
} else if (fScale == "exp") { |
|
|
|
table[index-1] = new ConverterZoneControl(zone, new ExpValueConverter(0., 1., min, max)); |
|
|
|
} else { |
|
|
|
table[index-1] = new ConverterZoneControl(zone, new LinearValueConverter(0., 1., min, max)); |
|
|
|
} |
|
|
|
} else { |
|
|
|
std::cerr << "ERROR : incorrect '" << index << "' value !\n"; |
|
|
|
cerr << "ERROR : incorrect '" << index << "' value !\n"; |
|
|
|
return -1; |
|
|
|
} |
|
|
|
} catch (std::invalid_argument& e) { |
|
|
|
std::cerr << "ERROR : " << e.what() << std::endl; |
|
|
|
} |
|
|
|
fValue = fKey = fScale = ""; |
|
|
|
} |
|
|
|
|
|
|
|
RackUI() |
|
|
|
{ |
|
|
|
fScale = "lin"; |
|
|
|
for (int i = 0; i < NUM_ROWS; i++) { |
|
|
|
fSwitches[i] = nullptr; |
|
|
|
fKnobs[i] = nullptr; |
|
|
|
fLedRed[i] = nullptr; |
|
|
|
fLedGreen[i] = nullptr; |
|
|
|
fLedBlue[i] = nullptr; |
|
|
|
fSwitchRed[i] = nullptr; |
|
|
|
fSwitchGreen[i] = nullptr; |
|
|
|
fSwitchBlue[i] = nullptr; |
|
|
|
} catch (invalid_argument& e) { |
|
|
|
cerr << "ERROR : " << e.what() << endl; |
|
|
|
return -1; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
RackUI():fScale("lin") |
|
|
|
{} |
|
|
|
|
|
|
|
virtual ~RackUI() |
|
|
|
{ |
|
|
|
for (int i = 0; i < NUM_ROWS; i++) { |
|
|
|
delete fKnobs[i]; |
|
|
|
} |
|
|
|
for (auto& it : fConverters) delete it; |
|
|
|
} |
|
|
|
|
|
|
|
void addButton(const char* label, FAUSTFLOAT* zone) |
|
|
|
{ |
|
|
|
if (fKey == "switch") { |
|
|
|
addItem(fSwitches, zone, fValue); |
|
|
|
int index = getIndex(fValue); |
|
|
|
if (fKey == "switch" && (index != -1)) { |
|
|
|
fUpdateFunIn.push_back([=] (ProcessBlock* block) { *zone = block->switches[index-1]; }); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@@ -129,27 +87,39 @@ struct RackUI : public GenericUI |
|
|
|
{ |
|
|
|
addNumEntry(label, zone, init, min, max, step); |
|
|
|
} |
|
|
|
|
|
|
|
void addNumEntry(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) |
|
|
|
{ |
|
|
|
if (fKey == "knob") { |
|
|
|
addItemConverter(fKnobs, zone, min, max, fValue); |
|
|
|
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); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void addBarGraph(FAUSTFLOAT* zone) |
|
|
|
{ |
|
|
|
if (fKey == "led_red") { |
|
|
|
addItem(fLedRed, zone, fValue); |
|
|
|
} else if (fKey == "led_green") { |
|
|
|
addItem(fLedGreen, zone, fValue); |
|
|
|
} else if (fKey == "led_blue") { |
|
|
|
addItem(fLedBlue, zone, fValue); |
|
|
|
} else if (fKey == "switch_red") { |
|
|
|
addItem(fSwitchRed, zone, fValue); |
|
|
|
} else if (fKey == "switch_green") { |
|
|
|
addItem(fSwitchGreen, zone, fValue); |
|
|
|
} else if (fKey == "switch_blue") { |
|
|
|
addItem(fSwitchBlue, zone, fValue); |
|
|
|
int index = getIndex(fValue); |
|
|
|
if ((fKey == "led_red") && (index != -1)) { |
|
|
|
fUpdateFunOut.push_back([=] (ProcessBlock* block) { block->lights[index-1][0] = *zone; }); |
|
|
|
} else if ((fKey == "led_green") && (index != -1)) { |
|
|
|
fUpdateFunOut.push_back([=] (ProcessBlock* block) { block->lights[index-1][1] = *zone; }); |
|
|
|
} else if ((fKey == "led_blue") && (index != -1)) { |
|
|
|
fUpdateFunOut.push_back([=] (ProcessBlock* block) { block->lights[index-1][2] = *zone; }); |
|
|
|
} else if ((fKey == "switch_red") && (index != -1)) { |
|
|
|
fUpdateFunOut.push_back([=] (ProcessBlock* block) { block->switchLights[index-1][0] = *zone; }); |
|
|
|
} else if ((fKey == "switch_green") && (index != -1)) { |
|
|
|
fUpdateFunOut.push_back([=] (ProcessBlock* block) { block->switchLights[index-1][1] = *zone; }); |
|
|
|
} else if ((fKey == "switch_blue") && (index != -1)) { |
|
|
|
fUpdateFunOut.push_back([=] (ProcessBlock* block) { block->switchLights[index-1][2] = *zone; }); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@@ -164,17 +134,11 @@ struct RackUI : public GenericUI |
|
|
|
|
|
|
|
void declare(FAUSTFLOAT* zone, const char* key, const char* val) |
|
|
|
{ |
|
|
|
if ((std::string(key) == "switch") |
|
|
|
|| (std::string(key) == "knob") |
|
|
|
|| (std::string(key) == "led_red") |
|
|
|
|| (std::string(key) == "led_green") |
|
|
|
|| (std::string(key) == "led_blue") |
|
|
|
|| (std::string(key) == "switch_red") |
|
|
|
|| (std::string(key) == "switch_green") |
|
|
|
|| (std::string(key) == "switch_blue")) { |
|
|
|
static vector<string> keys = {"switch", "knob", "led_red", "led_green", "led_blue", "switch_red", "switch_green", "switch_blue"}; |
|
|
|
if (find(keys.begin(), keys.end(), key) != keys.end()) { |
|
|
|
fKey = key; |
|
|
|
fValue = val; |
|
|
|
} else if (std::string(key) == "scale") { |
|
|
|
} else if (string(key) == "scale") { |
|
|
|
fScale = val; |
|
|
|
} |
|
|
|
} |
|
|
@@ -202,19 +166,19 @@ class FaustEngine : public ScriptEngine { |
|
|
|
deleteDSPFactory(fDSPFactory); |
|
|
|
} |
|
|
|
|
|
|
|
std::string getEngineName() override |
|
|
|
string getEngineName() override |
|
|
|
{ |
|
|
|
return "Faust"; |
|
|
|
} |
|
|
|
|
|
|
|
int run(const std::string& path, const std::string& script) override |
|
|
|
int run(const string& path, const string& script) override |
|
|
|
{ |
|
|
|
#if defined ARCH_MAC |
|
|
|
std::string temp_cache = "/private/var/tmp/VCV_" + generateSHA1(script); |
|
|
|
string temp_cache = "/private/var/tmp/VCV_" + generateSHA1(script); |
|
|
|
#else |
|
|
|
std::string temp_cache = "" + generateSHA1(script); |
|
|
|
string temp_cache = "" + generateSHA1(script); |
|
|
|
#endif |
|
|
|
std::string error_msg; |
|
|
|
string error_msg; |
|
|
|
|
|
|
|
// Try to load the machine code cache |
|
|
|
fDSPFactory = readDSPFactoryFromMachineFile(temp_cache, "", error_msg); |
|
|
@@ -250,12 +214,12 @@ class FaustEngine : public ScriptEngine { |
|
|
|
|
|
|
|
// Prepare inputs/outputs |
|
|
|
if (fDSP->getNumInputs() > NUM_ROWS) { |
|
|
|
display("ERROR: DSP has " + std::to_string(fDSP->getNumInputs()) + " inputs !"); |
|
|
|
display("ERROR: DSP has " + to_string(fDSP->getNumInputs()) + " inputs !"); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
if (fDSP->getNumOutputs() > NUM_ROWS) { |
|
|
|
display("ERROR: DSP has " + std::to_string(fDSP->getNumInputs()) + " outputs !"); |
|
|
|
display("ERROR: DSP has " + to_string(fDSP->getNumInputs()) + " outputs !"); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
@@ -293,39 +257,13 @@ class FaustEngine : public ScriptEngine { |
|
|
|
} |
|
|
|
|
|
|
|
// Update inputs controllers |
|
|
|
for (int i = 0; i < NUM_ROWS; i++) { |
|
|
|
if (fRackUI.fSwitches[i]) { |
|
|
|
*fRackUI.fSwitches[i] = block->switches[i]; |
|
|
|
} |
|
|
|
if (fRackUI.fKnobs[i]) { |
|
|
|
fRackUI.fKnobs[i]->update(block->knobs[i]); |
|
|
|
} |
|
|
|
} |
|
|
|
for (auto& it : fRackUI.fUpdateFunIn) it(block); |
|
|
|
|
|
|
|
// Compute samples |
|
|
|
fDSP->compute(kBufferSize, fInputs, fOutputs); |
|
|
|
fDSP->compute(block->bufferSize, fInputs, fOutputs); |
|
|
|
|
|
|
|
// Update output controllers |
|
|
|
for (int i = 0; i < NUM_ROWS; i++) { |
|
|
|
if (fRackUI.fLedRed[i]) { |
|
|
|
block->lights[i][0] = *fRackUI.fLedRed[i]; |
|
|
|
} |
|
|
|
if (fRackUI.fLedGreen[i]) { |
|
|
|
block->lights[i][1] = *fRackUI.fLedGreen[i]; |
|
|
|
} |
|
|
|
if (fRackUI.fLedBlue[i]) { |
|
|
|
block->lights[i][2] = *fRackUI.fLedBlue[i]; |
|
|
|
} |
|
|
|
if (fRackUI.fSwitchRed[i]) { |
|
|
|
block->switchLights[i][0] = *fRackUI.fSwitchRed[i]; |
|
|
|
} |
|
|
|
if (fRackUI.fSwitchGreen[i]) { |
|
|
|
block->switchLights[i][1] = *fRackUI.fSwitchGreen[i]; |
|
|
|
} |
|
|
|
if (fRackUI.fSwitchBlue[i]) { |
|
|
|
block->switchLights[i][2] = *fRackUI.fSwitchBlue[i]; |
|
|
|
} |
|
|
|
} |
|
|
|
for (auto& it : fRackUI.fUpdateFunOut) it(block); |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
@@ -336,7 +274,7 @@ class FaustEngine : public ScriptEngine { |
|
|
|
FAUSTFLOAT** fInputs; |
|
|
|
FAUSTFLOAT** fOutputs; |
|
|
|
RackUI fRackUI; |
|
|
|
std::string fDSPLibraries; |
|
|
|
string fDSPLibraries; |
|
|
|
}; |
|
|
|
|
|
|
|
__attribute__((constructor(1000))) |
|
|
|