From 94c33b3a812890fe80e7f11b1e5d8f538262f434 Mon Sep 17 00:00:00 2001 From: Paul Dempsey Date: Thu, 8 Feb 2024 11:56:32 -0800 Subject: [PATCH] TiltEQ module --- Makefile | 4 + plugin.json | 8 +- res/Tilt.svg | 624 +++++++++++++++++++++++++++++++++++++++++++ src/HC-2/HC-2-ui.cpp | 34 --- src/HC-2/HC-2.cpp | 101 +------ src/HC-2/HC-2.hpp | 32 +-- src/Tilt/Tilt-ui.cpp | 87 ++++++ src/Tilt/Tilt.cpp | 218 +++++++++++++++ src/Tilt/Tilt.hpp | 125 +++++++++ src/plugin.cpp | 1 + src/plugin.hpp | 1 + 11 files changed, 1071 insertions(+), 164 deletions(-) create mode 100644 res/Tilt.svg create mode 100644 src/Tilt/Tilt-ui.cpp create mode 100644 src/Tilt/Tilt.cpp create mode 100644 src/Tilt/Tilt.hpp diff --git a/Makefile b/Makefile index 169cc89..77f87d8 100644 --- a/Makefile +++ b/Makefile @@ -59,6 +59,10 @@ SOURCES += src/Round/Round-ui.cpp SOURCES += src/Compress/Compress.cpp SOURCES += src/Compress/Compress-ui.cpp +SOURCES += src/Tilt/Tilt.cpp +SOURCES += src/Tilt/Tilt-ui.cpp + + DISTRIBUTABLES += res # DISTRIBUTABLES += presets # DISTRIBUTABLES += selections diff --git a/plugin.json b/plugin.json index 0610cca..5b52434 100644 --- a/plugin.json +++ b/plugin.json @@ -1,7 +1,7 @@ { "slug": "pachde-hc-one", "name": "HC One", - "version": "2.0.0-beta6", + "version": "2.0.0-beta7", "license": "GPL-3.0-or-later", "brand": "pachde", "author": "pachde", @@ -54,6 +54,12 @@ "name": "Compressor", "description": "Controller for EaganMatrix Compressor (HC-1 companion)", "tags": [ "Controller", "Expander" ] + }, + { + "slug": "pachde-hc-tilt-eq", + "name": "TiltEQ", + "description": "Controller for EaganMatrix Tilt EQ (HC-1 companion)", + "tags": [ "Controller", "Expander" ] } ] } diff --git a/res/Tilt.svg b/res/Tilt.svg new file mode 100644 index 0000000..75891ad --- /dev/null +++ b/res/Tilt.svg @@ -0,0 +1,624 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/HC-2/HC-2-ui.cpp b/src/HC-2/HC-2-ui.cpp index 9c9926f..61cba0c 100644 --- a/src/HC-2/HC-2-ui.cpp +++ b/src/HC-2/HC-2-ui.cpp @@ -27,38 +27,6 @@ inline uint8_t GetSmallParamValue(rack::app::ModuleWidget* w, int id, uint8_t de return U8(pq->getValue()); } -void Hc2ModuleWidget::createTiltEqUI(float x, float y) -{ - addChild(createHeaderWidget(x, y, TEQ_BOX_WIDTH, KNOB_BOX_HEIGHT)); - addChild(createStaticTextLabel(Vec(x + TEQ_BOX_WIDTH*.5f, y + PAD), 60.f, "Tilt EQ", TextAlignment::Center)); - addChild(createLightCentered>(Vec(x + KNOB_COL1 + 2.f * KNOB_SPREAD, y + 8.f), my_module, Hc2L::L_TEQ)); - - float cx = x + KNOB_COL1; - addChild(createStaticTextLabel(Vec(cx, y + KNOB_ROW - STATIC_LABEL_OFFSET), 50.f, "Tilt", TextAlignment::Center)); - addChild(createModKnob( - Vec( cx, y + KNOB_ROW), - module, Hc2P::P_TEQ_TILT, Hc2I::IN_TEQ_TILT, Hc2P::P_TEQ_TILT_REL)); - addParam(createLightParamCentered>>(Vec(cx - REL_OFFSET, y + KNOB_ROW - REL_VOFFSET), my_module, Hc2P::P_TEQ_TILT_REL, Hc2L::L_TEQ_TILT_REL)); - addChild(createInputCentered(Vec(cx - CV_COLUMN_OFFSET, y + KNOB_ROW + CV_ROW_OFFSET), my_module, Hc2I::IN_TEQ_TILT)); - - cx += KNOB_SPREAD; - addChild(createStaticTextLabel(Vec(cx, y + KNOB_ROW - STATIC_LABEL_OFFSET), 55.f, "Frequency", TextAlignment::Center)); - addChild(createModKnob( - Vec( cx, y + KNOB_ROW), - module, Hc2P::P_TEQ_FREQ, Hc2I::IN_TEQ_FREQ, Hc2P::P_TEQ_FREQ_REL)); - addParam(createLightParamCentered>>(Vec(cx - REL_OFFSET, y + KNOB_ROW - REL_VOFFSET), my_module, Hc2P::P_TEQ_FREQ_REL, Hc2L::L_TEQ_FREQ_REL)); - addChild(createInputCentered(Vec(cx - CV_COLUMN_OFFSET, y + KNOB_ROW + CV_ROW_OFFSET), my_module, Hc2I::IN_TEQ_FREQ)); - - cx += KNOB_SPREAD; - addChild(createStaticTextLabel(Vec(cx, y + KNOB_ROW - STATIC_LABEL_OFFSET), 30.f, "Mix", TextAlignment::Center)); - addChild(createModKnob( - Vec( cx, y + KNOB_ROW), - module, Hc2P::P_TEQ_MIX, Hc2I::IN_TEQ_MIX, Hc2P::P_TEQ_MIX_REL)); - addParam(createLightParamCentered>>(Vec(cx - REL_OFFSET, y + KNOB_ROW - REL_VOFFSET), my_module, Hc2P::P_TEQ_MIX_REL, Hc2L::L_TEQ_MIX_REL)); - addChild(createInputCentered(Vec(cx - CV_COLUMN_OFFSET, y + KNOB_ROW + CV_ROW_OFFSET), my_module, Hc2I::IN_TEQ_MIX)); - -} - Hc2ModuleWidget::Hc2ModuleWidget(Hc2Module * module) { my_module = module; @@ -69,8 +37,6 @@ Hc2ModuleWidget::Hc2ModuleWidget(Hc2Module * module) setPanel(createPanel(asset::plugin(pluginInstance, "res/HC-2.svg"))); addChild(partner_picker = createPartnerPicker()); - createTiltEqUI(TEQ_BOX_LEFT, TEQ_BOX_TOP); - auto x = box.size.x * .5f; addChild(createCCMap(x, box.size.y - 24.f - 20.f, true, CCMapChannel::One, this)); addChild(createCCMap(x, box.size.y - 24.f, true, CCMapChannel::Sixteen, this)); diff --git a/src/HC-2/HC-2.cpp b/src/HC-2/HC-2.cpp index 189bddf..87ff1f7 100644 --- a/src/HC-2/HC-2.cpp +++ b/src/HC-2/HC-2.cpp @@ -11,23 +11,10 @@ namespace pachde { Hc2Module::Hc2Module() { - std::vector offon = {"off", "on"}; + //std::vector offon = {"off", "on"}; config(Params::NUM_PARAMS, Inputs::NUM_INPUTS, Outputs::NUM_OUTPUTS, Lights::NUM_LIGHTS); - configCCParam(EMCC_TiltEq, false, this, P_TEQ_TILT, IN_TEQ_TILT, P_TEQ_TILT_REL, L_TEQ_TILT_REL, 0.f, 127.f, 64.f, "Tilt", "", 0.f, 1.f)->snapEnabled = true; - configCCParam(EMCC_TiltEqFrequency, false, this, P_TEQ_FREQ, IN_TEQ_FREQ, P_TEQ_FREQ_REL, L_TEQ_FREQ_REL, 0.f, 127.f, 64.f, "Frequency", "%", 0.f, 100.f/127.f)->snapEnabled = true; - configCCParam(EMCC_TiltEqMix, false, this, P_TEQ_MIX, IN_TEQ_MIX, P_TEQ_MIX_REL, L_TEQ_MIX_REL, 0.f, 127.f, 0.f, "Mix", "%", 0.f, 100.f/127.f)->snapEnabled = true; - - configInput(IN_TEQ_TILT, "Tilt EQ tilt"); - configInput(IN_TEQ_FREQ, "Tilt EQ frequency"); - configInput(IN_TEQ_MIX, "Tilt EQ mix"); - - configSwitch(P_TEQ_TILT_REL, 0.f, 1.f, 0.f, "Tilt relative CV", offon); - configSwitch(P_TEQ_FREQ_REL, 0.f, 1.f, 0.f, "Frequency relative CV", offon); - configSwitch(P_TEQ_MIX_REL, 0.f, 1.f, 0.f, "Mix relative CV", offon); - - configLight(L_TEQ, "Tilt EQ"); partner_binding.setClient(this); } @@ -57,32 +44,6 @@ Hc1Module* Hc2Module::getPartner() return partner_binding.getPartner(); } -void Hc2Module::onTiltEqChanged(const TiltEqChangedEvent& e) -{ - bool changed = false; - auto old = tilt_eq; - tilt_eq = e.tilt_eq; - - if (old.tilt != tilt_eq.tilt) { - changed = true; - auto pq = dynamic_cast(getParamQuantity(Params::P_TEQ_TILT)); - pq->setValueSilent(tilt_eq.tilt); - } - if (old.frequency != tilt_eq.frequency) { - changed = true; - auto pq = dynamic_cast(getParamQuantity(Params::P_TEQ_FREQ)); - pq->setValueSilent(tilt_eq.frequency); - } - if (old.mix != tilt_eq.mix) { - changed = true; - auto pq = dynamic_cast(getParamQuantity(Params::P_TEQ_MIX)); - pq->setValueSilent(tilt_eq.mix); - } - if (changed && ui_event_sink) { - ui_event_sink->onTiltEqChanged(e); - } -} - void Hc2Module::onDeviceChanged(const DeviceChangedEvent& e) { partner_binding.onDeviceChanged(e); @@ -99,29 +60,6 @@ void Hc2Module::onDisconnect(const DisconnectEvent& e) } } -void Hc2Module::pullTiltEq(Hc1Module *partner) -{ - if (!partner) partner = getPartner(); - if (!partner) return; - tilt_eq = partner->em.tilt_eq; - getParamQuantity(Params::P_TEQ_TILT)->setValue(tilt_eq.tilt); - getParamQuantity(Params::P_TEQ_FREQ)->setValue(tilt_eq.frequency); - getParamQuantity(Params::P_TEQ_MIX)->setValue(tilt_eq.mix); - if (ui_event_sink) { - ui_event_sink->onTiltEqChanged(TiltEqChangedEvent{tilt_eq}); - } -} - -void Hc2Module::pushTiltEq(Hc1Module *partner) -{ - if (!partner) partner = getPartner(); - if (!partner) return; - partner->em.tilt_eq = tilt_eq; - if (ui_event_sink) { - ui_event_sink->onTiltEqChanged(TiltEqChangedEvent{tilt_eq}); - } -} - void Hc2Module::processCV(int paramId) { auto pq = dynamic_cast(getParamQuantity(paramId)); @@ -148,52 +86,19 @@ void Hc2Module::processCV(int paramId) } } -void Hc2Module::processTiltEqControls() -{ - bool changed = false; - - auto pq = dynamic_cast(getParamQuantity(Params::P_TEQ_TILT)); - auto v = pq->valueToSend(); - if (pq->last_value != v) { - tilt_eq.tilt = v; - changed = true; - pq->syncValue(); - } - pq = dynamic_cast(getParamQuantity(Params::P_TEQ_FREQ)); - v = pq->valueToSend(); - if (pq->last_value != v) { - tilt_eq.frequency = v; - changed = true; - pq->syncValue(); - } - pq = dynamic_cast(getParamQuantity(Params::P_TEQ_MIX)); - v = pq->valueToSend(); - if (pq->last_value != v) { - tilt_eq.mix = v; - changed = true; - pq->syncValue(); - } - if (changed) { - pushTiltEq(); - } -} - void Hc2Module::processControls() { if (!control_rate.process()) { return; } - processTiltEqControls(); } void Hc2Module::process(const ProcessArgs& args) { if ((0 == ((args.frame + id) % CV_INTERVAL))) { - processCV(Params::P_TEQ_TILT); - processCV(Params::P_TEQ_FREQ); - processCV(Params::P_TEQ_MIX); + // processCV(Params::P_whatever); } processControls(); - getLight(Lights::L_TEQ).setBrightness(static_cast(tilt_eq.mix)/127.f); + //getLight(Lights::L_whatever).setBrightness(static_cast(some_value)/127.f); } // ISendMidi diff --git a/src/HC-2/HC-2.hpp b/src/HC-2/HC-2.hpp index d568aa0..2264bca 100644 --- a/src/HC-2/HC-2.hpp +++ b/src/HC-2/HC-2.hpp @@ -27,21 +27,10 @@ struct Hc2Module : Module, ISendMidi, IHandleHcEvents { enum Params { - P_TEQ_TILT, - P_TEQ_FREQ, - P_TEQ_MIX, - P_TEQ_TILT_REL, - P_TEQ_FREQ_REL, - P_TEQ_MIX_REL, - NUM_PARAMS, }; enum Inputs { - IN_TEQ_TILT, - IN_TEQ_FREQ, - IN_TEQ_MIX, - NUM_INPUTS }; enum Outputs @@ -50,18 +39,9 @@ struct Hc2Module : Module, ISendMidi, IHandleHcEvents }; enum Lights { - L_TEQ_TILT_REL, - L_TEQ_FREQ_REL, - L_TEQ_MIX_REL, - - L_TEQ, - NUM_LIGHTS }; - Compressor compressor; - TiltEq tilt_eq; - IHandleHcEvents * ui_event_sink = nullptr; PartnerBinding partner_binding; Hc1Module* getPartner(); @@ -69,20 +49,11 @@ struct Hc2Module : Module, ISendMidi, IHandleHcEvents // cv processing const int CV_INTERVAL = 64; RateTrigger control_rate; - rack::dsp::SchmittTrigger round_initial_trigger; explicit Hc2Module(); virtual ~Hc2Module(); - void pullCompressor(Hc1Module * partner = nullptr); - void pushCompressor(Hc1Module * partner = nullptr); - void pullTiltEq(Hc1Module * partner = nullptr); - void pushTiltEq(Hc1Module * partner = nullptr); - void processCV(int paramId); - void processRoundingControls(); - void processCompressorControls(); - void processTiltEqControls(); void processControls(); // Module @@ -108,7 +79,7 @@ struct Hc2Module : Module, ISendMidi, IHandleHcEvents //void onPedalChanged(const PedalChangedEvent& e) override; //void onRoundingChanged(const RoundingChangedEvent& e) override; //void onCompressorChanged(const CompressorChangedEvent& e) override; - void onTiltEqChanged(const TiltEqChangedEvent& e) override; + //void onTiltEqChanged(const TiltEqChangedEvent& e) override; void onDeviceChanged(const DeviceChangedEvent& e) override; void onDisconnect(const DisconnectEvent& e) override; }; @@ -125,7 +96,6 @@ struct Hc2ModuleWidget : ModuleWidget, IHandleHcEvents // } } Hc1Module* getPartner(); - void createTiltEqUI(float x, float y); // IHandleHcEvents //void onPresetChanged(const PresetChangedEvent& e) override; diff --git a/src/Tilt/Tilt-ui.cpp b/src/Tilt/Tilt-ui.cpp new file mode 100644 index 0000000..c351b96 --- /dev/null +++ b/src/Tilt/Tilt-ui.cpp @@ -0,0 +1,87 @@ +#include "Tilt.hpp" +#include "../colors.hpp" +#include "../misc.hpp" +#include "../text.hpp" +#include "../widgets/cc_param.hpp" +#include "../widgets/components.hpp" +#include "../widgets/port.hpp" +#include "../widgets/small_push.hpp" +#include "../widgets/switch_4.hpp" + +namespace pachde { + +using TP = TiltModule::Params; +using TI = TiltModule::Inputs; +using TO = TiltModule::Outputs; +using TL = TiltModule::Lights; + +constexpr const float KNOB_SPREAD = 80.f; +constexpr const float CENTER = 22.5f; +constexpr const float PAD = 1.f; +constexpr const float MORE_PAD = 4.f; +constexpr const float REL_OFFSET = 20.f; +constexpr const float REL_VOFFSET = 10.f; +constexpr const float CV_COLUMN_OFFSET = 24.f; +constexpr const float CV_ROW_OFFSET = 6.f; +constexpr const float STATIC_LABEL_OFFSET = 29.5f; + +TiltModuleWidget::TiltModuleWidget(TiltModule * module) +: my_module(module) +{ + setModule(module); + if (module) { + my_module->ui_event_sink = this; + } + setPanel(createPanel(asset::plugin(pluginInstance, "res/Tilt.svg"))); + addChild(partner_picker = createPartnerPicker()); + + addChild(createLightCentered>(Vec(CENTER, 40.f), my_module, TL::L_TEQ)); + + float x_rel = CENTER - VK_REL_VOFFSET; + float y = 88.f; + + addChild(createModKnob( + Vec(CENTER, y), + module, TP::P_TEQ_TILT, TI::IN_TEQ_TILT, TP::P_TEQ_TILT_REL)); + addParam(createLightParamCentered>>(Vec(x_rel, y + VK_REL_VOFFSET), my_module, TP::P_TEQ_TILT_REL, TL::L_TEQ_TILT_REL)); + addChild(createInputCentered(Vec(CENTER, y + VK_CV_VOFFSET), my_module, TI::IN_TEQ_TILT)); + + y += KNOB_SPREAD; + addChild(createModKnob( + Vec(CENTER, y), + module, TP::P_TEQ_FREQ, TI::IN_TEQ_FREQ, TP::P_TEQ_FREQ_REL)); + addParam(createLightParamCentered>>(Vec(x_rel, y + VK_REL_VOFFSET), my_module, TP::P_TEQ_FREQ_REL, TL::L_TEQ_FREQ_REL)); + addChild(createInputCentered(Vec(CENTER, y + VK_CV_VOFFSET), my_module, TI::IN_TEQ_FREQ)); + + y += KNOB_SPREAD; + addChild(createModKnob( + Vec(CENTER, y), + module, TP::P_TEQ_MIX, TI::IN_TEQ_MIX, TP::P_TEQ_MIX_REL)); + addParam(createLightParamCentered>>(Vec(x_rel, y + VK_REL_VOFFSET), my_module, TP::P_TEQ_MIX_REL, TL::L_TEQ_MIX_REL)); + addChild(createInputCentered(Vec(CENTER, y + VK_CV_VOFFSET), my_module, TI::IN_TEQ_MIX)); + +} + +Hc1Module* TiltModuleWidget::getPartner() +{ + return module ? my_module->getPartner() : nullptr; +} + +void TiltModuleWidget::onDeviceChanged(const DeviceChangedEvent& e) +{ + partner_picker->onDeviceChanged(e); +} + +void TiltModuleWidget::onDisconnect(const DisconnectEvent& e) +{ + partner_picker->onDisconnect(e); +} + +void TiltModuleWidget::appendContextMenu(Menu *menu) +{ + if (!my_module) return; + menu->addChild(new MenuSeparator); + my_module->partner_binding.appendContextMenu(menu); +} + +} \ No newline at end of file diff --git a/src/Tilt/Tilt.cpp b/src/Tilt/Tilt.cpp new file mode 100644 index 0000000..fe3c6b6 --- /dev/null +++ b/src/Tilt/Tilt.cpp @@ -0,0 +1,218 @@ +#include "Tilt.hpp" +#include "../colors.hpp" +#include "../misc.hpp" +#include "../module_broker.hpp" +#include "../text.hpp" +#include "../widgets/cc_param.hpp" +#include "../widgets/components.hpp" +#include "../widgets/pedal_param.hpp" + +namespace pachde { + +TiltModule::TiltModule() +{ + std::vector offon = {"off", "on"}; + config(Params::NUM_PARAMS, Inputs::NUM_INPUTS, Outputs::NUM_OUTPUTS, Lights::NUM_LIGHTS); + + configCCParam(EMCC_TiltEq, false, this, P_TEQ_TILT, IN_TEQ_TILT, P_TEQ_TILT_REL, L_TEQ_TILT_REL, 0.f, 127.f, 64.f, "Tilt", "", 0.f, 1.f)->snapEnabled = true; + configCCParam(EMCC_TiltEqFrequency, false, this, P_TEQ_FREQ, IN_TEQ_FREQ, P_TEQ_FREQ_REL, L_TEQ_FREQ_REL, 0.f, 127.f, 64.f, "Frequency", "%", 0.f, 100.f/127.f)->snapEnabled = true; + configCCParam(EMCC_TiltEqMix, false, this, P_TEQ_MIX, IN_TEQ_MIX, P_TEQ_MIX_REL, L_TEQ_MIX_REL, 0.f, 127.f, 0.f, "Mix", "%", 0.f, 100.f/127.f)->snapEnabled = true; + + configInput(IN_TEQ_TILT, "Tilt EQ Tilt"); + configInput(IN_TEQ_FREQ, "Tilt EQ Frequency"); + configInput(IN_TEQ_MIX, "Tilt EQ Mix"); + + configSwitch(P_TEQ_TILT_REL, 0.f, 1.f, 0.f, "Tilt relative CV", offon); + configSwitch(P_TEQ_FREQ_REL, 0.f, 1.f, 0.f, "Frequency relative CV", offon); + configSwitch(P_TEQ_MIX_REL, 0.f, 1.f, 0.f, "Mix relative CV", offon); + + configLight(L_TEQ, "Tilt EQ"); + partner_binding.setClient(this); +} + +TiltModule::~TiltModule() +{ + partner_binding.unsubscribe(); +} + +json_t * TiltModule::dataToJson() +{ + auto root = json_object(); + json_object_set_new(root, "device", json_string(partner_binding.claim.c_str())); + return root; +} + +void TiltModule::dataFromJson(json_t *root) +{ + auto j = json_object_get(root, "device"); + if (j) { + partner_binding.setClaim(json_string_value(j)); + } + getPartner(); +} + +Hc1Module* TiltModule::getPartner() +{ + return partner_binding.getPartner(); +} + +// ISendMidi +void TiltModule::sendControlChange(uint8_t channel, uint8_t cc, uint8_t value) +{ + auto partner = getPartner(); + if (partner) { + partner->sendControlChange(channel, cc, value); + } +} +//void sendProgramChange(uint8_t channel, uint8_t program) {} +//void sendKeyPressure(uint8_t channel, uint8_t note, uint8_t pressure) {} +//void sendChannelPressure(uint8_t channel, uint8_t pressure) {} +//void sendPitchBend(uint8_t channel, uint8_t bend_lo, uint8_t bend_hi) {} +bool TiltModule::readyToSend() +{ + auto partner = getPartner(); + return partner && partner->ready(); +} + +void TiltModule::onTiltEqChanged(const TiltEqChangedEvent& e) +{ + bool changed = false; + auto old = tilt_eq; + tilt_eq = e.tilt_eq; + + if (old.tilt != tilt_eq.tilt) { + changed = true; + auto pq = dynamic_cast(getParamQuantity(Params::P_TEQ_TILT)); + pq->setValueSilent(tilt_eq.tilt); + } + if (old.frequency != tilt_eq.frequency) { + changed = true; + auto pq = dynamic_cast(getParamQuantity(Params::P_TEQ_FREQ)); + pq->setValueSilent(tilt_eq.frequency); + } + if (old.mix != tilt_eq.mix) { + changed = true; + auto pq = dynamic_cast(getParamQuantity(Params::P_TEQ_MIX)); + pq->setValueSilent(tilt_eq.mix); + } + if (changed && ui_event_sink) { + ui_event_sink->onTiltEqChanged(e); + } +} + +void TiltModule::onDeviceChanged(const DeviceChangedEvent& e) +{ + partner_binding.onDeviceChanged(e); + if (ui_event_sink) { + ui_event_sink->onDeviceChanged(e); + } +} + +void TiltModule::onDisconnect(const DisconnectEvent& e) +{ + partner_binding.onDisconnect(e); + if (ui_event_sink) { + ui_event_sink->onDisconnect(e); + } +} + +void TiltModule::pullTiltEq(Hc1Module *partner) +{ + if (!partner) partner = getPartner(); + if (!partner) return; + tilt_eq = partner->em.tilt_eq; + getParamQuantity(Params::P_TEQ_TILT)->setValue(tilt_eq.tilt); + getParamQuantity(Params::P_TEQ_FREQ)->setValue(tilt_eq.frequency); + getParamQuantity(Params::P_TEQ_MIX)->setValue(tilt_eq.mix); + if (ui_event_sink) { + ui_event_sink->onTiltEqChanged(TiltEqChangedEvent{tilt_eq}); + } +} + +void TiltModule::pushTiltEq(Hc1Module *partner) +{ + if (!partner) partner = getPartner(); + if (!partner) return; + partner->em.tilt_eq = tilt_eq; + if (ui_event_sink) { + ui_event_sink->onTiltEqChanged(TiltEqChangedEvent{tilt_eq}); + } +} + +void TiltModule::processTiltEqControls() +{ + bool changed = false; + + auto pq = dynamic_cast(getParamQuantity(Params::P_TEQ_TILT)); + auto v = pq->valueToSend(); + if (pq->last_value != v) { + tilt_eq.tilt = v; + changed = true; + pq->syncValue(); + } + pq = dynamic_cast(getParamQuantity(Params::P_TEQ_FREQ)); + v = pq->valueToSend(); + if (pq->last_value != v) { + tilt_eq.frequency = v; + changed = true; + pq->syncValue(); + } + pq = dynamic_cast(getParamQuantity(Params::P_TEQ_MIX)); + v = pq->valueToSend(); + if (pq->last_value != v) { + tilt_eq.mix = v; + changed = true; + pq->syncValue(); + } + if (changed) { + pushTiltEq(); + } +} + +void TiltModule::processControls() +{ + if (!control_rate.process()) { return; } + processTiltEqControls(); +} + +void TiltModule::processCV(int paramId) +{ + auto pq = dynamic_cast(getParamQuantity(paramId)); + if (!pq) return; + if (pq->inputId < 0) return; + + auto in = getInput(pq->inputId); + + bool relative = pq->relativeId >= 0 ? getParam(pq->relativeId).getValue() > .5f : false; + if (pq->lightId >= 0) { + getLight(pq->lightId).setBrightness((relative *.20f) + ((in.isConnected() && relative) *.80f)); + } + + if (in.isConnected()) { + auto v = in.getVoltage(); + if (relative) { + pq->setRelativeVoltage(v); + } else { + pq->offset = 0.f; + pq->setKnobVoltage(v); + } + } else { + pq->offset = 0.f; + } +} + +void TiltModule::process(const ProcessArgs& args) +{ + if ((0 == ((args.frame + id) % CV_INTERVAL))) { + processCV(Params::P_TEQ_TILT); + processCV(Params::P_TEQ_FREQ); + processCV(Params::P_TEQ_MIX); + } + + processControls(); + getLight(Lights::L_TEQ).setBrightness(static_cast(tilt_eq.mix)/127.f); +} + +} + +Model *modelTilt = createModel("pachde-hc-tilt-eq"); \ No newline at end of file diff --git a/src/Tilt/Tilt.hpp b/src/Tilt/Tilt.hpp new file mode 100644 index 0000000..5b5a070 --- /dev/null +++ b/src/Tilt/Tilt.hpp @@ -0,0 +1,125 @@ +#pragma once +#ifndef TILT_HPP_INCLUDED +#define TILT_HPP_INCLUDED +#include "../hc_events.hpp" +#include "../module_broker.hpp" +#include "../plugin.hpp" +#include "../widgets/label_widget.hpp" +#include "../widgets/partner_picker.hpp" +//#include "../widgets/symbol_widget.hpp" + +namespace pachde { + +using Symbol = SymbolWidget::Symbol; + + +struct TiltModule : Module, ISendMidi, IHandleHcEvents +{ + enum Params + { + P_TEQ_TILT, + P_TEQ_FREQ, + P_TEQ_MIX, + P_TEQ_TILT_REL, + P_TEQ_FREQ_REL, + P_TEQ_MIX_REL, + + NUM_PARAMS, + }; + enum Inputs + { + IN_TEQ_TILT, + IN_TEQ_FREQ, + IN_TEQ_MIX, + + NUM_INPUTS + }; + enum Outputs + { + NUM_OUTPUTS + }; + enum Lights + { + L_TEQ_TILT_REL, + L_TEQ_FREQ_REL, + L_TEQ_MIX_REL, + + L_TEQ, + + NUM_LIGHTS + }; + + TiltEq tilt_eq; + + + IHandleHcEvents * ui_event_sink = nullptr; + PartnerBinding partner_binding; + const int CV_INTERVAL = 128; + RateTrigger control_rate; + + explicit TiltModule(); + virtual ~TiltModule(); + Hc1Module * getPartner(); + + void pullTiltEq(Hc1Module * partner = nullptr); + void pushTiltEq(Hc1Module * partner = nullptr); + void processTiltEqControls(); + void processControls(); + void processCV(int paramId); + + // ISendMidi + //virtual void sendNoteOn(uint8_t channel, uint8_t note, uint8_t velocity) {} + //virtual void sendNoteOff(uint8_t channel, uint8_t note, uint8_t velocity) {} + void sendControlChange(uint8_t channel, uint8_t cc, uint8_t value) override; + //void sendProgramChange(uint8_t channel, uint8_t program) {} + //void sendKeyPressure(uint8_t channel, uint8_t note, uint8_t pressure) {} + //void sendChannelPressure(uint8_t channel, uint8_t pressure) {} + //void sendPitchBend(uint8_t channel, uint8_t bend_lo, uint8_t bend_hi) {} + bool readyToSend() override; + + // IHandleHcEvents + //void onPresetChanged(const PresetChangedEvent& e) override; + //void onRoundingChanged(const RoundingChangedEvent& e) override; + //void onPedalChanged(const PedalChangedEvent& e) override; + void onTiltEqChanged(const TiltEqChangedEvent& e) override; + void onDeviceChanged(const DeviceChangedEvent& e) override; + void onDisconnect(const DisconnectEvent& e) override; + //void onFavoritesFileChanged(const FavoritesFileChangedEvent& e) override; + + // Module + json_t *dataToJson() override; + void dataFromJson(json_t *root) override; + void process(const ProcessArgs& args) override; +}; + +using TiltO = TiltModule::Outputs; + +struct TiltModuleWidget : ModuleWidget, IHandleHcEvents +{ + TiltModule * my_module; + PartnerPicker* partner_picker = nullptr; + + explicit TiltModuleWidget(TiltModule * module); + + virtual ~TiltModuleWidget() { + if (my_module) { + my_module->ui_event_sink = nullptr; + } + } + + Hc1Module * getPartner(); + + // IHandleHcEvents + // void onPresetChanged(const PresetChangedEvent& e) override; + // void onRoundingChanged(const RoundingChangedEvent& e) override; + void onDeviceChanged(const DeviceChangedEvent& e) override; + void onDisconnect(const DisconnectEvent& e) override; + // void onFavoritesFileChanged(const FavoritesFileChangedEvent& e) override; + + void appendContextMenu(Menu *menu) override; +}; + + + +} +#endif \ No newline at end of file diff --git a/src/plugin.cpp b/src/plugin.cpp index 75e8145..57919a8 100644 --- a/src/plugin.cpp +++ b/src/plugin.cpp @@ -13,6 +13,7 @@ void init(Plugin *p) p->addModel(modelPedal2); p->addModel(modelRound); p->addModel(modelCompress); + p->addModel(modelTilt); // Any other plugin initialization may go here. // As an alternative, consider lazy-loading assets and lookup tables when your module is created to reduce startup times of Rack. diff --git a/src/plugin.hpp b/src/plugin.hpp index d8b64de..afe2481 100644 --- a/src/plugin.hpp +++ b/src/plugin.hpp @@ -11,4 +11,5 @@ extern Model* modelPedal1; extern Model* modelPedal2; extern Model* modelRound; extern Model* modelCompress; +extern Model* modelTilt;