Vital
Loading...
Searching...
No Matches
modulation_interface.cpp
Go to the documentation of this file.
2
3#include "envelope_section.h"
4#include "extra_mod_section.h"
5#include "lfo_section.h"
6#include "random_section.h"
8
9namespace {
10 // Strings representing keyboard modulation sources for top and bottom rows.
11 const char* kKeyboardTopModulationStrings[] = {
12 "note",
13 "velocity",
14 "lift",
15 "note_in_octave"
16 };
17
18 const char* kKeyboardBottomModulationStrings[] = {
19 "aftertouch",
20 "slide",
21 "stereo",
22 "random",
23 };
24}
25
27 // Create envelope sections
28 for (int i = 0; i < vital::kNumEnvelopes; ++i) {
29 std::string string_num = std::to_string(i + 1);
30 std::string prefix = "env_" + string_num;
31 envelopes_[i] = std::make_unique<EnvelopeSection>("ENVELOPE " + string_num, prefix,
32 synth_data->mono_modulations, synth_data->poly_modulations);
33 addSubSection(envelopes_[i].get());
34 envelopes_[i]->setVisible(i == 0);
35 }
36
37 // Create and configure envelope tab selector
38 envelope_tab_selector_ = std::make_unique<ModulationTabSelector>("env", vital::kNumEnvelopes);
39 addSubSection(envelope_tab_selector_.get());
40 envelope_tab_selector_->addListener(this);
41 envelope_tab_selector_->registerModulationButtons(this);
42 envelope_tab_selector_->enableSelections();
43 envelope_tab_selector_->setMinModulationsShown(kMinEnvelopeModulationsToShow);
44 envelope_tab_selector_->connectRight(true);
45 envelope_tab_selector_->drawBorders(true);
46
47 // Create LFO sections
48 for (int i = 0; i < vital::kNumLfos; ++i) {
49 std::string string_num = std::to_string(i + 1);
50 std::string prefix = "lfo_" + string_num;
51 lfos_[i] = std::make_unique<LfoSection>("LFO " + string_num, prefix, synth_data->synth->getLfoSource(i),
52 synth_data->mono_modulations, synth_data->poly_modulations);
53 addSubSection(lfos_[i].get());
54 lfos_[i]->setVisible(i == 0);
55 }
56
57 // Create and configure LFO tab selector
58 lfo_tab_selector_ = std::make_unique<ModulationTabSelector>("lfo", vital::kNumLfos);
59 addSubSection(lfo_tab_selector_.get());
60 lfo_tab_selector_->addListener(this);
61 lfo_tab_selector_->registerModulationButtons(this);
62 lfo_tab_selector_->enableSelections();
63 lfo_tab_selector_->setMinModulationsShown(kMinLfoModulationsToShow);
64 lfo_tab_selector_->connectRight(true);
65 lfo_tab_selector_->drawBorders(true);
66
67 // Create random modulation sections
68 for (int i = 0; i < vital::kNumRandomLfos; ++i) {
69 std::string string_num = std::to_string(i + 1);
70 std::string prefix = "random_" + string_num;
71 random_lfos_[i] = std::make_unique<RandomSection>("RANDOM " + string_num, prefix,
72 synth_data->mono_modulations, synth_data->poly_modulations);
73 addSubSection(random_lfos_[i].get());
74 random_lfos_[i]->setVisible(i == 0);
75 }
76
77 // Create and configure random tab selector
78 random_tab_selector_ = std::make_unique<ModulationTabSelector>("random", vital::kNumRandomLfos);
79 addSubSection(random_tab_selector_.get());
80 random_tab_selector_->addListener(this);
81 random_tab_selector_->registerModulationButtons(this);
82 random_tab_selector_->enableSelections();
83 random_tab_selector_->setMinModulationsShown(kMinRandomModulationsToShow);
84 random_tab_selector_->connectRight(true);
85 random_tab_selector_->drawBorders(true);
86
87 // Keyboard modulation selectors (top and bottom rows)
88 keyboard_modulations_top_ = std::make_unique<ModulationTabSelector>("top", 4, kKeyboardTopModulationStrings);
89 addSubSection(keyboard_modulations_top_.get());
90 keyboard_modulations_top_->registerModulationButtons(this);
91 keyboard_modulations_top_->setVertical(false);
92 keyboard_modulations_top_->getButton(3)->overrideText("OCT NOTE"); // Special label
93 keyboard_modulations_top_->drawBorders(true);
94
95 keyboard_modulations_bottom_ = std::make_unique<ModulationTabSelector>("bottom", 4, kKeyboardBottomModulationStrings);
96 addSubSection(keyboard_modulations_bottom_.get());
97 keyboard_modulations_bottom_->registerModulationButtons(this);
98 keyboard_modulations_bottom_->setVertical(false);
99 keyboard_modulations_bottom_->getButton(0)->overrideText("PRESSURE"); // Special label
100 keyboard_modulations_bottom_->drawBorders(true);
101
102 setOpaque(false);
103}
104
106
108 g.fillAll(findColour(Skin::kBackground, true));
110
111 // Draw backgrounds behind mod sections
112 int mod_x = lfo_tab_selector_->getX();
113 int lfo_env_width = lfos_[0]->getRight() - mod_x;
114 Rectangle<int> lfo_bounds(mod_x, lfo_tab_selector_->getY(), lfo_env_width, lfo_tab_selector_->getHeight());
115 paintBody(g, lfo_bounds);
116 Rectangle<int> env_bounds(mod_x, envelope_tab_selector_->getY(), lfo_env_width, envelope_tab_selector_->getHeight());
117 paintBody(g, env_bounds);
118
119 int random_width = random_lfos_[0]->getRight() - mod_x;
120 Rectangle<int> random_bounds(mod_x, random_tab_selector_->getY(), random_width, random_tab_selector_->getHeight());
121 paintBody(g, random_bounds);
122
124 g.saveState();
125 int tabs_right = lfo_tab_selector_->getRight();
126 g.reduceClipRegion(tabs_right, 0, getWidth() - tabs_right, getHeight());
127
128 // Paint borders around sections
129 paintBorder(g, lfo_bounds);
130 paintBorder(g, env_bounds);
131 paintBorder(g, random_bounds);
132 g.restoreState();
133}
134
136 paintTabShadow(g, envelope_tab_selector_->getBounds());
137 paintTabShadow(g, envelopes_[0]->getBounds());
138 paintTabShadow(g, lfo_tab_selector_->getBounds());
139 paintTabShadow(g, lfos_[0]->getBounds());
140 paintTabShadow(g, random_tab_selector_->getBounds());
141 paintTabShadow(g, random_lfos_[0]->getBounds());
142 paintTabShadow(g, keyboard_modulations_top_->getBounds());
143 paintTabShadow(g, keyboard_modulations_bottom_->getBounds());
144}
145
147 int padding = getPadding();
148 int active_width = getWidth();
149 int active_height = getHeight() - 2 * padding;
150
151 // Allocate vertical space based on minimum modulations shown
152 int envelope_height = (active_height * kMinEnvelopeModulationsToShow * 1.0f) / kMinTotalModulations;
153 int lfo_height = (active_height * kMinLfoModulationsToShow * 1.0f) / kMinTotalModulations;
155
156 // Envelopes
157 envelope_tab_selector_->setBounds(0, 0, mod_width, envelope_height);
158 Rectangle<int> envelope_bounds(mod_width, 0, active_width - mod_width, envelope_height);
159 for (int i = 0; i < vital::kNumEnvelopes; ++i)
160 envelopes_[i]->setBounds(envelope_bounds);
161
162 // LFOs
163 int lfo_y = envelope_bounds.getBottom() + padding;
164 lfo_tab_selector_->setBounds(0, lfo_y, mod_width, lfo_height);
165 Rectangle<int> lfo_bounds(mod_width, lfo_y, active_width - mod_width, lfo_height);
166 for (int i = 0; i < vital::kNumLfos; ++i)
167 lfos_[i]->setBounds(lfo_bounds);
168
169 // Random modulations
170 int keyboard_width = mod_width * 4;
171 int keyboard_x = getWidth() - keyboard_width;
172
173 int random_y = lfo_bounds.getBottom() + padding;
174 int random_height = getHeight() - random_y;
175 random_tab_selector_->setBounds(0, random_y, mod_width, random_height);
176 Rectangle<int> random_bounds(mod_width, random_y, keyboard_x - padding - mod_width, random_height);
177 for (int i = 0; i < vital::kNumRandomLfos; ++i)
178 random_lfos_[i]->setBounds(random_bounds);
179
180 // Keyboard modulations
181 int keyboard_top_height = random_height / 2;
182 keyboard_modulations_top_->setBounds(keyboard_x, random_y, keyboard_width, keyboard_top_height);
183
184 int keyboard_bottom_y = random_y + keyboard_top_height + 1;
185 int keyboard_bottom_height = getHeight() - keyboard_bottom_y;
186 keyboard_modulations_bottom_->setBounds(keyboard_x, keyboard_bottom_y, keyboard_width, keyboard_bottom_height);
187
188 // Adjust font sizes for selectors
189 envelope_tab_selector_->setFontSize(getModFontSize());
190 lfo_tab_selector_->setFontSize(getModFontSize());
191 random_tab_selector_->setFontSize(getModFontSize());
192 keyboard_modulations_top_->setFontSize(getModFontSize());
193 keyboard_modulations_bottom_->setFontSize(getModFontSize());
194
196}
197
199 lfo_tab_selector_->reset();
200 envelope_tab_selector_->reset();
201 random_tab_selector_->reset();
202 keyboard_modulations_top_->reset();
203 keyboard_modulations_bottom_->reset();
204
205 // Reset visible sections
206 for (int i = 0; i < vital::kNumEnvelopes; ++i) {
207 if (envelopes_[i]->isVisible())
208 envelopes_[i]->reset();
209 }
210 for (int i = 0; i < vital::kNumLfos; ++i) {
211 if (lfos_[i]->isVisible())
212 lfos_[i]->reset();
213 }
214 for (int i = 0; i < vital::kNumRandomLfos; ++i) {
215 if (random_lfos_[i]->isVisible())
216 random_lfos_[i]->reset();
217 }
218}
219
221 lfo_tab_selector_->checkNumShown(true);
222 envelope_tab_selector_->checkNumShown(true);
223 random_tab_selector_->checkNumShown(true);
224 keyboard_modulations_top_->checkNumShown(true);
225 keyboard_modulations_bottom_->checkNumShown(true);
226}
227
229 Image image(Image::ARGB, 1, 1, false);
230 Graphics g(image);
231
232 // Handle switching between different modulation tabs
233 if (selector == envelope_tab_selector_.get()) {
234 for (int i = 0; i < vital::kNumEnvelopes; ++i)
235 envelopes_[i]->setVisible(i == index);
236 envelopes_[index]->paintOpenGlChildrenBackgrounds(g);
237 envelopes_[index]->reset();
238 }
239 else if (selector == lfo_tab_selector_.get()) {
240 for (int i = 0; i < vital::kNumLfos; ++i)
241 lfos_[i]->setVisible(i == index);
242 lfos_[index]->paintOpenGlChildrenBackgrounds(g);
243 lfos_[index]->reset();
244 }
245 else if (selector == random_tab_selector_.get()) {
246 for (int i = 0; i < vital::kNumRandomLfos; ++i)
247 random_lfos_[i]->setVisible(i == index);
248 random_lfos_[index]->paintOpenGlChildrenBackgrounds(g);
249 random_lfos_[index]->reset();
250 }
251}
~ModulationInterface()
Destructor.
Definition modulation_interface.cpp:105
static constexpr int kMinLfoModulationsToShow
Minimum LFOs to show.
Definition modulation_interface.h:34
static constexpr int kMinTotalModulations
Definition modulation_interface.h:36
void checkNumShown()
Checks and adjusts the number of shown modulations in each category to maintain consistency with the ...
Definition modulation_interface.cpp:220
void paintBackground(Graphics &g) override
Paints the background of the modulation interface.
Definition modulation_interface.cpp:107
void reset() override
Resets all visible modulation sections to their default states.
Definition modulation_interface.cpp:198
void resized() override
Called when the component is resized.
Definition modulation_interface.cpp:146
void modulationSelected(ModulationTabSelector *selector, int index) override
Called when a modulation tab is selected.
Definition modulation_interface.cpp:228
void paintBackgroundShadow(Graphics &g) override
Paints shadows behind the modulation sections.
Definition modulation_interface.cpp:135
static constexpr int kMinEnvelopeModulationsToShow
The minimum number of envelopes, LFOs, and random modulations to show by default.
Definition modulation_interface.h:33
ModulationInterface(SynthGuiData *synth_data)
Constructs the ModulationInterface.
Definition modulation_interface.cpp:26
static constexpr int kMinRandomModulationsToShow
Minimum random modulations to show.
Definition modulation_interface.h:35
A section of the GUI providing multiple modulation sources as tabs.
Definition modulation_tab_selector.h:16
@ kModulationButtonWidth
Definition skin.h:101
@ kBackground
Definition skin.h:128
LineGenerator * getLfoSource(int index)
Retrieves an LFO source by index.
Definition synth_base.cpp:278
Base class for all synthesizer sections, providing UI layout, painting, and interaction logic.
Definition synth_section.h:193
float getModFontSize()
Definition synth_section.cpp:672
float getPadding()
Definition synth_section.cpp:660
void addSubSection(SynthSection *section, bool show=true)
Adds a subsection (another SynthSection) as a child.
Definition synth_section.cpp:457
virtual void resized() override
Called when the component is resized. Arranges layout of child components.
Definition synth_section.cpp:35
virtual void paintBody(Graphics &g, Rectangle< int > bounds)
Paints the body background within given bounds.
Definition synth_section.cpp:165
void paintChildrenBackgrounds(Graphics &g)
Paints the backgrounds for all child sections.
Definition synth_section.cpp:274
float findValue(Skin::ValueId value_id) const
Finds a value in the skin overrides or from the parent if not found locally.
Definition synth_section.cpp:18
virtual void paintBorder(Graphics &g, Rectangle< int > bounds)
Paints the border around given bounds.
Definition synth_section.cpp:170
virtual void paintTabShadow(Graphics &g)
Paints a tab-like shadow effect around the component.
Definition synth_section.cpp:188
Declares the EnvelopeSection class, which provides a UI for configuring ADSR-type envelopes.
constexpr int kNumRandomLfos
Number of random LFO sources (random modulation generators).
Definition synth_constants.h:25
constexpr int kNumEnvelopes
Number of envelope generators in Vital.
Definition synth_constants.h:22
constexpr int kNumLfos
Number of LFO sources available in the Vital synthesizer.
Definition synth_constants.h:13
A struct holding references and data used by the GUI to interact with the SynthBase.
Definition synth_gui_interface.h:27
vital::output_map poly_modulations
Polyphonic modulation values.
Definition synth_gui_interface.h:37
vital::output_map mono_modulations
Mono (global) modulation values.
Definition synth_gui_interface.h:36
SynthBase * synth
Pointer back to the associated SynthBase.
Definition synth_gui_interface.h:40