diff --git a/src/deluge/dsp/reverb/base.hpp b/src/deluge/dsp/reverb/base.hpp index 5e53d1b681..355c18f999 100644 --- a/src/deluge/dsp/reverb/base.hpp +++ b/src/deluge/dsp/reverb/base.hpp @@ -32,6 +32,9 @@ struct Base { virtual void setHPF(float f) {} [[nodiscard]] virtual float getHPF() const { return 0; } + virtual void setLPF(float f) {} + [[nodiscard]] virtual float getLPF() const { return 0; } + virtual void setDamping(float value) {} [[nodiscard]] virtual float getDamping() const { return 0; } diff --git a/src/deluge/dsp/reverb/mutable/reverb.hpp b/src/deluge/dsp/reverb/mutable/reverb.hpp index 3caedcf057..b8202bfbe5 100644 --- a/src/deluge/dsp/reverb/mutable/reverb.hpp +++ b/src/deluge/dsp/reverb/mutable/reverb.hpp @@ -86,6 +86,8 @@ class Mutable : public Base { wet = c.Get(); dsp::OnePole(hp_r_, wet, hp_cutoff_); wet = wet - hp_r_; + dsp::OnePole(lp_r_, wet, lp_cutoff_); + wet = lp_r_; auto output_right = static_cast(wet * static_cast(std::numeric_limits::max()) * 0xF); @@ -99,6 +101,8 @@ class Mutable : public Base { wet = c.Get(); dsp::OnePole(hp_l_, wet, hp_cutoff_); wet = wet - hp_l_; + dsp::OnePole(lp_l_, wet, lp_cutoff_); + wet = lp_l_; auto output_left = static_cast(wet * static_cast(std::numeric_limits::max()) * 0xF); @@ -143,6 +147,12 @@ class Mutable : public Base { [[nodiscard]] float getHPF() const { return hp_cutoff_val_; } + void setLPF(float f) { + lp_cutoff_val_ = f; + lp_cutoff_ = calcFilterCutoff(f); + } + + [[nodiscard]] float getLPF() const { return lp_cutoff_val_; } private: static constexpr float sample_rate = kSampleRate; @@ -171,6 +181,13 @@ class Mutable : public Base { float hp_cutoff_{calcFilterCutoff(0)}; float hp_l_{0.0}; // HP state variable float hp_r_{0.0}; // HP state variable + + // Low-pass + float lp_cutoff_val_{0.f}; + // corresponds to 20Hz + float lp_cutoff_{calcFilterCutoff(0)}; + float lp_l_{0.0}; // LP state variable + float lp_r_{0.0}; // LP state variable }; } // namespace deluge::dsp::reverb diff --git a/src/deluge/dsp/reverb/reverb.hpp b/src/deluge/dsp/reverb/reverb.hpp index a2bbd25a8c..fb7d8acb36 100644 --- a/src/deluge/dsp/reverb/reverb.hpp +++ b/src/deluge/dsp/reverb/reverb.hpp @@ -35,6 +35,7 @@ class Reverb : reverb::Base { base_->setDamping(damping_); base_->setWidth(width_); base_->setHPF(hpf_); + base_->setLPF(lpf_); model_ = m; } @@ -83,6 +84,12 @@ class Reverb : reverb::Base { } [[nodiscard]] virtual float getHPF() const { return base_->getHPF(); } + virtual void setLPF(float f) { + lpf_ = f; + base_->setLPF(f); + } + [[nodiscard]] virtual float getLPF() const { return base_->getLPF(); } + template constexpr T& reverb_as() { return std::get(reverb_); @@ -103,5 +110,6 @@ class Reverb : reverb::Base { float damping_; float width_; float hpf_; + float lpf_; }; } // namespace deluge::dsp diff --git a/src/deluge/gui/l10n/english.json b/src/deluge/gui/l10n/english.json index 5cabd08e62..4945f39088 100644 --- a/src/deluge/gui/l10n/english.json +++ b/src/deluge/gui/l10n/english.json @@ -533,10 +533,12 @@ "STRING_FOR_LFO1_TYPE": "LFO1 shape", "STRING_FOR_LFO1_RATE": "LFO1 rate", "STRING_FOR_LFO1_SYNC": "LFO1 sync", + "STRING_FOR_LFO1_SLEW": "LFO1 slew", "STRING_FOR_LFO1": "LFO1", "STRING_FOR_LFO2_TYPE": "LFO2 shape", "STRING_FOR_LFO2_RATE": "LFO2 rate", "STRING_FOR_LFO2_SYNC": "LFO2 sync", + "STRING_FOR_LFO1_SLEW": "LFO2 slew", "STRING_FOR_LFO2": "LFO2", "STRING_FOR_MODFX_TYPE": "MOD-FX type", "STRING_FOR_FEEDBACK": "FEEDBACK", diff --git a/src/deluge/gui/l10n/g_english.cpp b/src/deluge/gui/l10n/g_english.cpp index 6847df42a5..291a3503e7 100644 --- a/src/deluge/gui/l10n/g_english.cpp +++ b/src/deluge/gui/l10n/g_english.cpp @@ -487,6 +487,7 @@ PLACE_SDRAM_DATA Language english{ {STRING_FOR_LFO1_TYPE, "LFO1 shape"}, {STRING_FOR_LFO1_RATE, "LFO1 rate"}, {STRING_FOR_LFO1_SYNC, "LFO1 sync"}, + {STRING_FOR_LFO1_SLEW, "LFO2 slew"}, {STRING_FOR_LFO1, "LFO1"}, {STRING_FOR_LFO2_TYPE, "LFO2 shape"}, {STRING_FOR_LFO2_RATE, "LFO2 rate"}, diff --git a/src/deluge/gui/l10n/strings.h b/src/deluge/gui/l10n/strings.h index 7bb665e6b2..cc17470e1d 100644 --- a/src/deluge/gui/l10n/strings.h +++ b/src/deluge/gui/l10n/strings.h @@ -517,10 +517,12 @@ enum class String : size_t { STRING_FOR_LFO1_TYPE, STRING_FOR_LFO1_RATE, STRING_FOR_LFO1_SYNC, + STRING_FOR_LFO1_SLEW, STRING_FOR_LFO1, STRING_FOR_LFO2_TYPE, STRING_FOR_LFO2_RATE, STRING_FOR_LFO2_SYNC, + STRING_FOR_LFO2_SLEW, STRING_FOR_LFO2, STRING_FOR_MODFX_TYPE, STRING_FOR_MODFX_RATE, diff --git a/src/deluge/gui/menu_item/lfo/slew.h b/src/deluge/gui/menu_item/lfo/slew.h new file mode 100644 index 0000000000..665c41f2a1 --- /dev/null +++ b/src/deluge/gui/menu_item/lfo/slew.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2014-2023 Synthstrom Audible Limited + * + * This file is part of The Synthstrom Audible Deluge Firmware. + * + * The Synthstrom Audible Deluge Firmware 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 (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 . + */ +#pragma once +#include "gui/menu_item/integer.h" +#include "gui/menu_item/patched_param/integer.h" + +//I'm assuming this is all wrong +namespace deluge::gui::menu_item::lfo { +class Slew final : public Integer { +public: + using Integer::Integer; + void readCurrentValue() override { this->setValue(soundEditor.currentSound->slew); } + void writeCurrentValue() override { soundEditor.currentSound->setSlew(this->getValue()); } + [[nodiscard]] int32_t getMaxValue() const override { return kMaxSlew; } +}; + +extern Slew slewMenu; +} // namespace deluge::gui::menu_item::lfo diff --git a/src/deluge/gui/menu_item/lfo/sync.h b/src/deluge/gui/menu_item/lfo/sync.h index 236f60e0d5..3714a0c3aa 100644 --- a/src/deluge/gui/menu_item/lfo/sync.h +++ b/src/deluge/gui/menu_item/lfo/sync.h @@ -22,7 +22,7 @@ namespace deluge::gui::menu_item::lfo { -class Sync final : public SyncLevel { +class Sync : public SyncLevel { public: Sync(deluge::l10n::String name, deluge::l10n::String type, uint8_t lfoId) : SyncLevel(name, type), lfoId_(lfoId) {} @@ -43,5 +43,11 @@ class Sync final : public SyncLevel { private: uint8_t lfoId_; }; +//making slew accessible by select + sync +class SyncToSlew final : public Sync { +public: + using Sync::Sync; + MenuItem* selectButtonPress() override { return &lfo::slewMenu; } +}; } // namespace deluge::gui::menu_item::lfo diff --git a/src/deluge/gui/menu_item/reverb/lpf.h b/src/deluge/gui/menu_item/reverb/lpf.h new file mode 100644 index 0000000000..b07996f723 --- /dev/null +++ b/src/deluge/gui/menu_item/reverb/lpf.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2014-2023 Synthstrom Audible Limited + * + * This file is part of The Synthstrom Audible Deluge Firmware. + * + * The Synthstrom Audible Deluge Firmware 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 (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 . + */ +#pragma once +#include "definitions_cxx.hpp" +#include "dsp/reverb/mutable/reverb.hpp" +#include "dsp/reverb/reverb.hpp" +#include "gui/l10n/strings.h" +#include "gui/menu_item/integer.h" +#include "processing/engines/audio_engine.h" +#include + +namespace deluge::gui::menu_item::reverb { +class LPF final : public Integer { +public: + using Integer::Integer; + void readCurrentValue() override { this->setValue(AudioEngine::reverb.getLPF() * kMaxMenuValue); } + void writeCurrentValue() override { AudioEngine::reverb.setLPF((float)this->getValue() / kMaxMenuValue); } + + [[nodiscard]] int32_t getMaxValue() const override { return kMaxMenuValue; } + + bool isRelevant(ModControllableAudio* modControllable, int32_t whichThing) override { + return (AudioEngine::reverb.getModel() == dsp::Reverb::Model::MUTABLE); + } +}; +} // namespace deluge::gui::menu_item::reverb diff --git a/src/deluge/gui/ui/menus.cpp b/src/deluge/gui/ui/menus.cpp index 7ef0cf74b4..6cd74e10c1 100644 --- a/src/deluge/gui/ui/menus.cpp +++ b/src/deluge/gui/ui/menus.cpp @@ -74,6 +74,7 @@ #include "gui/menu_item/lfo/rate.h" #include "gui/menu_item/lfo/sync.h" #include "gui/menu_item/lfo/type.h" +#include "gui/menu_item/lfo/slew.h" #include "gui/menu_item/master_transpose.h" #include "gui/menu_item/menu_item.h" #include "gui/menu_item/midi/after_touch_to_mono.h" @@ -126,6 +127,7 @@ #include "gui/menu_item/record/quantize.h" #include "gui/menu_item/reverb/damping.h" #include "gui/menu_item/reverb/hpf.h" +#include "gui/menu_item/reverb/lpf.h" #include "gui/menu_item/reverb/model.h" #include "gui/menu_item/reverb/pan.h" #include "gui/menu_item/reverb/room_size.h" @@ -409,6 +411,7 @@ reverb::Width reverbWidthMenu{STRING_FOR_WIDTH, STRING_FOR_REVERB_WIDTH}; reverb::Pan reverbPanMenu{STRING_FOR_PAN, STRING_FOR_REVERB_PAN}; reverb::Model reverbModelMenu{STRING_FOR_MODEL}; reverb::HPF reverbHPFMenu{STRING_FOR_HPF}; +reverb::LPF reverbLPFMenu{STRING_FOR_LPF}; Submenu reverbMenu{ STRING_FOR_REVERB, @@ -419,6 +422,7 @@ Submenu reverbMenu{ &reverbDampingMenu, &reverbWidthMenu, &reverbHPFMenu, + &reverbLPFMenu, &reverbPanMenu, &reverbSidechainMenu, }, diff --git a/src/deluge/modulation/lfo.h b/src/deluge/modulation/lfo.h index 70edcb995a..4a2894bde5 100644 --- a/src/deluge/modulation/lfo.h +++ b/src/deluge/modulation/lfo.h @@ -75,6 +75,9 @@ class LFO { case LFOType::RANDOM_WALK: { uint32_t range = 4294967295u / 20; + + float slewRate = 0.01f; + if (phase == 0) { value = (range / 2) - CONG % range; holdValue = value; @@ -91,7 +94,19 @@ class LFO { // holdValue == -8 * range => (holdValue / -16) + (range / 2) == // range => next holdValue >= current holdValuie holdValue = add_saturation((holdValue / -16) + (range / 2) - CONG % range, holdValue); - value = holdValue; + + // checks if change is within slew rate + if (abs(holdValue - value) > slewRate) { + // limit if so + if (holdValue > value) { + value += slewRate; // increase + } else { + value -= slewRate; // decrease + } + } else { + // if change less than slew rate, dirctly assign + value = holdValue; + } } else { value = holdValue;