Vital
Loading...
Searching...
No Matches
random_section.cpp
Go to the documentation of this file.
1#include "random_section.h"
2
3#include "skin.h"
4#include "fonts.h"
6#include "synth_strings.h"
7#include "tempo_selector.h"
8#include "text_selector.h"
10
19 public:
20 static constexpr int kResolution = 64;
21 static constexpr float kBoostAmount = 1.0f;
22 static constexpr float kDecayMult = 0.9f;
23
28 RandomViewer(String name) : OpenGlLineRenderer(kResolution), stereo_line_(kResolution), random_value_(nullptr) {
29 setName(name);
30 setFill(true);
31 setFillCenter(-1.0f);
32
33 stereo_line_.setFill(true);
34 stereo_line_.setFillCenter(-1.0f);
35 addAndMakeVisible(stereo_line_);
36
38 stereo_line_.setFillBoostAmount(kBoostAmount);
39 setBoostAmount(1.0f);
40 stereo_line_.setBoostAmount(1.0f);
41
42 float boost = 1.0f;
43 for (int i = 0; i < kResolution; ++i) {
44 setYAt(i, 10000);
45 stereo_line_.setYAt(i, 10000);
46 setBoostLeft(i, 0.0f);
47 stereo_line_.setBoostLeft(i, 0.0f);
48 boost *= kDecayMult;
49 }
50 }
51
56 void paintBackground(Graphics& g) override {
58 g.setColour(findColour(Skin::kWidgetPrimaryDisabled, true));
59 g.fillRect(0, getHeight() / 2, getWidth(), 1);
60 }
61
66 void init(OpenGlWrapper& open_gl) override {
68 stereo_line_.init(open_gl);
69 }
70
75 void destroy(OpenGlWrapper& open_gl) override {
77 stereo_line_.destroy(open_gl);
78 }
79
85 void render(OpenGlWrapper& open_gl, bool animate) override {
86 bool animating = animate;
87 if (parent_)
88 animating = animating && parent_->getSynth()->isModSourceEnabled(getName().toStdString());
89
90 if (random_value_ == nullptr || !animating) {
91 renderCorners(open_gl, animate);
92 return;
93 }
94
95 float line_width = findValue(Skin::kWidgetLineWidth);
96 setLineWidth(line_width);
97 stereo_line_.setLineWidth(line_width);
98 float fill_center = findValue(Skin::kWidgetFillCenter);
99 setFillCenter(fill_center);
100 stereo_line_.setFillCenter(fill_center);
101
102 float width = getWidth();
103 float height = getHeight();
104
105 // Shift old data
106 for (int i = kResolution - 1; i > 1; --i) {
107 float x = i * width / (kResolution - 1);
108 setXAt(i, x);
109 setYAt(i, yAt(i - 1));
110 stereo_line_.setXAt(i, x);
111 stereo_line_.setYAt(i, stereo_line_.yAt(i - 1));
112
113 setBoostLeft(i, boostLeftAt(i - 1));
114 stereo_line_.setBoostLeft(i, stereo_line_.boostLeftAt(i - 1));
115 }
116
117 // Set new random values
118 vital::poly_float random_value = (-random_value_->value() + 1.0f) * height;
119 setXAt(1, 0.0f);
120 setYAt(1, random_value[0]);
121 setXAt(0, -1.0f);
122 setYAt(0, random_value[0]);
123 float boost = 0.0f;
124 if (random_value[0] >= height || yAt(2) >= height || yAt(3) >= height)
125 boost = -1.0f;
126
127 setBoostLeft(0, boost);
128 setBoostLeft(1, boost);
129 setBoostLeft(2, boost);
130
131 stereo_line_.setXAt(0, -1.0f);
132 stereo_line_.setYAt(0, random_value[1]);
133 stereo_line_.setXAt(1, 0.0f);
134 stereo_line_.setYAt(1, random_value[1]);
135
136 boost = 0.0f;
137 if (random_value[1] >= height || stereo_line_.yAt(2) >= height || stereo_line_.yAt(3) >= height)
138 boost = -1.0f;
139
140 stereo_line_.setBoostLeft(0, boost);
141 stereo_line_.setBoostLeft(1, boost);
142 stereo_line_.setBoostLeft(2, boost);
143
144 Colour fill_color = findColour(Skin::kWidgetSecondary1, true);
145 float fill_fade = findValue(Skin::kWidgetFillFade);
146 Colour fill_color_fade = fill_color.withMultipliedAlpha(1.0f - fill_fade);
147
148 Colour fill_color_stereo = findColour(Skin::kWidgetSecondary2, true);
149 Colour fill_color_stereo_fade = fill_color_stereo.withMultipliedAlpha(1.0f - fill_fade);
150
151 stereo_line_.setColor(findColour(Skin::kWidgetPrimary2, true));
152 stereo_line_.setFillColors(fill_color_stereo_fade, fill_color_stereo);
153 stereo_line_.drawLines(open_gl, true);
154
155 setColor(findColour(Skin::kWidgetPrimary1, true));
156 setFillColors(fill_color_fade, fill_color);
157 OpenGlLineRenderer::drawLines(open_gl, true);
158
159 renderCorners(open_gl, animate);
160 }
161
165 void parentHierarchyChanged() override {
166 parent_ = findParentComponentOfClass<SynthGuiInterface>();
167
168 if (random_value_ == nullptr && parent_)
169 random_value_ = parent_->getSynth()->getStatusOutput(getName().toStdString());
170
172 }
173
177 void resized() override {
179 stereo_line_.setBounds(getLocalBounds());
180 }
181
182 private:
183 SynthGuiInterface* parent_;
184 OpenGlLineRenderer stereo_line_;
185 const vital::StatusOutput* random_value_;
186
187 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(RandomViewer)
188};
189
190RandomSection::RandomSection(String name, std::string value_prepend,
191 const vital::output_map& mono_modulations, const vital::output_map& poly_modulations) :
192 SynthSection(name) {
193 static constexpr double kTempoDragSensitivity = 0.3;
194
195 frequency_ = std::make_unique<SynthSlider>(value_prepend + "_frequency");
196 addSlider(frequency_.get());
197 frequency_->setSliderStyle(Slider::RotaryHorizontalVerticalDrag);
198 frequency_->setLookAndFeel(TextLookAndFeel::instance());
199
200 tempo_ = std::make_unique<SynthSlider>(value_prepend + "_tempo");
201 addSlider(tempo_.get());
202 tempo_->setSliderStyle(Slider::RotaryHorizontalVerticalDrag);
203 tempo_->setLookAndFeel(TextLookAndFeel::instance());
204 tempo_->setSensitivity(kTempoDragSensitivity);
205
206 keytrack_transpose_ = std::make_unique<SynthSlider>(value_prepend + "_keytrack_transpose");
207 addSlider(keytrack_transpose_.get());
208 keytrack_transpose_->setSliderStyle(Slider::RotaryHorizontalVerticalDrag);
209 keytrack_transpose_->setLookAndFeel(TextLookAndFeel::instance());
210 keytrack_transpose_->setSensitivity(kTransposeMouseSensitivity);
211 keytrack_transpose_->setBipolar();
212
213 keytrack_tune_ = std::make_unique<SynthSlider>(value_prepend + "_keytrack_tune");
214 addSlider(keytrack_tune_.get());
215 keytrack_tune_->setSliderStyle(Slider::RotaryHorizontalVerticalDrag);
216 keytrack_tune_->setLookAndFeel(TextLookAndFeel::instance());
217 keytrack_tune_->setBipolar();
218 keytrack_tune_->setMaxDisplayCharacters(3);
219 keytrack_tune_->setMaxDecimalPlaces(0);
220
221 transpose_tune_divider_ = std::make_unique<OpenGlQuad>(Shaders::kColorFragment);
222 addOpenGlComponent(transpose_tune_divider_.get());
223 transpose_tune_divider_->setInterceptsMouseClicks(false, false);
224
225 sync_ = std::make_unique<TempoSelector>(value_prepend + "_sync");
226 addSlider(sync_.get());
227 sync_->setSliderStyle(Slider::LinearBar);
228 sync_->setTempoSlider(tempo_.get());
229 sync_->setFreeSlider(frequency_.get());
230 sync_->setKeytrackTransposeSlider(keytrack_transpose_.get());
231 sync_->setKeytrackTuneSlider(keytrack_tune_.get());
232
233 style_ = std::make_unique<TextSelector>(value_prepend + "_style");
234 addSlider(style_.get());
235 style_->setSliderStyle(Slider::RotaryHorizontalVerticalDrag);
236 style_->setLookAndFeel(TextLookAndFeel::instance());
237 style_->setLongStringLookup(strings::kRandomNames);
238
239 viewer_ = std::make_unique<RandomViewer>(value_prepend);
240 addOpenGlComponent(viewer_.get());
241 addAndMakeVisible(viewer_.get());
242
243 stereo_ = std::make_unique<SynthButton>(value_prepend + "_stereo");
244 addButton(stereo_.get());
245 stereo_->setButtonText("STEREO");
246 stereo_->setLookAndFeel(TextLookAndFeel::instance());
247
248 sync_type_ = std::make_unique<SynthButton>(value_prepend + "_sync_type");
249 addButton(sync_type_.get());
250 sync_type_->setButtonText("SYNC");
251 sync_type_->setLookAndFeel(TextLookAndFeel::instance());
252
254}
255
257
259 setLabelFont(g);
260 int widget_margin = findValue(Skin::kWidgetMargin);
261 int frequency_right = getWidth() - widget_margin;
262 int tempo_x = tempo_->getX();
263 Rectangle<int> frequency_bounds(tempo_x, tempo_->getY(), frequency_right - tempo_x, tempo_->getHeight());
264
265 drawTextComponentBackground(g, style_->getBounds(), true);
266 drawTextComponentBackground(g, frequency_bounds, true);
267 drawTempoDivider(g, sync_.get());
268
269 drawLabel(g, TRANS("STYLE"), style_->getBounds(), true);
270 drawLabel(g, TRANS("FREQUENCY"), frequency_bounds, true);
271
272 transpose_tune_divider_->setColor(findColour(Skin::kLightenScreen, true));
273
276}
277
279 int knob_section_height = getKnobSectionHeight();
280 int text_button_height = findValue(Skin::kTextButtonHeight);
281
282 int widget_margin = findValue(Skin::kWidgetMargin);
283 int button_width = (getWidth() - 3 * widget_margin) / 2;
284 sync_type_->setBounds(widget_margin, widget_margin, button_width, text_button_height);
285 int stereo_x = sync_type_->getRight() + widget_margin;
286 stereo_->setBounds(stereo_x, widget_margin, getWidth() - stereo_x - widget_margin, text_button_height);
287
288 int viewer_y = text_button_height + 2 * widget_margin;
289 int viewer_height = getHeight() - knob_section_height - viewer_y;
290 viewer_->setBounds(widget_margin, viewer_y, getWidth() - 2 * widget_margin, viewer_height);
291
292 int component_width = (getWidth() - 3 * widget_margin) / 2;
293 int control_y = getHeight() - knob_section_height + widget_margin;
294 style_->setBounds(widget_margin, control_y, component_width, knob_section_height - 2 * widget_margin);
295 int frequency_x = style_->getRight() + widget_margin;
296 placeTempoControls(frequency_x, control_y, getWidth() - widget_margin - frequency_x,
297 knob_section_height - 2 * widget_margin, frequency_.get(), sync_.get());
298 tempo_->setBounds(frequency_->getBounds());
299 tempo_->setModulationArea(frequency_->getModulationArea());
300
301 Rectangle<int> divider_bounds = frequency_->getModulationArea() + frequency_->getBounds().getTopLeft();
302 divider_bounds = divider_bounds.reduced(divider_bounds.getHeight() / 4);
303 divider_bounds.setX(divider_bounds.getCentreX());
304 divider_bounds.setWidth(1);
305 transpose_tune_divider_->setBounds(divider_bounds);
306
307 Rectangle<int> frequency_bounds = frequency_->getBounds();
308 keytrack_transpose_->setBounds(frequency_bounds.withWidth(frequency_bounds.getWidth() / 2));
309 keytrack_tune_->setBounds(frequency_bounds.withLeft(keytrack_transpose_->getRight()));
310 keytrack_transpose_->setModulationArea(frequency_->getModulationArea().withWidth(keytrack_transpose_->getWidth()));
311 keytrack_tune_->setModulationArea(frequency_->getModulationArea().withWidth(keytrack_tune_->getWidth()));
312
314}
virtual void resized() override
Called when the component is resized.
Definition open_gl_component.cpp:121
void renderCorners(OpenGlWrapper &open_gl, bool animate, Colour color, float rounding)
Renders the corner shapes using the given color and rounding amount.
Definition open_gl_component.cpp:153
float findValue(Skin::ValueId value_id)
Finds a float value from the skin associated with this component's parent.
Definition open_gl_component.cpp:173
virtual void paintBackground(Graphics &g)
Paints a standard background for the component.
Definition open_gl_component.cpp:105
virtual void parentHierarchyChanged() override
Called when the component's parent hierarchy changes.
Definition open_gl_component.cpp:128
A component for rendering lines with optional filling and boost effects using OpenGL.
Definition open_gl_line_renderer.h:16
virtual void init(OpenGlWrapper &open_gl) override
Initializes OpenGL resources for rendering the line.
Definition open_gl_line_renderer.cpp:78
virtual void destroy(OpenGlWrapper &open_gl) override
Destroys OpenGL resources allocated by this line renderer.
Definition open_gl_line_renderer.cpp:468
force_inline void setFillCenter(float fill_center)
Sets the vertical center for the fill area.
Definition open_gl_line_renderer.h:138
force_inline void setYAt(int index, float val)
Sets the y-coordinate of a point, marking data as dirty.
Definition open_gl_line_renderer.h:98
force_inline void setFill(bool fill)
Enables or disables filling below the line.
Definition open_gl_line_renderer.h:124
force_inline void setFillBoostAmount(float boost_amount)
Sets the boost amount that affects fill thickness.
Definition open_gl_line_renderer.h:147
force_inline float boostLeftAt(int index) const
Gets the left-side boost at a given point index.
Definition open_gl_line_renderer.h:72
force_inline void setBoostAmount(float boost_amount)
Sets the boost amount that affects line thickness.
Definition open_gl_line_renderer.h:144
force_inline void setXAt(int index, float val)
Sets the x-coordinate of a point, marking data as dirty.
Definition open_gl_line_renderer.h:105
force_inline void setFillColors(Colour fill_color_from, Colour fill_color_to)
Sets a gradient fill from one color to another.
Definition open_gl_line_renderer.h:132
force_inline void setLineWidth(float width)
Sets the line width in pixels.
Definition open_gl_line_renderer.h:66
force_inline float yAt(int index) const
Gets the y-coordinate of a point at a given index.
Definition open_gl_line_renderer.h:78
force_inline void setColor(Colour color)
Sets the line color.
Definition open_gl_line_renderer.h:63
force_inline void setBoostLeft(int index, float val)
Sets the left-side boost for a point, marking data as dirty.
Definition open_gl_line_renderer.h:84
void drawLines(OpenGlWrapper &open_gl, bool left)
Draws the line and optional fill using OpenGL.
Definition open_gl_line_renderer.cpp:386
void paintBackground(Graphics &g) override
Paints the background of the random section including labels and backgrounds.
Definition random_section.cpp:258
~RandomSection()
Destructor.
Definition random_section.cpp:256
void resized() override
Called when the component is resized. Arranges the layout of sliders, buttons, and viewer.
Definition random_section.cpp:278
RandomSection(String name, std::string value_prepend, const vital::output_map &mono_modulations, const vital::output_map &poly_modulations)
Constructs a RandomSection.
Definition random_section.cpp:190
Visualizes the random modulation source as a waveform line renderer.
Definition random_section.cpp:18
void resized() override
Called when the component is resized. Updates the stereo_line_ bounds.
Definition random_section.cpp:177
void render(OpenGlWrapper &open_gl, bool animate) override
Renders the waveform lines. Updates positions based on the random source.
Definition random_section.cpp:85
RandomViewer(String name)
Constructs the RandomViewer with a given name.
Definition random_section.cpp:28
void parentHierarchyChanged() override
Called when the parent hierarchy changes, used to find the parent synth and status output.
Definition random_section.cpp:165
static constexpr float kBoostAmount
Initial boost amount for the line rendering.
Definition random_section.cpp:21
static constexpr float kDecayMult
Decay multiplier for boost values over time.
Definition random_section.cpp:22
void destroy(OpenGlWrapper &open_gl) override
Releases OpenGL resources.
Definition random_section.cpp:75
void paintBackground(Graphics &g) override
Paints the background of the viewer, including a reference line.
Definition random_section.cpp:56
static constexpr int kResolution
Number of points in the waveform visualization.
Definition random_section.cpp:20
void init(OpenGlWrapper &open_gl) override
Initializes OpenGL resources.
Definition random_section.cpp:66
@ kColorFragment
Definition shaders.h:63
@ kWidgetMargin
Definition skin.h:103
@ kWidgetLineWidth
Definition skin.h:105
@ kWidgetFillCenter
Definition skin.h:107
@ kWidgetFillFade
Definition skin.h:108
@ kTextButtonHeight
Definition skin.h:87
@ kWidgetPrimaryDisabled
Definition skin.h:167
@ kWidgetPrimary2
Definition skin.h:166
@ kWidgetPrimary1
Definition skin.h:165
@ kWidgetSecondary1
Definition skin.h:168
@ kLightenScreen
Definition skin.h:141
@ kWidgetSecondary2
Definition skin.h:169
@ kRandomLfo
Definition skin.h:41
bool isModSourceEnabled(const std::string &source)
Checks if a modulation source is currently enabled.
Definition synth_base.cpp:223
const vital::StatusOutput * getStatusOutput(const std::string &name)
Retrieves a status output by name.
Definition synth_base.cpp:262
An interface class linking the Vital synthesizer backend (SynthBase) with a GUI.
Definition synth_gui_interface.h:56
SynthBase * getSynth()
Returns the SynthBase instance this interface is managing.
Definition synth_gui_interface.h:85
Base class for all synthesizer sections, providing UI layout, painting, and interaction logic.
Definition synth_section.h:193
void drawTextComponentBackground(Graphics &g, Rectangle< int > bounds, bool extend_to_label)
Draws a background for a text component area.
Definition synth_section.cpp:319
void addSlider(SynthSlider *slider, bool show=true, bool listen=true)
Definition synth_section.cpp:445
void drawLabel(Graphics &g, String text, Rectangle< int > component_bounds, bool text_component=false)
Draws a label text below a component.
Definition synth_section.cpp:789
void drawTempoDivider(Graphics &g, Component *sync)
Draws a divider line for tempo-related controls.
Definition synth_section.cpp:339
virtual void resized() override
Called when the component is resized. Arranges layout of child components.
Definition synth_section.cpp:35
void placeTempoControls(int x, int y, int width, int height, SynthSlider *tempo, SynthSlider *sync)
Definition synth_section.cpp:584
static constexpr double kTransposeMouseSensitivity
Definition synth_section.h:204
void paintChildrenBackgrounds(Graphics &g)
Paints the backgrounds for all child sections.
Definition synth_section.cpp:274
void paintKnobShadows(Graphics &g)
Paints knob shadows for all sliders.
Definition synth_section.cpp:253
void setLabelFont(Graphics &g)
Sets the Graphics context font and color for labels.
Definition synth_section.cpp:740
void addButton(OpenGlToggleButton *button, bool show=true)
Definition synth_section.cpp:428
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
float getKnobSectionHeight()
Definition synth_section.cpp:633
void addOpenGlComponent(OpenGlComponent *open_gl_component, bool to_beginning=false)
Definition synth_section.cpp:489
void setSkinOverride(Skin::SectionOverride skin_override)
Definition synth_section.h:303
static TextLookAndFeel * instance()
Singleton instance access.
Definition text_look_and_feel.h:106
A helper class to track the "status" of a particular Output as a poly_float value.
Definition synth_module.h:35
force_inline poly_float value() const
Returns the current status value.
Definition synth_module.h:49
const std::string kRandomNames[]
Full names for different random generator modes.
Definition synth_strings.h:316
std::map< std::string, Output * > output_map
Maps parameter names to Output pointers, representing output signals from various modules.
Definition synth_types.h:229
A helper struct containing references to OpenGL context, shaders, and display scale.
Definition shaders.h:174
Represents a vector of floating-point values using SIMD instructions.
Definition poly_values.h:600
Declares the TempoSelector class, a specialized slider for selecting tempo-related modes.
Declares the TextSelector class and PaintPatternSelector class for selecting text-based options and d...