Vital
Loading...
Searching...
No Matches
wave_source_overlay.cpp
Go to the documentation of this file.
2
3#include "skin.h"
5#include "synth_strings.h"
7#include "text_selector.h"
8#include "wave_frame.h"
9
10namespace {
11 constexpr int kNumInterpolationTypes = 5;
12
13 const std::string interpolation_types[kNumInterpolationTypes] = {
14 "None",
15 "Waveform Blend",
16 "Spectral Blend",
17 "Smooth Waveform Blend",
18 "Smooth Spectral Blend",
19 };
20
21} // namespace
22
30WaveSourceOverlay::WaveSourceOverlay() : WavetableComponentOverlay("WAVE SOURCE"), wave_source_(nullptr) {
31 current_frame_ = nullptr;
32 int waveform_size = vital::WaveFrame::kWaveformSize;
33
34 // Create and configure time-domain editor
35 oscillator_ = std::make_unique<WaveSourceEditor>(waveform_size);
37 oscillator_->setFill(true);
38 oscillator_->setEditable(true);
39 oscillator_->addListener(this);
41 oscillator_->setVisible(false);
42
43 // Create and configure frequency amplitude editor
45 frequency_amplitudes_ = std::make_unique<BarEditor>(bar_size);
46 frequency_amplitudes_->setSquareScale(true);
47 frequency_amplitudes_->addListener(this);
49 frequency_amplitudes_->setVisible(false);
50
51 // Create and configure frequency phase editor
52 frequency_phases_ = std::make_unique<BarEditor>(bar_size);
53 frequency_phases_->addListener(this);
54 frequency_phases_->setClearValue(kDefaultPhase);
56 frequency_phases_->setVisible(false);
57
58 controls_background_.toFront(false);
59
60 // Create interpolation selector
61 interpolation_type_ = std::make_unique<TextSelector>("Interpolation");
63 interpolation_type_->setAlwaysOnTop(true);
64 interpolation_type_->getImageComponent()->setAlwaysOnTop(true);
65 interpolation_type_->setRange(0, kNumInterpolationTypes - 1);
66 interpolation_type_->setLongStringLookup(interpolation_types);
67 interpolation_type_->setStringLookup(interpolation_types);
68 interpolation_type_->setSliderStyle(Slider::RotaryHorizontalVerticalDrag);
70 interpolation_type_->addListener(this);
71
72 // Create horizontal grid slider
73 horizontal_grid_ = std::make_unique<SynthSlider>("wave_source_horizontal_grid");
74 horizontal_grid_->setValue(kDefaultXGrid, dontSendNotification);
76 horizontal_grid_->setAlwaysOnTop(true);
77 horizontal_grid_->getImageComponent()->setAlwaysOnTop(true);
78 horizontal_grid_->addListener(this);
80 horizontal_grid_->setDoubleClickReturnValue(true, kDefaultXGrid);
82 horizontal_grid_->setSliderStyle(Slider::RotaryHorizontalVerticalDrag);
83
84 // Create horizontal grid incrementer
85 horizontal_incrementers_ = std::make_unique<IncrementerButtons>(horizontal_grid_.get());
86 addAndMakeVisible(horizontal_incrementers_.get());
87
88 // Create vertical grid slider
89 vertical_grid_ = std::make_unique<SynthSlider>("wave_source_vertical_grid");
90 vertical_grid_->setValue(kDefaultYGrid, dontSendNotification);
92 vertical_grid_->setAlwaysOnTop(true);
93 vertical_grid_->getImageComponent()->setAlwaysOnTop(true);
94 vertical_grid_->addListener(this);
96 vertical_grid_->setDoubleClickReturnValue(true, kDefaultYGrid);
98 vertical_grid_->setSliderStyle(Slider::RotaryHorizontalVerticalDrag);
99
100 // Create vertical grid incrementer
101 vertical_incrementers_ = std::make_unique<IncrementerButtons>(vertical_grid_.get());
102 addAndMakeVisible(vertical_incrementers_.get());
103
104 // Configure background controls
109}
110
118 if (findParentComponentOfClass<SynthGuiInterface>() == nullptr)
119 return;
120
121 Colour line_color = findColour(Skin::kWidgetPrimary1, true);
122 oscillator_->setColor(line_color);
123 Colour fill_color1 = findColour(Skin::kWidgetSecondary1, true);
124 Colour fill_color2 = fill_color1.withMultipliedAlpha(1.0f - findValue(Skin::kWidgetFillFade));
125 oscillator_->setFillColors(fill_color2, fill_color1);
126
127 Colour bar_color = findColour(Skin::kWidgetSecondary2, true);
128 frequency_amplitudes_->setColor(bar_color);
129 frequency_phases_->setColor(bar_color);
130}
131
141 if (keyframe == nullptr) {
142 oscillator_->setVisible(false);
143 frequency_amplitudes_->setVisible(false);
144 frequency_phases_->setVisible(false);
145 current_frame_ = nullptr;
146 }
147 else if (keyframe->owner() == wave_source_) {
148 oscillator_->setVisible(true);
149 frequency_amplitudes_->setVisible(true);
150 frequency_phases_->setVisible(true);
152 oscillator_->loadWaveform(current_frame_->time_domain);
154 }
155}
156
165void WaveSourceOverlay::setEditBounds(Rectangle<int> bounds) {
166 static constexpr float kInterpolationWidthHeightRatio = 8.0f;
167 static constexpr float kGridWidthHeightRatio = 2.0f;
168
169 int padding = getPadding();
170 int interpolation_width = bounds.getHeight() * kInterpolationWidthHeightRatio;
171 int grid_width = bounds.getHeight() * kGridWidthHeightRatio;
172 int total_width = interpolation_width + 2 * grid_width + 2 * padding;
173 setControlsWidth(total_width);
175
176 int x = bounds.getX() + (bounds.getWidth() - total_width) / 2;
177 int title_height = WavetableComponentOverlay::kTitleHeightRatio * bounds.getHeight();
178 int y = bounds.getY();
179 int y_title = y + title_height;
180 int height = bounds.getHeight();
181 int height_title = height - title_height;
182 interpolation_type_->setBounds(x, y, interpolation_width, height);
183 interpolation_type_->setTextHeightPercentage(0.4f);
184 horizontal_grid_->setBounds(interpolation_type_->getRight() + padding, y_title, grid_width, height_title);
185 vertical_grid_->setBounds(horizontal_grid_->getRight() + padding, y_title, grid_width, height_title);
186
187 horizontal_incrementers_->setBounds(horizontal_grid_->getRight() - height_title, y_title, height_title, height_title);
188 vertical_incrementers_->setBounds(vertical_grid_->getRight() - height_title, y_title, height_title, height_title);
189
191 controls_background_.addLine(interpolation_width);
192 controls_background_.addLine(interpolation_width + grid_width + padding);
193
194 interpolation_type_->redoImage();
195 horizontal_grid_->redoImage();
196 vertical_grid_->redoImage();
197}
198
205bool WaveSourceOverlay::setTimeDomainBounds(Rectangle<int> bounds) {
206 oscillator_->setBounds(bounds);
207 return true;
208}
209
217 frequency_amplitudes_->setBounds(bounds);
218 return true;
219}
220
227bool WaveSourceOverlay::setPhaseBounds(Rectangle<int> bounds) {
228 frequency_phases_->setBounds(bounds);
229 return true;
230}
231
240void WaveSourceOverlay::updateFrequencyDomain(std::complex<float>* frequency_domain) {
241 for (int i = 0; i < vital::WaveFrame::kNumRealComplex; ++i) {
242 std::complex<float> frequency = frequency_domain[i];
243 float amplitude = std::abs(frequency);
244 float phase = kDefaultPhase;
245 if (amplitude)
246 phase = std::arg(frequency) / vital::kPi;
247
248 float adjusted_amplitude = amplitude / vital::WaveFrame::kWaveformSize;
249 frequency_amplitudes_->setScaledY(i, adjusted_amplitude);
250 frequency_phases_->setY(i, phase);
251 }
252}
253
261 for (int i = 0; i < vital::WaveFrame::kNumRealComplex; ++i) {
262 float amplitude = frequency_amplitudes_->scaledYAt(i);
264 float phase = vital::kPi * frequency_phases_->yAt(i);
265 std::complex<float> value = std::polar(amplitude, phase);
267 }
268
272}
273
283void WaveSourceOverlay::valuesChanged(int start, int end, bool mouse_up) {
284 if (current_frame_ == nullptr)
285 return;
286
287 for (int i = start; i <= end; ++i)
288 current_frame_->time_domain[i] = oscillator_->valueAt(i);
289
292
293 notifyChanged(mouse_up);
294}
295
303void WaveSourceOverlay::sliderValueChanged(Slider* moved_slider) {
304 if (wave_source_ == nullptr)
305 return;
306
307 // Grid controls
308 if (moved_slider == horizontal_grid_.get() || moved_slider == vertical_grid_.get()) {
309 oscillator_->setGrid(horizontal_grid_->getValue(), vertical_grid_->getValue());
310 }
311 // Interpolation controls
312 else if (moved_slider == interpolation_type_.get()) {
315 int value = interpolation_type_->getValue();
316 if (value) {
317 style = static_cast<WaveSource::InterpolationStyle>((value + 1) / 2);
318 mode = static_cast<WaveSource::InterpolationMode>((value + 1) % 2);
319 }
320
323
324 notifyChanged(true);
325 }
326}
327
338 if (style == WaveSource::kNone)
339 interpolation_type_->setValue(0, sendNotificationSync);
340 else
341 interpolation_type_->setValue(2 * style + mode - 1, sendNotificationSync);
342}
343
354void WaveSourceOverlay::barsChanged(int start, int end, bool mouse_up) {
356
357 oscillator_->loadWaveform(current_frame_->time_domain);
358 notifyChanged(mouse_up);
359}
@ kWidgetFillFade
Definition skin.h:108
@ kWidgetPrimary1
Definition skin.h:165
@ kWidgetSecondary1
Definition skin.h:168
@ kWidgetSecondary2
Definition skin.h:169
void addSlider(SynthSlider *slider, bool show=true, bool listen=true)
Definition synth_section.cpp:445
virtual void resized() override
Called when the component is resized. Arranges layout of child components.
Definition synth_section.cpp:35
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
void addOpenGlComponent(OpenGlComponent *open_gl_component, bool to_beginning=false)
Definition synth_section.cpp:489
static TextLookAndFeel * instance()
Singleton instance access.
Definition text_look_and_feel.h:106
void setInterpolationMode(InterpolationMode mode)
Sets the interpolation mode for morphing between keyframes.
Definition wave_source.h:69
vital::WaveFrame * getWaveFrame(int index)
Gets a WaveFrame from a specified keyframe index.
Definition wave_source.cpp:47
InterpolationMode
Defines how keyframes should be interpolated.
Definition wave_source.h:31
@ kTime
Interpolate directly in time domain.
Definition wave_source.h:32
void loadFrequencyDomain()
Loads frequency-domain data from the editors back into the current frame.
Definition wave_source_overlay.cpp:260
std::unique_ptr< SynthSlider > horizontal_grid_
SynthSlider for the number of horizontal grid lines in the WaveSourceEditor.
Definition wave_source_overlay.h:232
void updateFrequencyDomain(std::complex< float > *frequency_domain)
Updates the frequency-domain editors with new data.
Definition wave_source_overlay.cpp:240
std::unique_ptr< BarEditor > frequency_phases_
BarEditor for frequency phases.
Definition wave_source_overlay.h:222
static constexpr int kDefaultYGrid
Default number of vertical grid divisions.
Definition wave_source_overlay.h:34
virtual bool setFrequencyAmplitudeBounds(Rectangle< int > bounds) override
Sets the bounds for the frequency amplitude editor.
Definition wave_source_overlay.cpp:216
vital::WaveFrame * current_frame_
Pointer to the currently selected WaveFrame in the WaveSource.
Definition wave_source_overlay.h:207
virtual bool setTimeDomainBounds(Rectangle< int > bounds) override
Sets the bounds for the time-domain editor.
Definition wave_source_overlay.cpp:205
void barsChanged(int start, int end, bool mouse_up) override
Called when values in the BarEditor are changed.
Definition wave_source_overlay.cpp:354
WaveSource * wave_source_
Pointer to the WaveSource being edited.
Definition wave_source_overlay.h:202
void valuesChanged(int start, int end, bool mouse_up) override
Called when values in the WaveSourceEditor are changed.
Definition wave_source_overlay.cpp:283
std::unique_ptr< Component > vertical_incrementers_
Incrementer button set for vertical grid adjustments.
Definition wave_source_overlay.h:247
std::unique_ptr< TextSelector > interpolation_type_
TextSelector for choosing interpolation style and mode.
Definition wave_source_overlay.h:227
static constexpr float kDefaultPhase
Default phase value for frequency phase editor.
Definition wave_source_overlay.h:41
void resized() override
Called when the component is resized.
Definition wave_source_overlay.cpp:116
std::unique_ptr< Component > horizontal_incrementers_
Incrementer button set for horizontal grid adjustments.
Definition wave_source_overlay.h:242
virtual bool setPhaseBounds(Rectangle< int > bounds) override
Sets the bounds for the frequency phase editor.
Definition wave_source_overlay.cpp:227
std::unique_ptr< BarEditor > frequency_amplitudes_
BarEditor for frequency amplitudes.
Definition wave_source_overlay.h:217
static constexpr int kDefaultXGrid
Default number of horizontal grid divisions.
Definition wave_source_overlay.h:29
virtual void frameSelected(WavetableKeyframe *keyframe) override
Called when a keyframe is selected within the Wavetable.
Definition wave_source_overlay.cpp:140
WaveSourceOverlay()
Constructs a new WaveSourceOverlay.
Definition wave_source_overlay.cpp:30
void setInterpolationType(WaveSource::InterpolationStyle style, WaveSource::InterpolationMode mode)
Sets the interpolation type for the WaveSource.
Definition wave_source_overlay.cpp:336
virtual void setEditBounds(Rectangle< int > bounds) override
Sets the bounds for the editable region of this overlay.
Definition wave_source_overlay.cpp:165
void sliderValueChanged(Slider *moved_slider) override
Called when a slider changes value.
Definition wave_source_overlay.cpp:303
std::unique_ptr< WaveSourceEditor > oscillator_
Editor for time-domain waveforms.
Definition wave_source_overlay.h:212
std::unique_ptr< SynthSlider > vertical_grid_
SynthSlider for the number of vertical grid lines in the WaveSourceEditor.
Definition wave_source_overlay.h:237
InterpolationStyle
Defines how interpolation is performed between keyframes.
Definition wavetable_component.h:38
@ kNone
No interpolation, just jumps between keyframes.
Definition wavetable_component.h:39
void setInterpolationStyle(InterpolationStyle type)
Sets the global interpolation style.
Definition wavetable_component.h:209
void addTitle(const std::string &title)
Adds a title string for the next control section.
Definition wavetable_component_overlay.h:94
void addLine(int position)
Adds a vertical line divider at the given position.
Definition wavetable_component_overlay.h:88
void clearTitles()
Clears all control section titles.
Definition wavetable_component_overlay.h:82
void clearLines()
Clears all line divider positions.
Definition wavetable_component_overlay.h:77
A base overlay component for editing and interacting with a wavetable component's parameters.
Definition wavetable_component_overlay.h:22
void setControlsWidth(int width)
Sets the total width for controls in the overlay.
Definition wavetable_component_overlay.h:267
ControlsBackground controls_background_
Definition wavetable_component_overlay.h:300
virtual void setEditBounds(Rectangle< int > bounds)
Sets the editing bounds within which controls and titles are placed.
Definition wavetable_component_overlay.cpp:67
static constexpr float kTitleHeightRatio
Definition wavetable_component_overlay.h:32
int getPadding()
Gets the current padding value.
Definition wavetable_component_overlay.h:248
static constexpr int kMaxGrid
Maximum grid lines used by some overlays.
Definition wavetable_component_overlay.h:25
void notifyChanged(bool mouse_up)
Notifies listeners that a change has occurred to the frame.
Definition wavetable_component_overlay.cpp:86
Represents a single state of a waveform at a specific position in a wavetable.
Definition wavetable_keyframe.h:35
int index()
Gets the index of this keyframe within its owner component.
Definition wavetable_keyframe.cpp:32
WavetableComponent * owner()
Gets the WavetableComponent that owns this keyframe.
Definition wavetable_keyframe.h:152
std::complex< float > frequency_domain[kWaveformSize]
The frequency-domain representation (complex spectrum).
Definition wave_frame.h:125
void toFrequencyDomain()
Converts the currently loaded time-domain data into frequency-domain representation.
Definition wave_frame.cpp:64
static constexpr int kWaveformSize
The size of the waveform (number of samples per frame).
Definition wave_frame.h:21
mono_float time_domain[2 *kWaveformSize]
The time-domain data, extended buffer size for FFT alignment.
Definition wave_frame.h:124
void toTimeDomain()
Converts the currently loaded frequency-domain data into time-domain representation.
Definition wave_frame.cpp:77
static constexpr int kNumRealComplex
The number of real-valued frequency components (half the size + 1).
Definition wave_frame.h:23
void normalize(bool allow_positive_gain=false)
Normalizes the time-domain waveform samples to have a maximum absolute value of 1....
Definition wave_frame.cpp:38
constexpr mono_float kPi
Pi constant.
Definition common.h:36
Declares the TextSelector class and PaintPatternSelector class for selecting text-based options and d...