|
|
@@ -0,0 +1,221 @@ |
|
|
|
/* |
|
|
|
* DISTRHO Cardinal Plugin |
|
|
|
* Copyright (C) 2021 Filipe Coelho <falktx@falktx.com> |
|
|
|
* |
|
|
|
* 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 3 of |
|
|
|
* the License, or 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. |
|
|
|
* |
|
|
|
* For a full copy of the GNU General Public License see the LICENSE file. |
|
|
|
*/ |
|
|
|
|
|
|
|
#include "src/lv2/buf-size.h" |
|
|
|
#include "src/lv2/options.h" |
|
|
|
#include <rack.hpp> |
|
|
|
#include <context.hpp> |
|
|
|
|
|
|
|
#include "DistrhoUtils.hpp" |
|
|
|
|
|
|
|
using namespace rack; |
|
|
|
|
|
|
|
extern Model* modelSpringReverb; |
|
|
|
Plugin* pluginInstance__Befaco; |
|
|
|
|
|
|
|
namespace rack { |
|
|
|
namespace settings { |
|
|
|
bool cpuMeter = false; |
|
|
|
} |
|
|
|
Context::~Context() { |
|
|
|
} |
|
|
|
static thread_local Context* threadContext = nullptr; |
|
|
|
Context* contextGet() { |
|
|
|
DISTRHO_SAFE_ASSERT(threadContext != nullptr); |
|
|
|
return threadContext; |
|
|
|
} |
|
|
|
// Apple's clang incorrectly compiles this function when -O2 or higher is enabled. |
|
|
|
#ifdef ARCH_MAC |
|
|
|
__attribute__((optnone)) |
|
|
|
#endif |
|
|
|
void contextSet(Context* const context) { |
|
|
|
// DISTRHO_SAFE_ASSERT(threadContext == nullptr); |
|
|
|
threadContext = context; |
|
|
|
} |
|
|
|
Exception::Exception(const char* format, ...) |
|
|
|
{ |
|
|
|
va_list args; |
|
|
|
va_start(args, format); |
|
|
|
msg = string::fV(format, args); |
|
|
|
va_end(args); |
|
|
|
} |
|
|
|
namespace asset { |
|
|
|
std::string plugin(plugin::Plugin* plugin, std::string filename) { return {}; } |
|
|
|
std::string system(std::string filename) { return {}; } |
|
|
|
} |
|
|
|
namespace engine { |
|
|
|
float Engine::getParamValue(Module* module, int paramId) { return 0.0f; } |
|
|
|
float Engine::getParamSmoothValue(Module* module, int paramId) { return 0.0f; } |
|
|
|
void Engine::setParamValue(Module* module, int paramId, float value) {} |
|
|
|
void Engine::setParamSmoothValue(Module* module, int paramId, float value) {} |
|
|
|
} |
|
|
|
namespace plugin { |
|
|
|
void Plugin::addModel(Model* model) |
|
|
|
{ |
|
|
|
// Check that the model is not added to a plugin already |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(model != nullptr,); |
|
|
|
DISTRHO_SAFE_ASSERT_RETURN(model->plugin == nullptr,); |
|
|
|
model->plugin = this; |
|
|
|
models.push_back(model); |
|
|
|
} |
|
|
|
Model* modelFromJson(json_t* moduleJ) { |
|
|
|
return nullptr; |
|
|
|
} |
|
|
|
std::vector<Plugin*> plugins; |
|
|
|
} // namespace plugin |
|
|
|
} // namespace rack |
|
|
|
|
|
|
|
struct PluginLv2 { |
|
|
|
Plugin* plugin; |
|
|
|
engine::Module* module; |
|
|
|
float sampleRate; |
|
|
|
int frameCount = 0; |
|
|
|
|
|
|
|
void* ports[11]; |
|
|
|
|
|
|
|
PluginLv2(double sr) |
|
|
|
{ |
|
|
|
sampleRate = sr; |
|
|
|
plugin = new Plugin; |
|
|
|
pluginInstance__Befaco = plugin; |
|
|
|
plugin->addModel(modelSpringReverb); |
|
|
|
module = modelSpringReverb->createModule(); |
|
|
|
|
|
|
|
// FIXME we need to detect if something is connected |
|
|
|
// module->inputs[0].channels = 1; |
|
|
|
// module->inputs[1].channels = 1; |
|
|
|
module->inputs[2].channels = 1; |
|
|
|
module->inputs[3].channels = 1; |
|
|
|
module->inputs[4].channels = 1; |
|
|
|
module->outputs[0].channels = 1; |
|
|
|
module->outputs[1].channels = 1; |
|
|
|
} |
|
|
|
|
|
|
|
void lv2_connect_port(const uint32_t port, void* const dataLocation) |
|
|
|
{ |
|
|
|
ports[port] = dataLocation; |
|
|
|
} |
|
|
|
|
|
|
|
void lv2_run(const uint32_t sampleCount) |
|
|
|
{ |
|
|
|
if (sampleCount == 0) |
|
|
|
return; |
|
|
|
|
|
|
|
Module::ProcessArgs args = { |
|
|
|
sampleRate, |
|
|
|
1.0f / sampleRate, |
|
|
|
frameCount |
|
|
|
}; |
|
|
|
|
|
|
|
const float* CV1_INPUT = (float*)ports[0]; |
|
|
|
const float* CV2_INPUT = (float*)ports[1]; |
|
|
|
const float* IN1_INPUT = (float*)ports[2]; |
|
|
|
const float* IN2_INPUT = (float*)ports[3]; |
|
|
|
const float* MIX_CV_INPUT = (float*)ports[4]; |
|
|
|
float* MIX_OUTPUT = (float*)ports[5]; |
|
|
|
float* WET_OUTPUT = (float*)ports[6]; |
|
|
|
|
|
|
|
const float drywet = *(float*)ports[7] * 0.01f; |
|
|
|
const float lvl1 = *(float*)ports[8] * 0.01f; |
|
|
|
const float lvl2 = *(float*)ports[9] * 0.01f; |
|
|
|
const float hpf = *(float*)ports[10]; |
|
|
|
|
|
|
|
module->params[0].setValue(drywet); |
|
|
|
module->params[1].setValue(lvl1); |
|
|
|
module->params[2].setValue(lvl2); |
|
|
|
module->params[3].setValue(hpf); |
|
|
|
|
|
|
|
for (uint32_t i=0; i<sampleCount; ++i) |
|
|
|
{ |
|
|
|
module->inputs[0].setVoltage(CV1_INPUT[i]); |
|
|
|
module->inputs[1].setVoltage(CV2_INPUT[i]); |
|
|
|
module->inputs[2].setVoltage(IN1_INPUT[i] * 10); |
|
|
|
module->inputs[3].setVoltage(IN2_INPUT[i] * 10); |
|
|
|
module->inputs[4].setVoltage(MIX_CV_INPUT[i]); |
|
|
|
module->doProcess(args); |
|
|
|
MIX_OUTPUT[i] = module->outputs[0].getVoltage() * 0.1f; |
|
|
|
WET_OUTPUT[i] = module->outputs[1].getVoltage() * 0.1f; |
|
|
|
++args.frame; |
|
|
|
} |
|
|
|
|
|
|
|
frameCount += sampleCount; |
|
|
|
} |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
static LV2_Handle lv2_instantiate(const LV2_Descriptor*, double sampleRate, const char* bundlePath, const LV2_Feature* const* features) |
|
|
|
{ |
|
|
|
return new PluginLv2(sampleRate); |
|
|
|
} |
|
|
|
|
|
|
|
// ----------------------------------------------------------------------- |
|
|
|
|
|
|
|
#define instancePtr ((PluginLv2*)instance) |
|
|
|
|
|
|
|
static void lv2_connect_port(LV2_Handle instance, uint32_t port, void* dataLocation) |
|
|
|
{ |
|
|
|
instancePtr->lv2_connect_port(port, dataLocation); |
|
|
|
} |
|
|
|
|
|
|
|
static void lv2_activate(LV2_Handle instance) |
|
|
|
{ |
|
|
|
} |
|
|
|
|
|
|
|
static void lv2_run(LV2_Handle instance, uint32_t sampleCount) |
|
|
|
{ |
|
|
|
instancePtr->lv2_run(sampleCount); |
|
|
|
} |
|
|
|
|
|
|
|
static void lv2_deactivate(LV2_Handle instance) |
|
|
|
{ |
|
|
|
} |
|
|
|
|
|
|
|
static void lv2_cleanup(LV2_Handle instance) |
|
|
|
{ |
|
|
|
delete instancePtr; |
|
|
|
} |
|
|
|
|
|
|
|
// ----------------------------------------------------------------------- |
|
|
|
|
|
|
|
static const void* lv2_extension_data(const char* uri) |
|
|
|
{ |
|
|
|
return nullptr; |
|
|
|
} |
|
|
|
|
|
|
|
#undef instancePtr |
|
|
|
|
|
|
|
// ----------------------------------------------------------------------- |
|
|
|
|
|
|
|
static const LV2_Descriptor sLv2Descriptor = { |
|
|
|
"urn:Cardinal:Befaco", |
|
|
|
lv2_instantiate, |
|
|
|
lv2_connect_port, |
|
|
|
lv2_activate, |
|
|
|
lv2_run, |
|
|
|
lv2_deactivate, |
|
|
|
lv2_cleanup, |
|
|
|
lv2_extension_data |
|
|
|
}; |
|
|
|
|
|
|
|
DISTRHO_PLUGIN_EXPORT |
|
|
|
const LV2_Descriptor* lv2_descriptor(uint32_t index) |
|
|
|
{ |
|
|
|
USE_NAMESPACE_DISTRHO |
|
|
|
return (index == 0) ? &sLv2Descriptor : nullptr; |
|
|
|
} |
|
|
|
|
|
|
|
// ----------------------------------------------------------------------- |