diff --git a/plugins/Cardinal/orig/HostAudio.svg b/plugins/Cardinal/orig/HostAudio.svg new file mode 100644 index 0000000..7d5247d --- /dev/null +++ b/plugins/Cardinal/orig/HostAudio.svg @@ -0,0 +1,103 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + Host Audio + + diff --git a/plugins/Cardinal/plugin.json b/plugins/Cardinal/plugin.json index 0265114..5f1f06c 100644 --- a/plugins/Cardinal/plugin.json +++ b/plugins/Cardinal/plugin.json @@ -13,13 +13,29 @@ "changelogUrl": "", "modules": [ + { + "slug": "HostAudio2", + "name": "Audio 2", + "description": "Exposes host-provided audio ports in a module", + "tags": [ + "External" + ] + }, + { + "slug": "HostAudio8", + "name": "Audio 8", + "description": "Exposes host-provided audio ports in a module", + "tags": [ + "External" + ] + }, { "slug": "HostCV", "disabled": false, "name": "Host CV", "description": "Exposes host-provided CV ports in a module", "tags": [ - "Utility" + "External" ] }, { @@ -28,7 +44,7 @@ "name": "Host Parameters", "description": "Exposes host-controlled plugin parameters in a module", "tags": [ - "Utility" + "External" ] }, { @@ -37,7 +53,7 @@ "name": "Host Time", "description": "Exposes host-provided time/transport information in a module", "tags": [ - "Utility" + "External" ] }, { diff --git a/plugins/Cardinal/res/HostAudio.svg b/plugins/Cardinal/res/HostAudio.svg new file mode 100644 index 0000000..8d56ae9 --- /dev/null +++ b/plugins/Cardinal/res/HostAudio.svg @@ -0,0 +1,133 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/Cardinal/src/HostAudio.cpp b/plugins/Cardinal/src/HostAudio.cpp new file mode 100644 index 0000000..802bc7d --- /dev/null +++ b/plugins/Cardinal/src/HostAudio.cpp @@ -0,0 +1,197 @@ +/* + * DISTRHO Cardinal Plugin + * Copyright (C) 2021-2022 Filipe Coelho + * + * 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 "plugincontext.hpp" + +// ----------------------------------------------------------------------------------------------------------- + +USE_NAMESPACE_DISTRHO; + +template +struct HostAudio : Module { + CardinalPluginContext* const pcontext; + const int numParams; + const int numInputs; + const int numOutputs; + int dataFrame = 0; + int64_t lastBlockFrame = -1; + + // for rack core audio module compatibility + dsp::RCFilter dcFilters[numIO]; + bool dcFilterEnabled = (numIO == 2); + + HostAudio() + : pcontext(static_cast(APP)), + numParams(numIO == 2 ? 1 : 0), + numInputs(pcontext->variant == kCardinalVariantSynth ? 0 : std::max(pcontext->variant != kCardinalVariantMain ? 2 : 8, numIO)), + numOutputs(std::max(pcontext->variant != kCardinalVariantMain ? 2 : 8, numIO)) + { + if (pcontext == nullptr) + throw rack::Exception("Plugin context is null"); + + config(numParams, numIO, numIO, 0); + + if (numParams != 0) + configParam(0, 0.f, 2.f, 1.f, "Level", " dB", -10, 40); + + const float sampleTime = pcontext->engine->getSampleTime(); + for (int i = 0; i < numIO; i++) { + dcFilters[i].setCutoffFreq(10.f * sampleTime); + } + } + + void onReset() override + { + dcFilterEnabled = (numIO == 2); + } + + void onSampleRateChange(const SampleRateChangeEvent& e) override + { + for (int i = 0; i < numIO; i++) + dcFilters[i].setCutoffFreq(10.f * e.sampleTime); + } + + void process(const ProcessArgs&) override + { + const float* const* const dataIns = pcontext->dataIns; + float** const dataOuts = pcontext->dataOuts; + + const int64_t blockFrame = pcontext->engine->getBlockFrame(); + + if (lastBlockFrame != blockFrame) + { + dataFrame = 0; + lastBlockFrame = blockFrame; + } + + const int k = dataFrame++; + DISTRHO_SAFE_ASSERT_RETURN(k < pcontext->engine->getBlockFrames(),); + + const float gain = numParams != 0 ? std::pow(params[0].getValue(), 2.f) : 1.0f; + + // from host into cardinal, shows as output plug + for (int i=0; i +struct HostAudioWidget : ModuleWidget { + static constexpr const float startX_In = 14.0f; + static constexpr const float startX_Out = 96.0f; + static constexpr const float startY = 74.0f; + static constexpr const float padding = 29.0f; + static constexpr const float middleX = startX_In + (startX_Out - startX_In) * 0.5f + padding * 0.25f; + + HostAudio* const module; + + HostAudioWidget(HostAudio* const m) + : module(m) + { + setModule(m); + setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/HostAudio.svg"))); + + addChild(createWidget(Vec(RACK_GRID_WIDTH, 0))); + addChild(createWidget(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0))); + addChild(createWidget(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); + addChild(createWidget(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); + + for (uint i=0; i(Vec(startX_In, startY + padding * i), m, i)); + + for (uint i=0; i(Vec(startX_Out, startY + padding * i), m, i)); + } + + void drawTextLine(NVGcontext* const vg, const uint offset, const char* const text) + { + const float y = startY + offset * padding; + nvgBeginPath(vg); + nvgFillColor(vg, color::WHITE); + nvgText(vg, middleX, y + 16, text, nullptr); + } + + void draw(const DrawArgs& args) override + { + nvgBeginPath(args.vg); + nvgRect(args.vg, 0, 0, box.size.x, box.size.y); + nvgFillPaint(args.vg, nvgLinearGradient(args.vg, 0, 0, 0, box.size.y, + nvgRGB(0x18, 0x19, 0x19), nvgRGB(0x21, 0x22, 0x22))); + nvgFill(args.vg); + + nvgFontFaceId(args.vg, 0); + nvgFontSize(args.vg, 11); + nvgTextAlign(args.vg, NVG_ALIGN_CENTER); + + nvgBeginPath(args.vg); + nvgRoundedRect(args.vg, startX_Out - 4.0f, startY - 2.0f, padding, padding * numIO, 4); + nvgFillColor(args.vg, nvgRGB(0xd0, 0xd0, 0xd0)); + nvgFill(args.vg); + + for (int i=0; i('0'+i+1),'\0'}; + drawTextLine(args.vg, i, text); + } + + ModuleWidget::draw(args); + } + + void appendContextMenu(Menu* const menu) override { + menu->addChild(new MenuSeparator); + menu->addChild(createBoolPtrMenuItem("DC blocker", "", &module->dcFilterEnabled)); + } +}; + +// -------------------------------------------------------------------------------------------------------------------- + +Model* modelHostAudio2 = createModel, HostAudioWidget<2>>("HostAudio2"); +Model* modelHostAudio8 = createModel, HostAudioWidget<8>>("HostAudio8"); + +// -------------------------------------------------------------------------------------------------------------------- diff --git a/plugins/Cardinal/src/HostCV.cpp b/plugins/Cardinal/src/HostCV.cpp index f0e4202..36d7d45 100644 --- a/plugins/Cardinal/src/HostCV.cpp +++ b/plugins/Cardinal/src/HostCV.cpp @@ -1,6 +1,6 @@ /* * DISTRHO Cardinal Plugin - * Copyright (C) 2021 Filipe Coelho + * Copyright (C) 2021-2022 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -24,6 +24,10 @@ USE_NAMESPACE_DISTRHO; struct HostCV : Module { + CardinalPluginContext* const pcontext; + int dataFrame = 0; + int64_t lastBlockFrame = -1; + enum ParamIds { BIPOLAR_INPUTS_1_5, BIPOLAR_INPUTS_6_10, @@ -42,62 +46,54 @@ struct HostCV : Module { }; HostCV() + : pcontext(static_cast(APP)) { + if (pcontext == nullptr) + throw rack::Exception("Plugin context is null"); + config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); configParam(BIPOLAR_INPUTS_1_5, 0.f, 1.f, 0.f, "Bipolar Inputs 1-5")->randomizeEnabled = false; configParam(BIPOLAR_INPUTS_6_10, 0.f, 1.f, 0.f, "Bipolar Inputs 6-10")->randomizeEnabled = false; configParam(BIPOLAR_OUTPUTS_1_5, 0.f, 1.f, 0.f, "Bipolar Outputs 1-5")->randomizeEnabled = false; configParam(BIPOLAR_OUTPUTS_6_10, 0.f, 1.f, 0.f, "Bipolar Outputs 6-10")->randomizeEnabled = false; - - CardinalPluginContext* const pcontext = static_cast(APP); - - if (pcontext == nullptr) - throw rack::Exception("Plugin context is null."); - - if (pcontext->loadedHostCV) - throw rack::Exception("Another instance of a Host CV module is already loaded, only one can be used at a time."); - - pcontext->loadedHostCV = true; } - ~HostCV() override + void process(const ProcessArgs&) override { - CardinalPluginContext* const pcontext = static_cast(APP); - DISTRHO_SAFE_ASSERT_RETURN(pcontext != nullptr,); + if (pcontext->variant != kCardinalVariantMain) + return; - pcontext->loadedHostCV = false; - } + const float* const* const dataIns = pcontext->dataIns; + float** const dataOuts = pcontext->dataOuts; - void process(const ProcessArgs&) override - { - if (CardinalPluginContext* const pcontext = static_cast(APP)) - { - const float** dataIns = pcontext->dataIns; - float** dataOuts = pcontext->dataOuts; + const int64_t blockFrame = pcontext->engine->getBlockFrame(); - if (dataIns == nullptr || dataOuts == nullptr) - return; + if (lastBlockFrame != blockFrame) + { + dataFrame = 0; + lastBlockFrame = blockFrame; + } - const uint32_t dataFrame = pcontext->dataFrame++; - float inputOffset, outputOffset; + const int k = dataFrame++; + DISTRHO_SAFE_ASSERT_RETURN(k < pcontext->engine->getBlockFrames(),); - inputOffset = params[BIPOLAR_INPUTS_1_5].getValue() > 0.1f ? 5.0f : 0.0f; - outputOffset = params[BIPOLAR_OUTPUTS_1_5].getValue() > 0.1f ? 5.0f : 0.0f; + float inputOffset, outputOffset; + inputOffset = params[BIPOLAR_INPUTS_1_5].getValue() > 0.1f ? 5.0f : 0.0f; + outputOffset = params[BIPOLAR_OUTPUTS_1_5].getValue() > 0.1f ? 5.0f : 0.0f; - for (int i=0; i<5; ++i) - { - outputs[i].setVoltage(dataIns[i+CARDINAL_AUDIO_IO_OFFSET][dataFrame] - outputOffset); - dataOuts[i+CARDINAL_AUDIO_IO_OFFSET][dataFrame] = inputs[i].getVoltage() + inputOffset; - } + for (int i=0; i<5; ++i) + { + outputs[i].setVoltage(dataIns[i+CARDINAL_AUDIO_IO_OFFSET][k] - outputOffset); + dataOuts[i+CARDINAL_AUDIO_IO_OFFSET][k] = inputs[i].getVoltage() + inputOffset; + } - inputOffset = params[BIPOLAR_INPUTS_6_10].getValue() > 0.1f ? 5.0f : 0.0f; - outputOffset = params[BIPOLAR_OUTPUTS_6_10].getValue() > 0.1f ? 5.0f : 0.0f; + inputOffset = params[BIPOLAR_INPUTS_6_10].getValue() > 0.1f ? 5.0f : 0.0f; + outputOffset = params[BIPOLAR_OUTPUTS_6_10].getValue() > 0.1f ? 5.0f : 0.0f; - for (int i=5; i<10; ++i) - { - outputs[i].setVoltage(dataIns[i+CARDINAL_AUDIO_IO_OFFSET][dataFrame] - outputOffset); - dataOuts[i+CARDINAL_AUDIO_IO_OFFSET][dataFrame] = inputs[i].getVoltage() + inputOffset; - } + for (int i=5; i<10; ++i) + { + outputs[i].setVoltage(dataIns[i+CARDINAL_AUDIO_IO_OFFSET][k] - outputOffset); + dataOuts[i+CARDINAL_AUDIO_IO_OFFSET][k] = inputs[i].getVoltage() + inputOffset; } } }; diff --git a/plugins/Cardinal/src/HostParameters.cpp b/plugins/Cardinal/src/HostParameters.cpp index 2ad13eb..aaf442b 100644 --- a/plugins/Cardinal/src/HostParameters.cpp +++ b/plugins/Cardinal/src/HostParameters.cpp @@ -1,6 +1,6 @@ /* * DISTRHO Cardinal Plugin - * Copyright (C) 2021 Filipe Coelho + * Copyright (C) 2021-2022 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -36,6 +36,7 @@ struct HostParameters : Module { }; rack::dsp::SlewLimiter parameters[kModuleParameters]; + bool parametersConnected[kModuleParameters] = {}; float sampleTime = 0.0f; HostParameters() @@ -60,7 +61,18 @@ struct HostParameters : Module { if (const CardinalPluginContext* const pcontext = static_cast(APP)) { for (uint32_t i=0; iparameters[i])); + { + const bool connected = outputs[i].isConnected(); + + if (parametersConnected[i] != connected) + { + parametersConnected[i] = connected; + parameters[i].reset(); + } + + if (connected) + outputs[i].setVoltage(parameters[i].process(sampleTime, pcontext->parameters[i])); + } } } diff --git a/plugins/Cardinal/src/plugin.hpp b/plugins/Cardinal/src/plugin.hpp index cdc93a0..436e91a 100644 --- a/plugins/Cardinal/src/plugin.hpp +++ b/plugins/Cardinal/src/plugin.hpp @@ -1,6 +1,6 @@ /* * DISTRHO Cardinal Plugin - * Copyright (C) 2021 Filipe Coelho + * Copyright (C) 2021-2022 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -31,6 +31,8 @@ extern Model* modelAudioFile; extern Model* modelCarla; extern Model* modelCardinalBlank; extern Model* modelGlBars; +extern Model* modelHostAudio2; +extern Model* modelHostAudio8; extern Model* modelHostCV; extern Model* modelHostParameters; extern Model* modelHostTime; diff --git a/plugins/Cardinal/src/plugincontext.hpp b/plugins/Cardinal/src/plugincontext.hpp index 803e721..618e981 100644 --- a/plugins/Cardinal/src/plugincontext.hpp +++ b/plugins/Cardinal/src/plugincontext.hpp @@ -1,6 +1,6 @@ /* * DISTRHO Cardinal Plugin - * Copyright (C) 2021 Filipe Coelho + * Copyright (C) 2021-2022 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -33,6 +33,12 @@ START_NAMESPACE_DISTRHO static constexpr const uint32_t kModuleParameters = 24; +enum CardinalVariant { + kCardinalVariantMain, + kCardinalVariantFX, + kCardinalVariantSynth, +}; + class Plugin; class UI; @@ -40,14 +46,14 @@ struct CardinalPluginContext : rack::Context { uint32_t bufferSize; double sampleRate; float parameters[kModuleParameters]; - bool playing, reset, bbtValid, loadedHostCV; + CardinalVariant variant; + bool playing, reset, bbtValid; int32_t bar, beat, beatsPerBar, beatType; uint64_t frame; double barStartTick, beatsPerMinute; double tick, tickClock, ticksPerBeat, ticksPerClock, ticksPerFrame; uintptr_t nativeWindowId; - uint32_t dataFrame; - const float** dataIns; + const float* const* dataIns; float** dataOuts; Plugin* const plugin; #ifndef HEADLESS diff --git a/plugins/Makefile b/plugins/Makefile index 3b0e745..3a96dc6 100644 --- a/plugins/Makefile +++ b/plugins/Makefile @@ -188,6 +188,7 @@ PLUGIN_FILES = plugins.cpp PLUGIN_FILES += Cardinal/src/Blank.cpp PLUGIN_FILES += Cardinal/src/glBars.cpp +PLUGIN_FILES += Cardinal/src/HostAudio.cpp PLUGIN_FILES += Cardinal/src/HostCV.cpp PLUGIN_FILES += Cardinal/src/HostParameters.cpp PLUGIN_FILES += Cardinal/src/HostTime.cpp diff --git a/plugins/plugins.cpp b/plugins/plugins.cpp index a487e9d..d8f3d10 100644 --- a/plugins/plugins.cpp +++ b/plugins/plugins.cpp @@ -1,6 +1,6 @@ /* * DISTRHO Cardinal Plugin - * Copyright (C) 2021 Filipe Coelho + * Copyright (C) 2021-2022 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -679,6 +679,8 @@ static void initStatic__Cardinal() { p->addModel(modelCardinalBlank); p->addModel(modelGlBars); + p->addModel(modelHostAudio2); + p->addModel(modelHostAudio8); p->addModel(modelHostCV); p->addModel(modelHostParameters); p->addModel(modelHostTime); diff --git a/src/CardinalPlugin.cpp b/src/CardinalPlugin.cpp index b377fbb..bb73bbb 100644 --- a/src/CardinalPlugin.cpp +++ b/src/CardinalPlugin.cpp @@ -1,6 +1,6 @@ /* * DISTRHO Cardinal Plugin - * Copyright (C) 2021 Filipe Coelho + * Copyright (C) 2021-2022 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -182,9 +182,6 @@ struct Initializer "Make sure Cardinal was downloaded and installed correctly.", asset::systemDir.c_str()); } - INFO("Initializing audio driver"); - audio::addDriver(0, new CardinalAudioDriver); - INFO("Initializing midi driver"); midi::addDriver(0, new CardinalMidiDriver); @@ -336,14 +333,11 @@ class CardinalPlugin : public CardinalBasePlugin { SharedResourcePointer fInitializer; - float* fAudioBufferIn; - float* fAudioBufferOut; + float** fAudioBufferCopy; std::string fAutosavePath; String fWindowSize; // for base/context handling - bool fIsActive; - CardinalAudioDevice* fCurrentAudioDevice; CardinalMidiInputDevice** fCurrentMidiInputs; CardinalMidiOutputDevice** fCurrentMidiOutputs; uint64_t fPreviousFrame; @@ -358,10 +352,7 @@ public: CardinalPlugin() : CardinalBasePlugin(kModuleParameters + kWindowParameterCount, 0, kCardinalStateCount), fInitializer(this), - fAudioBufferIn(nullptr), - fAudioBufferOut(nullptr), - fIsActive(false), - fCurrentAudioDevice(nullptr), + fAudioBufferCopy(nullptr), fCurrentMidiInputs(nullptr), fCurrentMidiOutputs(nullptr), fPreviousFrame(0) @@ -443,7 +434,6 @@ public: { const MutexLocker cml(fDeviceMutex); - fCurrentAudioDevice = nullptr; delete[] fCurrentMidiInputs; fCurrentMidiInputs = nullptr; delete[] fCurrentMidiOutputs; @@ -463,36 +453,6 @@ protected: /* -------------------------------------------------------------------------------------------------------- * Cardinal Base things */ - bool isActive() const noexcept override - { - return fIsActive; - } - - bool canAssignAudioDevice() const noexcept override - { - const MutexLocker cml(fDeviceMutex); - return fCurrentAudioDevice == nullptr; - } - - void assignAudioDevice(CardinalAudioDevice* const dev) noexcept override - { - DISTRHO_SAFE_ASSERT_RETURN(fCurrentAudioDevice == nullptr,); - - const MutexLocker cml(fDeviceMutex); - fCurrentAudioDevice = dev; - } - - bool clearAudioDevice(CardinalAudioDevice* const dev) noexcept override - { - const MutexLocker cml(fDeviceMutex); - - if (fCurrentAudioDevice != dev) - return false; - - fCurrentAudioDevice = nullptr; - return true; - } - void assignMidiInputDevice(CardinalMidiInputDevice* const dev) noexcept override { CardinalMidiInputDevice** const oldDevs = fCurrentMidiInputs; @@ -625,13 +585,15 @@ protected: int64_t getUniqueId() const override { -#if CARDINAL_VARIANT_SYNTH - return d_cconst('d', 'C', 'n', 'S'); -#elif CARDINAL_VARIANT_FX - return d_cconst('d', 'C', 'n', 'F'); -#else + #if CARDINAL_VARIANT_MAIN return d_cconst('d', 'C', 'd', 'n'); -#endif + #elif CARDINAL_VARIANT_FX + return d_cconst('d', 'C', 'n', 'F'); + #elif CARDINAL_VARIANT_SYNTH + return d_cconst('d', 'C', 'n', 'S'); + #else + #error cardinal variant not set + #endif } /* -------------------------------------------------------------------------------------------------------- @@ -892,42 +854,25 @@ protected: void activate() override { + #if DISTRHO_PLUGIN_NUM_INPUTS != 0 const uint32_t bufferSize = getBufferSize(); - fAudioBufferOut = new float[bufferSize * DISTRHO_PLUGIN_NUM_OUTPUTS]; - - const uint32_t numInputs = std::max(1, DISTRHO_PLUGIN_NUM_INPUTS); - fAudioBufferIn = new float[bufferSize * numInputs]; - std::memset(fAudioBufferIn, 0, sizeof(float)*bufferSize * numInputs); + fAudioBufferCopy = new float*[DISTRHO_PLUGIN_NUM_INPUTS]; + for (int i=0; ionStartStream(); - } - } } void deactivate() override { + if (fAudioBufferCopy != nullptr) { - const MutexLocker cml(fDeviceMutex); - - if (fCurrentAudioDevice != nullptr) - { - rack::contextSet(context); - fCurrentAudioDevice->onStopStream(); - } + for (int i=0; ihandleMessagesFromHost(midiEvents, midiEventCount); } - if (fCurrentAudioDevice != nullptr) + // separate buffers, use them + if (inputs != outputs && (inputs == nullptr || inputs[0] != outputs[0])) { -#if CARDINAL_NUM_AUDIO_INPUTS != 0 - for (uint32_t i=0, j=0; iprocessInput(fAudioBufferIn, CARDINAL_NUM_AUDIO_INPUTS, frames); -#else - std::memset(fAudioBufferIn, 0, sizeof(float)*frames); - fCurrentAudioDevice->processInput(fAudioBufferIn, 1, frames); -#endif - } - -#if CARDINAL_VARIANT_MAIN - context->dataFrame = 0; - context->dataIns = inputs; - context->dataOuts = outputs; -#endif - - context->engine->stepBlock(frames); - - if (fCurrentAudioDevice != nullptr) - { - std::memset(fAudioBufferOut, 0, sizeof(float)*frames*CARDINAL_NUM_AUDIO_OUTPUTS); - fCurrentAudioDevice->processOutput(fAudioBufferOut, CARDINAL_NUM_AUDIO_OUTPUTS, frames); - - for (uint32_t i=0, j=0; idataIns = inputs; + context->dataOuts = outputs; } + // inline processing, use a safe copy else { - for (uint32_t k=0; kdataIns = fAudioBufferCopy; + context->dataOuts = outputs; } + + for (int i=0; iengine->stepBlock(frames); } void bufferSizeChanged(const uint32_t newBufferSize) override diff --git a/src/PluginContext.hpp b/src/PluginContext.hpp index 96c0051..4d261a6 100644 --- a/src/PluginContext.hpp +++ b/src/PluginContext.hpp @@ -1,6 +1,6 @@ /* * DISTRHO Cardinal Plugin - * Copyright (C) 2021 Filipe Coelho + * Copyright (C) 2021-2022 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -39,20 +39,26 @@ START_NAMESPACE_DISTRHO static constexpr const uint kModuleParameters = 24; +enum CardinalVariant { + kCardinalVariantMain, + kCardinalVariantFX, + kCardinalVariantSynth, +}; + // ----------------------------------------------------------------------------------------------------------- struct CardinalPluginContext : rack::Context { uint32_t bufferSize; double sampleRate; float parameters[kModuleParameters]; - bool playing, reset, bbtValid, loadedHostCV; + CardinalVariant variant; + bool playing, reset, bbtValid; int32_t bar, beat, beatsPerBar, beatType; uint64_t frame; double barStartTick, beatsPerMinute; double tick, tickClock, ticksPerBeat, ticksPerClock, ticksPerFrame; uintptr_t nativeWindowId; - uint32_t dataFrame; - const float** dataIns; + const float* const* dataIns; float** dataOuts; Plugin* const plugin; #ifndef HEADLESS @@ -62,10 +68,18 @@ struct CardinalPluginContext : rack::Context { CardinalPluginContext(Plugin* const p) : bufferSize(p->getBufferSize()), sampleRate(p->getSampleRate()), + #if CARDINAL_VARIANT_MAIN + variant(kCardinalVariantMain), + #elif CARDINAL_VARIANT_FX + variant(kCardinalVariantFX), + #elif CARDINAL_VARIANT_SYNTH + variant(kCardinalVariantSynth), + #else + #error cardinal variant not set + #endif playing(false), reset(false), bbtValid(false), - loadedHostCV(false), bar(1), beat(1), beatsPerBar(4), @@ -79,7 +93,6 @@ struct CardinalPluginContext : rack::Context { ticksPerClock(0.0), ticksPerFrame(0.0), nativeWindowId(0), - dataFrame(0), dataIns(nullptr), dataOuts(nullptr), plugin(p) @@ -116,10 +129,6 @@ public: : Plugin(parameterCount, programCount, stateCount), context(new CardinalPluginContext(this)) {} ~CardinalBasePlugin() override {} - virtual bool isActive() const noexcept = 0; - virtual bool canAssignAudioDevice() const noexcept = 0; - virtual bool clearAudioDevice(CardinalAudioDevice* dev) noexcept = 0; - virtual void assignAudioDevice(CardinalAudioDevice* dev) noexcept = 0; virtual void assignMidiInputDevice(CardinalMidiInputDevice* dev) noexcept = 0; virtual void assignMidiOutputDevice(CardinalMidiOutputDevice* dev) noexcept = 0; virtual void clearMidiInputDevice(CardinalMidiInputDevice* dev) noexcept = 0; diff --git a/src/PluginDriver.hpp b/src/PluginDriver.hpp index c0a234d..d9d21dc 100644 --- a/src/PluginDriver.hpp +++ b/src/PluginDriver.hpp @@ -1,6 +1,6 @@ /* * DISTRHO Cardinal Plugin - * Copyright (C) 2021 Filipe Coelho + * Copyright (C) 2021-2022 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -23,145 +23,6 @@ START_NAMESPACE_DISTRHO // ----------------------------------------------------------------------------------------------------------- -struct CardinalAudioDevice : rack::audio::Device -{ - CardinalBasePlugin* const fPlugin; - - CardinalAudioDevice(CardinalBasePlugin* const plugin) - : fPlugin(plugin) {} - - std::string getName() override - { - return "Cardinal"; - } - - int getNumInputs() override - { - return CARDINAL_NUM_AUDIO_INPUTS; - } - - int getNumOutputs() override - { - return CARDINAL_NUM_AUDIO_OUTPUTS; - } - - int getBlockSize() override - { - return fPlugin->getBufferSize(); - } - - float getSampleRate() override - { - return fPlugin->getSampleRate(); - } - - std::set getBlockSizes() override - { - return std::set({ getBlockSize() }); - } - - std::set getSampleRates() override - { - return std::set({ getSampleRate() }); - } - - void setBlockSize(int) override {} - void setSampleRate(float) override {} - - void processInput(const float* const input, const int inputStride, const int frames) - { - for (rack::audio::Port* port : subscribed) - port->processInput(input + port->inputOffset, inputStride, frames); - } - - void processOutput(float* const output, const int outputStride, const int frames) - { - for (rack::audio::Port* port : subscribed) - port->processOutput(output + port->outputOffset, outputStride, frames); - } -}; - -// ----------------------------------------------------------------------------------------------------------- - -struct CardinalAudioDriver : rack::audio::Driver -{ - CardinalAudioDriver() {} - - std::string getName() override - { - return "Plugin Driver"; - } - - std::vector getDeviceIds() override - { - return std::vector({ 0 }); - } - - int getDefaultDeviceId() override - { - return 0; - } - - std::string getDeviceName(int) override - { - return "Plugin Device"; - } - - int getDeviceNumInputs(int) override - { - return CARDINAL_NUM_AUDIO_INPUTS; - } - - int getDeviceNumOutputs(int) override - { - return CARDINAL_NUM_AUDIO_OUTPUTS; - } - - rack::audio::Device* subscribe(int, rack::audio::Port* const port) override - { - CardinalPluginContext* const pluginContext = reinterpret_cast(port->context); - DISTRHO_SAFE_ASSERT_RETURN(pluginContext != nullptr, nullptr); - - CardinalBasePlugin* const plugin = reinterpret_cast(pluginContext->plugin); - DISTRHO_SAFE_ASSERT_RETURN(plugin != nullptr, nullptr); - - if (! plugin->canAssignAudioDevice()) - throw rack::Exception("Plugin driver only allows one audio device to be used simultaneously"); - - CardinalAudioDevice* const device = new CardinalAudioDevice(plugin); - device->subscribe(port); - - if (plugin->isActive()) - device->onStartStream(); - - plugin->assignAudioDevice(device); - return device; - } - - void unsubscribe(int, rack::audio::Port* const port) override - { - CardinalAudioDevice* const device = reinterpret_cast(port->device); - DISTRHO_SAFE_ASSERT_RETURN(device != nullptr,); - - CardinalPluginContext* const pluginContext = reinterpret_cast(port->context); - DISTRHO_SAFE_ASSERT_RETURN(pluginContext != nullptr,); - - CardinalBasePlugin* const plugin = reinterpret_cast(pluginContext->plugin); - DISTRHO_SAFE_ASSERT_RETURN(plugin != nullptr,); - - if (plugin->clearAudioDevice(device)) - { - if (plugin->isActive()) - device->onStopStream(); - - device->unsubscribe(port); - delete device; - } - } -}; - -// ----------------------------------------------------------------------------------------------------------- - struct CardinalMidiInputDevice : rack::midi::InputDevice { CardinalBasePlugin* const fPlugin; diff --git a/src/template.vcv b/src/template.vcv index b6f65d5..e19bcdc 100644 --- a/src/template.vcv +++ b/src/template.vcv @@ -4,8 +4,8 @@ "modules": [ { "id": 1, - "plugin": "Core", - "model": "AudioInterface2", + "plugin": "Cardinal", + "model": "HostAudio2", "version": "2.0", "params": [ { @@ -15,14 +15,6 @@ ], "rightModuleId": 2, "data": { - "audio": { - "driver": 0, - "deviceName": "Cardinal", - "sampleRate": 48000.0, - "blockSize": 512, - "inputOffset": 0, - "outputOffset": 0 - }, "dcFilter": true }, "pos": [