Vital
Loading...
Searching...
No Matches
oscillator_section.cpp
Go to the documentation of this file.
2
3#include "bar_renderer.h"
5#include "skin.h"
6#include "paths.h"
7#include "fonts.h"
8#include "full_interface.h"
9#include "load_save.h"
10#include "preset_selector.h"
11#include "producers_module.h"
12#include "synth_strings.h"
13#include "synth_button.h"
14#include "synth_oscillator.h"
15#include "synth_gui_interface.h"
16#include "synth_slider.h"
17#include "text_look_and_feel.h"
18#include "text_selector.h"
19#include "wavetable_3d.h"
20#include "tooltipText.h"
21
22namespace {
23 // Internal namespace for static strings, lookup tables, and helper functions.
24 const std::string kSpectralMorphTypes[vital::SynthOscillator::kNumSpectralMorphTypes] = {
25 "---",
26 "VOCODE",
27 "FORM SCALE",
28 "HARM STRETCH",
29 "INHARMONIC",
30 "SMEAR",
31 "RAND AMP",
32 "LOW PASS",
33 "HIGH PASS",
34 "PHASE DISP",
35 "SHEPARD TONE",
36 "TIME SKEW",
37 };
38
39 const std::string kDistortionTypes[vital::SynthOscillator::kNumDistortionTypes] = {
40 "---",
41 "SYNC",
42 "FORMANT",
43 "QUANTIZE",
44 "BEND",
45 "SQUEEZE",
46 "PULSE",
47 "FM <- OSC",
48 "FM <- OSC",
49 "FM <- SAMPLE",
50 "RM <- OSC",
51 "RM <- OSC",
52 "RM <- SAMPLE"
53 };
54
55 const std::string kLanguageNames[] = {
56 "Arabic",
57 "Czech",
58 "Danish",
59 "Dutch",
60 "English (Aus)",
61 "English (UK)",
62 "English (US)",
63 "Filipino",
64 "Finnish",
65 "French (Can)",
66 "French (Fr)",
67 "German",
68 "Greek",
69 "Hindi",
70 "Hungarian",
71 "Indonesian",
72 "Italian",
73 "Japanese",
74 "Korean",
75 "Mandarin Chinese",
76 "Norwegian",
77 "Polish",
78 "Portuguese (Br)",
79 "Portuguese (Po)",
80 "Russian",
81 "Slovak",
82 "Spanish",
83 "Swedish",
84 "Turkish",
85 "Ukrainian",
86 "Vietnamese"
87 };
88
89 const std::string kLanguageCodes[] = {
90 "ar-XA",
91 "cs-CZ",
92 "da-DK",
93 "nl-NL",
94 "en-AU",
95 "en-GB",
96 "en-US",
97 "fil-PH",
98 "fi-FI",
99 "fr-CA",
100 "fr-FR",
101 "de-DE",
102 "el-GR",
103 "hi-IN",
104 "hu-HU",
105 "id-ID",
106 "it-IT",
107 "ja-JP",
108 "ko-KR",
109 "cmn-CN",
110 "nb-NO",
111 "pl-PL",
112 "pt-BR",
113 "pt-PT",
114 "ru-RU",
115 "sk-SK",
116 "es-ES",
117 "sv-SE",
118 "tr-TR",
119 "uk-UA",
120 "vi-VN"
121 };
122
123 const std::string kUrlPrefix = "";
124 const std::string kLanguageUrlQuery = "&language=";
125 const std::string kTokenUrlQuery = "&idToken=";
126 constexpr int kTtwtId = INT_MAX;
127 constexpr int kAddCustomFolderId = INT_MAX - 1;
128 constexpr int kMaxTTWTLength = 100;
129 constexpr int kShowErrorMs = 2000;
130
137 String getDistortionSuffix(int type, int index) {
139 return " " + String(1 + vital::ProducersModule::getFirstModulationIndex(index));
141 return " " + String(1 + vital::ProducersModule::getSecondModulationIndex(index));
142
143 return "";
144 }
145
151 bool isSpectralMenuSeparator(int index) {
152 return index == (vital::SynthOscillator::kNoSpectralMorph + 1);
153 }
154
160 bool isDistortionMenuSeparator(int index) {
162 }
163
170 String getDistortionMenuString(int type, int index) {
171 return String(strings::kPhaseDistortionNames[type]) + getDistortionSuffix(type, index);
172 }
173
180 String getDistortionString(int type, int index) {
181 return String(kDistortionTypes[type]) + getDistortionSuffix(type, index);
182 }
183
189 int getLanguageIndex(const std::string& language) {
190 constexpr int kDefaultIndex = 4;
191
192 for (int i = 0; i < sizeof(kLanguageNames) / sizeof(std::string); ++i) {
193 if (kLanguageCodes[i] == language)
194 return i;
195 }
196
197 return kDefaultIndex;
198 }
199
205 bool isBipolarDistortionType(int distortion_type) {
206 return distortion_type == vital::SynthOscillator::kNone ||
207 distortion_type == vital::SynthOscillator::kSqueeze ||
208 distortion_type == vital::SynthOscillator::kSync ||
209 distortion_type == vital::SynthOscillator::kFormant ||
210 distortion_type == vital::SynthOscillator::kBend;
211 }
212
218 bool isBipolarSpectralMorphType(int morph_type) {
219 return morph_type == vital::SynthOscillator::kNoSpectralMorph ||
220 morph_type == vital::SynthOscillator::kVocode ||
225 }
226} // namespace
227
236class UnisonViewer : public BarRenderer {
237 public:
244 UnisonViewer(int index, const vital::output_map& mono_modulations, const vital::output_map& poly_modulations) :
245 BarRenderer(vital::SynthOscillator::kMaxUnison) {
246 std::string prefix = std::string("osc_") + std::to_string(index + 1);
247 voices_ = { mono_modulations.at(prefix + "_unison_voices"), poly_modulations.at(prefix + "_unison_voices") };
248 detune_ = { mono_modulations.at(prefix + "_unison_detune"), poly_modulations.at(prefix + "_unison_detune") };
249 detune_power_ = { mono_modulations.at(prefix + "_detune_power"), poly_modulations.at(prefix + "_detune_power") };
250
251 voices_slider_ = nullptr;
252 detune_slider_ = nullptr;
253 detune_power_slider_ = nullptr;
254 }
255
263 static inline vital::poly_float getOutputsTotal(std::pair<vital::Output*, vital::Output*> outputs,
264 vital::poly_float default_value, bool animate) {
265 if (!outputs.first->owner->enabled() || !animate)
266 return default_value;
267 return outputs.first->trigger_value + outputs.second->trigger_value;
268 }
269
274 void setVoicesSlider(SynthSlider* slider) { voices_slider_ = slider; }
275
280 void setDetuneSlider(SynthSlider* slider) { detune_slider_ = slider; }
281
286 void setDetunePowerSlider(SynthSlider* slider) { detune_power_slider_ = slider; }
287
293 void render(OpenGlWrapper& open_gl, bool animate) override {
294 static constexpr float kHeightRatio = 0.7f;
295 static constexpr int kMaxUnison = vital::SynthOscillator::kMaxUnison;
296
297 int voices = getOutputsTotal(voices_, voices_slider_->getValue(), animate)[0];
298 voices = std::min(std::max(voices, 1), kMaxUnison);
299 float detune = 0.1f * getOutputsTotal(detune_, detune_slider_->getValue(), animate)[0];
300 float detune_power = getOutputsTotal(detune_power_, detune_power_slider_->getValue(), animate)[0];
301
302 setColor(findColour(Skin::kWidgetPrimary1, true).withMultipliedAlpha(0.5f));
303 setBarWidth(1.0f / getWidth());
304 float percent_active = 1.0f - getHeight() / (2.0f * getWidth());
305
306 for (int i = 0; i < kMaxUnison; ++i) {
307 setBottom(i, -kHeightRatio);
308 setY(i, kHeightRatio);
309 }
310
311 float offset = -1.0f / getWidth();
312 if (voices == 1)
313 setX(0, offset);
314 else {
315 for (int i = 0; i < voices; ++i) {
316 float t = 2.0f * i / (voices - 1.0f) - 1.0f;
317 float center_offset = fabsf(t);
318 float power_scale = vital::futils::powerScale(center_offset, detune_power);
319 if (t < 0.0f)
320 power_scale = -power_scale;
321 setX(i, power_scale * percent_active * detune + offset);
322 }
323 }
324 for (int i = voices; i < kMaxUnison; ++i)
325 setX(i, -2.0f);
326
327 BarRenderer::render(open_gl, animate);
328 }
329
330 private:
331 std::pair<vital::Output*, vital::Output*> voices_;
332 std::pair<vital::Output*, vital::Output*> detune_;
333 std::pair<vital::Output*, vital::Output*> detune_power_;
334
335 SynthSlider* voices_slider_;
336 SynthSlider* detune_slider_;
337 SynthSlider* detune_power_slider_;
338};
339
345 public:
350 InvisibleSlider(String name) : SynthSlider(std::move(name)) { }
351
356 void paint(Graphics& g) override { }
357
362 void drawShadow(Graphics& g) override { }
363};
364
365// Constructor implementation with UI component creation and configuration.
367 int index,
368 const vital::output_map& mono_modulations,
369 const vital::output_map& poly_modulations) :
370 SynthSection(String("OSC ") + String(index + 1)), auth_(auth), index_(index),
371 show_ttwt_error_(false), ttwt_overlay_(Shaders::kRoundedRectangleFragment) {
372 std::string number = std::to_string(index + 1);
373 wavetable_ = std::make_unique<Wavetable3d>(index, mono_modulations, poly_modulations);
374 addOpenGlComponent(wavetable_.get());
375 wavetable_->addListener(this);
376
377 transpose_quantize_button_ = std::make_unique<TransposeQuantizeButton>();
378 addOpenGlComponent(transpose_quantize_button_.get());
379 transpose_quantize_button_->addQuantizeListener(this);
380
381 transpose_ = std::make_unique<SynthSlider>("osc_" + number + "_transpose");
382 addSlider(transpose_.get());
383 transpose_->setSliderStyle(Slider::RotaryHorizontalVerticalDrag);
384 transpose_->setLookAndFeel(TextLookAndFeel::instance());
385 transpose_->setSensitivity(kTransposeMouseSensitivity);
386 transpose_->setTextEntrySizePercent(1.0f, 0.7f);
387 transpose_->setShiftIndexAmount(vital::kNotesPerOctave);
388 transpose_->overrideValue(Skin::kTextComponentOffset, 0.0f);
389 transpose_->setModulationBarRight(false);
390
391 tune_ = std::make_unique<SynthSlider>("osc_" + number + "_tune");
392 addSlider(tune_.get());
393 tune_->setSliderStyle(Slider::RotaryHorizontalVerticalDrag);
394 tune_->setLookAndFeel(TextLookAndFeel::instance());
395 tune_->setBipolar();
396 tune_->setMaxDisplayCharacters(3);
397 tune_->setMaxDecimalPlaces(0);
398 tune_->setTextEntrySizePercent(1.0f, 0.7f);
399 tune_->overrideValue(Skin::kTextComponentOffset, 0.0f);
400
401 unison_detune_ = std::make_unique<SynthSlider>("osc_" + number + "_unison_detune");
402 addSlider(unison_detune_.get());
403 unison_detune_->setSliderStyle(Slider::RotaryHorizontalVerticalDrag);
404 unison_detune_->setLookAndFeel(TextLookAndFeel::instance());
405 unison_detune_->setMaxDisplayCharacters(3);
406 unison_detune_->setMaxDecimalPlaces(0);
407 unison_detune_->setTextEntrySizePercent(1.0f, 0.7f);
408 unison_detune_->overrideValue(Skin::kTextComponentOffset, 0.0f);
409
410 unison_detune_power_ = std::make_unique<InvisibleSlider>("osc_" + number + "_detune_power");
411 addSlider(unison_detune_power_.get());
412 unison_detune_power_->setSliderStyle(Slider::RotaryHorizontalVerticalDrag);
413 unison_detune_power_->setLookAndFeel(CurveLookAndFeel::instance());
414 unison_detune_power_->setPopupPrefix("Unison Detune Power: ");
415 unison_detune_power_->setTextEntrySizePercent(1.0f, 0.7f);
416
417 unison_voices_ = std::make_unique<SynthSlider>("osc_" + number + "_unison_voices");
418 addSlider(unison_voices_.get());
419 unison_voices_->setSliderStyle(Slider::RotaryHorizontalVerticalDrag);
420 unison_voices_->setLookAndFeel(TextLookAndFeel::instance());
421 unison_voices_->setTextEntrySizePercent(1.0f, 0.7f);
422 unison_voices_->overrideValue(Skin::kTextComponentOffset, 0.0f);
423 unison_voices_->setModulationBarRight(false);
424
425 phase_ = std::make_unique<SynthSlider>("osc_" + number + "_phase");
426 addSlider(phase_.get());
427 phase_->setSliderStyle(Slider::RotaryHorizontalVerticalDrag);
428 phase_->setLookAndFeel(TextLookAndFeel::instance());
429 phase_->setTextEntrySizePercent(1.0f, 0.7f);
430 phase_->overrideValue(Skin::kTextComponentOffset, 0.0f);
431 phase_->setMaxDisplayCharacters(3);
432 phase_->setMaxDecimalPlaces(0);
433
434 random_phase_ = std::make_unique<SynthSlider>("osc_" + number + "_random_phase");
435 addSlider(random_phase_.get());
436 random_phase_->setSliderStyle(Slider::RotaryHorizontalVerticalDrag);
437 random_phase_->setLookAndFeel(TextLookAndFeel::instance());
438 random_phase_->setTextEntrySizePercent(1.0f, 0.7f);
439 random_phase_->overrideValue(Skin::kTextComponentOffset, 0.0f);
440 random_phase_->setMaxDisplayCharacters(3);
441 random_phase_->setMaxDecimalPlaces(0);
442
443 distortion_phase_ = std::make_unique<SynthSlider>("osc_" + number + "_distortion_phase");
444 addSlider(distortion_phase_.get());
445 distortion_phase_->setSliderStyle(Slider::LinearBar);
446 distortion_phase_->setVisible(false);
447 distortion_phase_->setBipolar(true);
448 distortion_phase_->setModulationPlacement(BubbleComponent::above);
449
450 level_ = std::make_unique<SynthSlider>("osc_" + number + "_level");
451 addSlider(level_.get());
452 level_->setSliderStyle(Slider::RotaryHorizontalVerticalDrag);
453
454 pan_ = std::make_unique<SynthSlider>("osc_" + number + "_pan");
455 addSlider(pan_.get());
456 pan_->setSliderStyle(Slider::RotaryHorizontalVerticalDrag);
457 pan_->setBipolar();
458
459 distortion_control_name_ = "osc_" + number + "_distortion_type";
460 current_distortion_type_ = 0;
461 distortion_type_text_ = std::make_unique<PlainTextComponent>("Distortion Text", "---");
462 addOpenGlComponent(distortion_type_text_.get());
463
464 spectral_morph_control_name_ = "osc_" + number + "_spectral_morph_type";
465 current_spectral_morph_type_ = 0;
466 spectral_morph_type_text_ = std::make_unique<PlainTextComponent>("Frequency Morph Text", "---");
467 addOpenGlComponent(spectral_morph_type_text_.get());
468
469 quantize_control_name_ = "osc_" + number + "_transpose_quantize";
470
471 distortion_amount_ = std::make_unique<SynthSlider>("osc_" + number + "_distortion_amount");
472 addSlider(distortion_amount_.get());
473 distortion_amount_->setSliderStyle(Slider::RotaryHorizontalVerticalDrag);
474 distortion_amount_->setKnobSizeScale(1.5f);
475 distortion_amount_->setPopupPrefix("Wave Morph: ");
476// Grab the suffix text from your map:
477 auto& tooltips = getTooltips();
478 auto it = tooltips.find("distortion_amount");
479 if (it != tooltips.end()) {
480 distortion_amount_->setPopupSuffix("\n" + it->second); // prefix + value + suffix
481 }
482
483 spectral_morph_amount_ = std::make_unique<SynthSlider>("osc_" + number + "_spectral_morph_amount");
484 addSlider(spectral_morph_amount_.get());
485 spectral_morph_amount_->setSliderStyle(Slider::RotaryHorizontalVerticalDrag);
486 spectral_morph_amount_->setKnobSizeScale(1.5f);
487 spectral_morph_amount_->setPopupPrefix("Spectral Morph: ");
488
489 spectral_morph_type_selector_ = std::make_unique<ShapeButton>("Spectral Morph", Colour(0xff666666),
490 Colour(0xffaaaaaa), Colour(0xff888888));
491 addAndMakeVisible(spectral_morph_type_selector_.get());
492 spectral_morph_type_selector_->addListener(this);
493 spectral_morph_type_selector_->setTriggeredOnMouseDown(true);
494 spectral_morph_type_selector_->setShape(Path(), true, true, true);
495
496 distortion_type_selector_ = std::make_unique<ShapeButton>("Distortion", Colour(0xff666666),
497 Colour(0xffaaaaaa), Colour(0xff888888));
498 addAndMakeVisible(distortion_type_selector_.get());
499 distortion_type_selector_->addListener(this);
500 distortion_type_selector_->setTriggeredOnMouseDown(true);
501 distortion_type_selector_->setShape(Path(), true, true, true);
502
503 wave_frame_ = std::make_unique<SynthSlider>("osc_" + number + "_wave_frame");
504 addSlider(wave_frame_.get());
505 wave_frame_->setSliderStyle(Slider::LinearBarVertical);
506 wave_frame_->setPopupPlacement(BubbleComponent::right);
507 wave_frame_->setMouseWheelMovement(8.0);
508 wave_frame_->setModulationPlacement(BubbleComponent::left);
509 wave_frame_->setExtraModulationTarget(wavetable_.get());
510 wave_frame_->setPopupPrefix("Frame: ");
511
512 destination_selector_ = std::make_unique<ShapeButton>("Destination", Colour(0xff666666),
513 Colour(0xffaaaaaa), Colour(0xff888888));
514
515 destination_control_name_ = "osc_" + number + "_destination";
516 current_destination_ = 0;
517 destination_text_ = std::make_unique<PlainTextComponent>("Destination Text", "---");
518 addOpenGlComponent(destination_text_.get());
519
520 addAndMakeVisible(destination_selector_.get());
521 destination_selector_->addListener(this);
522 destination_selector_->setTriggeredOnMouseDown(true);
523 destination_selector_->setShape(Path(), true, true, true);
524
525 prev_destination_ = std::make_unique<OpenGlShapeButton>("Prev Destination");
526 addAndMakeVisible(prev_destination_.get());
527 addOpenGlComponent(prev_destination_->getGlComponent());
528 prev_destination_->addListener(this);
529 prev_destination_->setShape(Paths::prev());
530
531 next_destination_ = std::make_unique<OpenGlShapeButton>("Next Destination");
532 addAndMakeVisible(next_destination_.get());
533 addOpenGlComponent(next_destination_->getGlComponent());
534 next_destination_->addListener(this);
535 next_destination_->setShape(Paths::next());
536
537 preset_selector_ = std::make_unique<PresetSelector>();
538 addSubSection(preset_selector_.get());
539 preset_selector_->addListener(this);
540 setPresetSelector(preset_selector_.get(), true);
541
542 edit_button_ = std::make_unique<OpenGlShapeButton>("edit");
543 addAndMakeVisible(edit_button_.get());
544 addOpenGlComponent(edit_button_->getGlComponent());
545 edit_button_->addListener(this);
546 edit_button_->setShape(Paths::pencil());
547
548 dimension_button_ = std::make_unique<SynthButton>("osc_" + number + "_dimension");
549 addButton(dimension_button_.get());
550 dimension_button_->setNoBackground();
551 dimension_button_->setShowOnColors(false);
552 dimension_button_->setLookAndFeel(TextLookAndFeel::instance());
553
554 dimension_value_ = std::make_unique<SynthSlider>("osc_" + number + "_view_2d");
555 addSlider(dimension_value_.get());
556 dimension_value_->setVisible(false);
557
558 ttwt_overlay_.setQuad(0, -1.0f, -1.0f, 2.0f, 2.0f);
559 addOpenGlComponent(&ttwt_overlay_);
560 ttwt_overlay_.setVisible(false);
561
562#if !defined(NO_TEXT_ENTRY)
563 ttwt_ = std::make_unique<OpenGlTextEditor>("ttwt");
564 ttwt_->addListener(this);
565 ttwt_->setFont(Fonts::instance()->proportional_light().withPointHeight(16.0f));
566 ttwt_->setMultiLine(false, false);
567 ttwt_->setJustification(Justification::centred);
568 addChildComponent(ttwt_.get());
569 addOpenGlComponent(ttwt_->getImageComponent());
570#endif
571
572 showing_language_menu_ = false;
573 ttwt_language_ = getLanguageIndex(LoadSave::getPreferredTTWTLanguage());
574 ttwt_settings_ = std::make_unique<SynthButton>("Menu");
575 ttwt_settings_->setNoBackground();
576 addChildComponent(ttwt_settings_.get());
577 addOpenGlComponent(ttwt_settings_->getGlComponent());
578 ttwt_settings_->addListener(this);
579 ttwt_settings_->setTriggeredOnMouseDown(true);
580 ttwt_settings_->setText(kLanguageCodes[ttwt_language_]);
581
582 std::string ttwt_error = "Error rendering speech. Check internet connection";
583 ttwt_error_text_ = std::make_unique<PlainTextComponent>("ttwt error", ttwt_error);
584 addOpenGlComponent(ttwt_error_text_.get());
585 ttwt_error_text_->setVisible(false);
586
587 oscillator_on_ = std::make_unique<SynthButton>("osc_" + number + "_on");
588 addButton(oscillator_on_.get());
589 setActivator(oscillator_on_.get());
590
591 wavetable_->setFrameSlider(wave_frame_.get());
592 wavetable_->setSpectralMorphSlider(spectral_morph_amount_.get());
593 wavetable_->setDistortionSlider(distortion_amount_.get());
594 wavetable_->setDistortionPhaseSlider(distortion_phase_.get());
595
597
598 unison_viewer_ = std::make_unique<UnisonViewer>(index, mono_modulations, poly_modulations);
599 addOpenGlComponent(unison_viewer_.get());
600 unison_viewer_->setVoicesSlider(unison_voices_.get());
601 unison_viewer_->setDetuneSlider(unison_detune_.get());
602 unison_viewer_->setDetunePowerSlider(unison_detune_power_.get());
603 unison_viewer_->setInterceptsMouseClicks(false, false);
604
605 prev_spectral_ = std::make_unique<OpenGlShapeButton>("Prev Spectral");
606 addAndMakeVisible(prev_spectral_.get());
607 addOpenGlComponent(prev_spectral_->getGlComponent());
608 prev_spectral_->addListener(this);
609 prev_spectral_->setShape(Paths::prev());
610
611 next_spectral_ = std::make_unique<OpenGlShapeButton>("Next Spectral");
612 addAndMakeVisible(next_spectral_.get());
613 addOpenGlComponent(next_spectral_->getGlComponent());
614 next_spectral_->addListener(this);
615 next_spectral_->setShape(Paths::next());
616
617 prev_distortion_ = std::make_unique<OpenGlShapeButton>("Prev Distortion");
618 addAndMakeVisible(prev_distortion_.get());
619 addOpenGlComponent(prev_distortion_->getGlComponent());
620 prev_distortion_->addListener(this);
621 prev_distortion_->setShape(Paths::prev());
622
623 next_distortion_ = std::make_unique<OpenGlShapeButton>("Next Distortion");
624 addAndMakeVisible(next_distortion_.get());
625 addOpenGlComponent(next_distortion_->getGlComponent());
626 next_distortion_->addListener(this);
627 next_distortion_->setShape(Paths::next());
628}
629
631
632// Applies skin values to the wavetable display.
633void OscillatorSection::setSkinValues(const Skin& skin, bool top_level) {
634 SynthSection::setSkinValues(skin, top_level);
635 float horizontal_angle = skin.getValue(Skin::kWavetableHorizontalAngle);
636 float vertical_angle = skin.getValue(Skin::kWavetableVerticalAngle);
637 float draw_width = skin.getValue(Skin::kWavetableDrawWidth);
638 float wave_height = skin.getValue(Skin::kWavetableWaveHeight);
639 float y_offset = skin.getValue(Skin::kWavetableYOffset);
640 wavetable_->setViewSettings(horizontal_angle, vertical_angle, draw_width, wave_height, y_offset);
641}
642
643// Paints section background, including text editors and labels.
645 if (getWidth() == 0)
646 return;
647
648 if (ttwt_) {
649 ttwt_->setColour(CaretComponent::caretColourId, findColour(Skin::kTextEditorCaret, true));
650 ttwt_->setColour(TextEditor::textColourId, findColour(Skin::kBodyText, true));
651 ttwt_->setColour(TextEditor::highlightedTextColourId, findColour(Skin::kBodyText, true));
652 ttwt_->setColour(TextEditor::highlightColourId, findColour(Skin::kTextEditorSelection, true));
653 Colour empty_color = findColour(Skin::kBodyText, true);
654 empty_color = empty_color.withAlpha(0.5f * empty_color.getFloatAlpha());
655 ttwt_->setTextToShowWhenEmpty(TRANS("Text to wavetable"), empty_color);
656 }
657
660
662 paintBorder(g);
663
664 int title_width = findValue(Skin::kTitleWidth);
665 setLabelFont(g);
666 drawLabelConnectionForComponents(g, level_.get(), pan_.get());
667 drawLabelForComponent(g, TRANS("PAN"), pan_.get());
668 drawLabelForComponent(g, TRANS("LEVEL"), level_.get());
669
670 int widget_margin = findValue(Skin::kWidgetMargin);
671 int level_pan_x = title_width;
672 int level_pan_width = getWidth() * kSectionWidthRatio;
673 int knob_section_height = getKnobSectionHeight();
674 int top_row_width = level_pan_width - 2 * widget_margin;
675 int section2_x = getWidth() - 2 * top_row_width - 2 * widget_margin;
676 int top_row_y = widget_margin;
677 int top_row_height = level_->getY() - top_row_y;
678 int phase_x = section2_x + top_row_width + widget_margin;
679 int unison_x = section2_x;
680
681 g.setColour(findColour(Skin::kTextComponentBackground, true));
682 int label_rounding = findValue(Skin::kLabelBackgroundRounding);
683 int morph_y = getHeight() - knob_section_height + widget_margin;
684 Rectangle<int> spectral_normal_bounds(spectral_morph_amount_->getX(), morph_y,
685 spectral_morph_amount_->getWidth(), knob_section_height - 2 * widget_margin);
686 g.fillRoundedRectangle(getLabelBackgroundBounds(spectral_normal_bounds, false).toFloat(), label_rounding);
687 Rectangle<int> distortion_normal_bounds(distortion_amount_->getX(), morph_y,
688 distortion_amount_->getWidth(), knob_section_height - 2 * widget_margin);
689 g.fillRoundedRectangle(getLabelBackgroundBounds(distortion_normal_bounds, false).toFloat(), label_rounding);
690 g.fillRoundedRectangle(destination_selector_->getBounds().toFloat(), label_rounding);
691
693
694 paintJointControl(g, level_pan_x + widget_margin, top_row_y, top_row_width, top_row_height, "PITCH");
695 paintJointControl(g, unison_x, top_row_y, top_row_width, top_row_height, "UNISON");
696 paintJointControl(g, phase_x, top_row_y, top_row_width, top_row_height, "PHASE");
697 wavetable_->setDirty();
698}
699
700// Handles layout and positions all child components.
702 if (getWidth() <= 0 || getHeight() <= 0)
703 return;
704
706
707 preset_selector_->setColour(Skin::kIconButtonOff, findColour(Skin::kUiButton, true));
708 preset_selector_->setColour(Skin::kIconButtonOffHover, findColour(Skin::kUiButtonHover, true));
709 preset_selector_->setColour(Skin::kIconButtonOffPressed, findColour(Skin::kUiButtonPressed, true));
710 dimension_button_->setColour(Skin::kIconButtonOff, findColour(Skin::kUiButton, true));
711 dimension_button_->setColour(Skin::kIconButtonOffHover, findColour(Skin::kUiButtonHover, true));
712 dimension_button_->setColour(Skin::kIconButtonOffPressed, findColour(Skin::kUiButtonPressed, true));
713 edit_button_->setColour(Skin::kIconButtonOff, findColour(Skin::kUiButton, true));
714 edit_button_->setColour(Skin::kIconButtonOffHover, findColour(Skin::kUiButtonHover, true));
715 edit_button_->setColour(Skin::kIconButtonOffPressed, findColour(Skin::kUiButtonPressed, true));
716
717 int label_height = findValue(Skin::kLabelBackgroundHeight);
718 float label_text_height = findValue(Skin::kLabelHeight);
719 Colour body_text = findColour(Skin::kBodyText, true);
720 destination_text_->setColor(body_text);
721 spectral_morph_type_text_->setColor(body_text);
722 distortion_type_text_->setColor(body_text);
723
724 int title_width = getTitleWidth();
725 int widget_margin = getWidgetMargin();
726 int text_height = findValue(Skin::kTextButtonHeight);
727 int slider_width = getSliderWidth();
728
729 int knob_section_height = getKnobSectionHeight();
730 int slider_overlap = getSliderOverlap();
731 int overlap_with_space = getSliderOverlapWithSpace();
732 int wave_section_height = getHeight() - 2 * widget_margin;
733 if (distortion_phase_->isVisible())
734 wave_section_height -= slider_width - slider_overlap - overlap_with_space;
735
736 int level_pan_x = title_width;
737 int level_pan_width = getWidth() * kSectionWidthRatio;
738 int top_row_width = level_pan_width - 2 * widget_margin;
739 int knob_y = getHeight() - label_height - widget_margin - knob_section_height;
740 int big_knob_height = getHeight() - knob_y;
741 placeKnobsInArea(Rectangle<int>(level_pan_x, knob_y, level_pan_width, knob_section_height),
742 { level_.get(), pan_.get() });
743
744 int section2_x = getWidth() - 2 * top_row_width - 2 * widget_margin;
745 int wave_frame_x = section2_x - slider_width + overlap_with_space;
746 int wavetable_x = level_pan_width + level_pan_x;
747 int wavetable_width = wave_frame_x - wavetable_x + overlap_with_space;
748
749 wavetable_->setBounds(wavetable_x, widget_margin, wavetable_width, wave_section_height);
750 preset_selector_->setBounds(wavetable_x, widget_margin, wavetable_width, title_width - 2 * widget_margin);
751 dimension_button_->setBounds(wavetable_x, widget_margin + wave_section_height - text_height,
752 text_height, text_height);
753
754 int wave_frame_height = wave_section_height + 2 * widget_margin;
755 wave_frame_->setBounds(wave_frame_x, 0, slider_width, wave_frame_height);
756 int edit_x = wavetable_->getRight() - text_height;
757 edit_button_->setBounds(edit_x, widget_margin + wave_section_height - text_height, text_height, text_height);
758
759 int top_row_y = widget_margin;
760 int text_section_height = knob_y - widget_margin;
761 placeJointControls(title_width + widget_margin, top_row_y, level_pan_width - 2 * widget_margin, text_section_height,
762 transpose_.get(), tune_.get(), transpose_quantize_button_.get());
763
764 int section2_width = getWidth() - section2_x;
765 int unison_x = section2_x;
766 placeJointControls(unison_x, top_row_y, top_row_width, text_section_height,
767 unison_voices_.get(), unison_detune_.get(), unison_detune_power_.get());
768 unison_viewer_->setBounds(unison_detune_power_->getBounds());
769
770 int phase_x = unison_x + top_row_width + widget_margin;
771 placeJointControls(phase_x, top_row_y, top_row_width, text_section_height,
772 phase_.get(), random_phase_.get(), nullptr);
773
774 placeKnobsInArea(Rectangle<int>(section2_x - widget_margin, knob_y, section2_width + widget_margin, big_knob_height),
775 { spectral_morph_amount_.get(), distortion_amount_.get() });
776
777 int morph_y = getHeight() - knob_section_height + widget_margin;
778 Rectangle<int> spectral_normal_bounds(spectral_morph_amount_->getX(), morph_y,
779 spectral_morph_amount_->getWidth(), knob_section_height - 2 * widget_margin);
780 Rectangle<int> spectral_label_bounds = getLabelBackgroundBounds(spectral_normal_bounds);
781 int browse_width = spectral_label_bounds.getHeight();
782 int browse_y = spectral_label_bounds.getY();
783 prev_spectral_->setBounds(spectral_morph_amount_->getX(), browse_y, browse_width, browse_width);
784 next_spectral_->setBounds(spectral_morph_amount_->getRight() - browse_width, browse_y,
785 browse_width, browse_width);
786
787 prev_distortion_->setBounds(distortion_amount_->getX(), browse_y, browse_width, browse_width);
788 next_distortion_->setBounds(distortion_amount_->getRight() - browse_width, browse_y,
789 browse_width, browse_width);
790
791 spectral_morph_type_text_->setBounds(spectral_label_bounds);
792 spectral_morph_type_text_->setTextSize(label_text_height);
793 int spectral_menu_x = prev_spectral_->getRight();
794 spectral_morph_type_selector_->setBounds(spectral_menu_x, prev_spectral_->getY(),
795 next_spectral_->getX() - spectral_menu_x, prev_spectral_->getHeight());
796
797 Rectangle<int> distortion_normal_bounds(distortion_amount_->getX(), morph_y,
798 distortion_amount_->getWidth(), knob_section_height - 2 * widget_margin);
799 distortion_type_text_->setBounds(getLabelBackgroundBounds(distortion_normal_bounds));
800 distortion_type_text_->setTextSize(label_text_height);
801 int distortion_menu_x = prev_distortion_->getRight();
802 distortion_type_selector_->setBounds(distortion_menu_x, prev_distortion_->getY(),
803 next_distortion_->getX() - distortion_menu_x, prev_distortion_->getHeight());
804
805 distortion_phase_->setBounds(wavetable_->getX() - widget_margin,
806 wavetable_->getBottom() - slider_overlap + widget_margin,
807 wavetable_->getWidth() + 2 * widget_margin, slider_width);
808
809 int destination_x = level_pan_x + widget_margin;
810 int destination_y = getHeight() - label_height - widget_margin;
811 destination_selector_->setBounds(destination_x, destination_y, top_row_width, label_height);
812 destination_text_->setBounds(destination_selector_->getBounds());
813 destination_text_->setTextSize(label_text_height);
814
815 prev_destination_->setBounds(destination_x, destination_y, browse_width, browse_width);
816 next_destination_->setBounds(destination_x + top_row_width - browse_width, destination_y,
817 browse_width, browse_width);
818
820 ttwt_overlay_.setBounds(wavetable_->getBounds());
821 ttwt_overlay_.setColor(findColour(Skin::kOverlayScreen, true));
822
823 if (ttwt_) {
824 float ttwt_height = title_width;
825 int settings_width = ttwt_height * 2.0f;
826 int ttwt_y = (wavetable_->getHeight() - ttwt_height) / 2;
827 int ttwt_x = wavetable_->getX() + widget_margin;
828 int ttwt_width = wavetable_->getWidth() - 2 * widget_margin;
829 ttwt_->setBounds(ttwt_x, ttwt_y, ttwt_width, ttwt_height);
830 ttwt_->setFont(Fonts::instance()->proportional_light().withPointHeight(ttwt_height * 0.6f));
831 ttwt_settings_->setBounds(ttwt_->getRight() - settings_width, ttwt_->getBottom(), settings_width, ttwt_height / 2);
832
833 ttwt_error_text_->setTextSize(label_text_height);
834 ttwt_error_text_->setBounds(ttwt_->getBounds());
835 ttwt_error_text_->setColor(body_text);
836 }
837}
838
839// Handles user interaction with buttons such as type selectors, navigation, etc.
840void OscillatorSection::buttonClicked(Button* clicked_button) {
841 if (clicked_button == edit_button_.get()) {
842 FullInterface* parent = findParentComponentOfClass<FullInterface>();
843 if (parent)
844 parent->showWavetableEditSection(index_);
845 }
846 else if (clicked_button == spectral_morph_type_selector_.get()) {
847 PopupItems options;
848
849 for (int i = 0; i < vital::SynthOscillator::kNumSpectralMorphTypes; ++i) {
850 if (isSpectralMenuSeparator(i))
851 options.addItem(-1, "");
852
854 }
855
856 Point<int> position(spectral_morph_type_selector_->getX(), spectral_morph_type_selector_->getBottom());
857 showPopupSelector(this, position, options, [=](int selection) { setSpectralMorphSelected(selection); });
858 }
859 else if (clicked_button == distortion_type_selector_.get()) {
860 PopupItems options;
861
862 for (int i = 0; i < vital::SynthOscillator::kNumDistortionTypes; ++i) {
863 if (isDistortionMenuSeparator(i))
864 options.addItem(-1, "");
865
866 options.addItem(i, getDistortionMenuString(i, index_).toStdString());
867 }
868
869 Point<int> position(distortion_type_selector_->getX(), distortion_type_selector_->getBottom());
870 showPopupSelector(this, position, options, [=](int selection) { setDistortionSelected(selection); });
871 }
872 else if (clicked_button == destination_selector_.get()) {
873 PopupItems options;
874
875 int num_source_destinations = vital::constants::kNumSourceDestinations;
876 for (int i = 0; i < num_source_destinations; ++i)
878
879 Point<int> position(destination_selector_->getX(), destination_selector_->getBottom());
880 showPopupSelector(this, position, options, [=](int selection) { setDestinationSelected(selection); });
881 }
882 else if (clicked_button == ttwt_settings_.get())
883 showTtwtSettings();
884 else if (clicked_button == dimension_button_.get()) {
885 int render_type = (wavetable_->getRenderType() + Wavetable3d::kNumRenderTypes - 1) % Wavetable3d::kNumRenderTypes;
886 dimension_button_->setText(strings::kWavetableDimensionNames[render_type]);
887 dimension_value_->setValue(render_type, sendNotificationSync);
888 wavetable_->setRenderType(static_cast<Wavetable3d::RenderType>(render_type));
889 }
890 else if (clicked_button == prev_destination_.get()) {
891 int new_destination = current_destination_ - 1 + vital::constants::kNumSourceDestinations;
893 }
894 else if (clicked_button == next_destination_.get()) {
895 int new_destination = (current_destination_ + 1) % vital::constants::kNumSourceDestinations;
896 setDestinationSelected(new_destination);
897 }
898 else if (clicked_button == prev_spectral_.get()) {
899 int new_morph_type = current_spectral_morph_type_ - 1 + vital::SynthOscillator::kNumSpectralMorphTypes;
901 }
902 else if (clicked_button == next_spectral_.get()) {
903 int new_morph_type = (current_spectral_morph_type_ + 1) % vital::SynthOscillator::kNumSpectralMorphTypes;
904 setSpectralMorphSelected(new_morph_type);
905 }
906 else if (clicked_button == prev_distortion_.get()) {
907 int new_distortion_type = current_distortion_type_ - 1 + vital::SynthOscillator::kNumDistortionTypes;
909 }
910 else if (clicked_button == next_distortion_.get()) {
911 int new_distortion_type = (current_distortion_type_ + 1) % vital::SynthOscillator::kNumDistortionTypes;
912 setDistortionSelected(new_distortion_type);
913 }
914 else
915 SynthSection::buttonClicked(clicked_button);
916}
917
918// Updates local state from given control values and configures UI elements.
921 current_spectral_morph_type_ = controls[spectral_morph_control_name_]->value();
922 current_distortion_type_ = controls[distortion_control_name_]->value();
923 current_destination_ = controls[destination_control_name_]->value();
924 transpose_quantize_button_->setValue(static_cast<int>(controls[quantize_control_name_]->value()));
925 setupSpectralMorph();
926 setupDistortion();
927 setupDestination();
929
930 setDistortionPhaseVisible(vital::SynthOscillator::usesDistortionPhase(type));
931
932 wavetable_->setSpectralMorphType(current_spectral_morph_type_);
933 wavetable_->setDistortionType(current_distortion_type_);
934 int render_type = dimension_value_->getValue();
935 dimension_button_->setText(strings::kWavetableDimensionNames[render_type]);
936 wavetable_->setRenderType(static_cast<Wavetable3d::RenderType>(render_type));
937}
938
939// Handles "Enter" pressed in TTWT text editor, attempts to convert text to wavetable.
941 String text = text_editor.getText();
942 text = text.trim();
943 show_ttwt_error_ = false;
944 if (!text.isEmpty()) {
945 std::string error = loadWavetableFromText(text);
946 show_ttwt_error_ = !error.empty();
947 if (show_ttwt_error_) {
948 ttwt_error_text_->setText(error);
949 ttwt_error_text_->redrawImage(true);
950 ttwt_error_text_->setVisible(true);
951 startTimer(kShowErrorMs);
952 }
953 }
954
955 ttwt_->clear();
956 ttwt_overlay_.setVisible(show_ttwt_error_);
957 ttwt_->setVisible(false);
958 ttwt_settings_->setVisible(false);
959}
960
961// Handles focus loss in TTWT text editor.
962void OscillatorSection::textEditorFocusLost(TextEditor& text_editor) {
963 if (showing_language_menu_)
964 return;
965
966 ttwt_overlay_.setVisible(show_ttwt_error_);
967 ttwt_->setVisible(false);
968 ttwt_settings_->setVisible(false);
969}
970
971// Used to hide error messages after a delay.
973 show_ttwt_error_ = false;
974 ttwt_error_text_->setVisible(false);
975 ttwt_overlay_.setVisible(false);
976 stopTimer();
977}
978
979// Sets the active state for all relevant controls.
981 wavetable_->setActive(active);
983 spectral_morph_amount_->setActive(active && current_spectral_morph_type_ != vital::SynthOscillator::kNoSpectralMorph);
984 distortion_amount_->setActive(active && current_distortion_type_ != vital::SynthOscillator::kNone);
985}
986
987// Sets the displayed name in the preset selector.
988void OscillatorSection::setName(String name) {
989 preset_selector_->setText(name);
990}
991
992// Shows TTWT language settings.
993void OscillatorSection::showTtwtSettings() {
994 showing_language_menu_ = true;
995 PopupItems options;
996
997 for (int i = 0; i < sizeof(kLanguageNames) / sizeof(std::string); ++i)
998 options.addItem(i, kLanguageNames[i]);
999
1000 Point<int> position(ttwt_settings_->getX(), ttwt_settings_->getBottom());
1001 showPopupSelector(this, position, options, [=](int selection) { setLanguage(selection); });
1002}
1003
1004// Loads a wavetable by sending text to a web service (TTWT).
1005std::string OscillatorSection::loadWavetableFromText(const String& text) {
1006 String clamped_text = text.substring(0, kMaxTTWTLength);
1007 String language_query = String(kLanguageUrlQuery) + URL::addEscapeChars(kLanguageCodes[ttwt_language_], true);
1008 std::string token = auth_->token();
1009 String token_query = String(kTokenUrlQuery) + URL::addEscapeChars(token, true);
1010 URL ttwt_url(String(kUrlPrefix) + URL::addEscapeChars(clamped_text, true) + language_query + token_query);
1011
1012 try {
1013 String result = ttwt_url.readEntireTextStream(false);
1014 json data = json::parse(result.toStdString());
1015
1016 if (data.count("error"))
1017 return data["error"];
1018
1019 std::string hex_encoded_buffer = data["buffer"];
1020 MemoryBlock audio_memory;
1021 audio_memory.loadFromHexString(hex_encoded_buffer);
1022 MemoryInputStream* audio_stream = new MemoryInputStream(audio_memory, false);
1023
1024 bool succeeded = loadAudioAsWavetable("TTWT", audio_stream, WavetableCreator::kTtwt);
1025 if (succeeded)
1026 return "";
1027 return "Error converting speech to wavetable.";
1028 }
1029 catch (const std::exception& e) {
1030 return "Error rendering speech. Check internet connection";
1031 }
1032}
1033
1035 return wave_frame_.get();
1036}
1037
1038// Updates the distortion selection and notifies listeners.
1040 current_distortion_type_ = selection;
1041 wavetable_->setDistortionType(selection);
1043 setDistortionPhaseVisible(vital::SynthOscillator::usesDistortionPhase(type));
1044 notifyDistortionTypeChange();
1045}
1046
1047// Updates the spectral morph selection and notifies listeners.
1049 current_spectral_morph_type_ = selection;
1050 wavetable_->setSpectralMorphType(selection);
1051 notifySpectralMorphTypeChange();
1052}
1053
1054// Updates the destination routing and notifies listeners.
1056 current_destination_ = selection;
1057 notifyDestinationChange();
1058}
1059
1060// Toggles filter routing.
1061void OscillatorSection::toggleFilterInput(int filter_index, bool on) {
1062 vital::constants::SourceDestination current_destination = (vital::constants::SourceDestination)current_destination_;
1063 if (filter_index == 0)
1064 current_destination_ = vital::constants::toggleFilter1(current_destination, on);
1065 else
1066 current_destination_ = vital::constants::toggleFilter2(current_destination, on);
1067 notifyDestinationChange();
1068}
1069
1070// Loads the browser state from the parent component.
1072 FullInterface* parent = findParentComponentOfClass<FullInterface>();
1073 if (parent)
1074 preset_selector_->setText(parent->getWavetableName(index_));
1075}
1076
1077// Sets the currently selected index (no implementation details given).
1079 FullInterface* parent = findParentComponentOfClass<FullInterface>();
1080 if (parent == nullptr)
1081 return;
1082}
1083
1084// Sets the language for TTWT and updates preferences.
1086 ttwt_language_ = index;
1087 LoadSave::savePreferredTTWTLanguage(kLanguageCodes[ttwt_language_]);
1088 showing_language_menu_ = false;
1089 if (ttwt_)
1090 ttwt_->grabKeyboardFocus();
1091 ttwt_settings_->setToggleState(false, dontSendNotification);
1092 ttwt_settings_->setText(kLanguageCodes[ttwt_language_]);
1093}
1094
1095// Handles cancellation of language selection.
1097 showing_language_menu_ = false;
1098 if (ttwt_)
1099 ttwt_->grabKeyboardFocus();
1100 ttwt_settings_->setToggleState(false, dontSendNotification);
1101}
1102
1103// Loads the previous wavetable file.
1107 if (wavetable_file.exists())
1108 loadFile(wavetable_file);
1109
1110 updatePopupBrowser(this);
1111}
1112
1113// Loads the next wavetable file.
1117 if (wavetable_file.exists())
1118 loadFile(wavetable_file);
1119
1120 updatePopupBrowser(this);
1121}
1122
1123// Opens a popup browser on text click.
1124void OscillatorSection::textMouseDown(const MouseEvent& e) {
1125 static constexpr int kBrowserWidth = 600;
1126 static constexpr int kBrowserHeight = 400;
1127 Rectangle<int> bounds(unison_voices_->getX(), preset_selector_->getY(),
1128 kBrowserWidth * size_ratio_, kBrowserHeight * size_ratio_);
1129 bounds = getLocalArea(this, bounds);
1132}
1133
1134// Updates transpose quantization state.
1136 int value = transpose_quantize_button_->getValue();
1137 SynthGuiInterface* parent = findParentComponentOfClass<SynthGuiInterface>();
1138 if (parent)
1139 parent->getSynth()->valueChangedInternal(quantize_control_name_, value);
1140}
1141
1142// Resets distortion type if it's a modulation-based type.
1144 if (vital::SynthOscillator::isFirstModulation(current_distortion_type_) ||
1145 vital::SynthOscillator::isSecondModulation(current_distortion_type_)) {
1146 current_distortion_type_ = vital::SynthOscillator::kNone;
1147 notifyDistortionTypeChange();
1148 }
1149}
1150
1151// Loads audio data as a wavetable.
1152bool OscillatorSection::loadAudioAsWavetable(String name, InputStream* audio_stream,
1154 preset_selector_->setText(name);
1155
1156 FullInterface* parent = findParentComponentOfClass<FullInterface>();
1157 if (parent == nullptr) {
1158 delete audio_stream;
1159 return false;
1160 }
1161
1162 wavetable_->setLoadingWavetable(true);
1163 bool success = parent->loadAudioAsWavetable(index_, name, audio_stream, style);
1164 wavetable_->setLoadingWavetable(false);
1165 wavetable_->repaintBackground();
1166 return success;
1167}
1168
1169// Loads wavetable from JSON data.
1171 FullInterface* parent = findParentComponentOfClass<FullInterface>();
1172 if (parent == nullptr)
1173 return;
1174
1175 wavetable_->setLoadingWavetable(true);
1176 parent->loadWavetable(index_, wavetable_data);
1177 wavetable_->setLoadingWavetable(false);
1178 std::string name = wavetable_data["name"];
1179 preset_selector_->setText(name);
1180}
1181
1182// Loads the default wavetable.
1184 FullInterface* parent = findParentComponentOfClass<FullInterface>();
1185 wavetable_->setLoadingWavetable(true);
1186 if (parent)
1187 parent->loadDefaultWavetable(index_);
1188 wavetable_->setLoadingWavetable(false);
1189
1190 preset_selector_->setText("Init");
1191}
1192
1193// Resynthesizes the current source to a wavetable.
1195 FullInterface* parent = findParentComponentOfClass<FullInterface>();
1196 wavetable_->setLoadingWavetable(true);
1197 if (parent)
1198 parent->resynthesizeToWavetable(index_);
1199 wavetable_->setLoadingWavetable(false);
1200}
1201
1202// Initiates text-to-wavetable input mode.
1204 if (auth_)
1205 auth_->refreshToken();
1206
1207 ttwt_settings_->setColour(Skin::kIconButtonOff, findColour(Skin::kWidgetPrimary1, true));
1208 ttwt_overlay_.setVisible(true);
1209 ttwt_->setVisible(true);
1210 ttwt_settings_->setVisible(true);
1211 ttwt_->resized();
1212 ttwt_->grabKeyboardFocus();
1213}
1214
1215// Saves the current wavetable to disk.
1217 FullInterface* parent = findParentComponentOfClass<FullInterface>();
1218 if (parent)
1219 parent->saveWavetable(index_);
1220}
1221
1222// Loads a wavetable from a file.
1223void OscillatorSection::loadFile(const File& wavetable_file) {
1224 FullInterface* parent = findParentComponentOfClass<FullInterface>();
1225 if (parent == nullptr)
1226 return;
1227
1228 current_file_ = wavetable_file;
1229 if (wavetable_file.getFileExtension() == String(".") + vital::kWavetableExtension) {
1230 wavetable_->setLoadingWavetable(true);
1231 parent->loadWavetableFile(index_, wavetable_file);
1232 wavetable_->setLoadingWavetable(false);
1233 preset_selector_->setText(wavetable_file.getFileNameWithoutExtension());
1234 wavetable_->repaintBackground();
1235 }
1236 else {
1237 FileInputStream* input_stream = new FileInputStream(wavetable_file);
1238 loadAudioAsWavetable(wavetable_file.getFileNameWithoutExtension(), input_stream,
1240 }
1241}
1242
1243// Returns relative coordinates of the wavetable area.
1245 Rectangle<int> wavetable_bounds = wavetable_->getBounds();
1246 float width_ratio = 1.0f / getWidth();
1247 float height_ratio = 1.0f / getHeight();
1248 return Rectangle<float>(wavetable_bounds.getX() * width_ratio, wavetable_bounds.getY() * height_ratio,
1249 wavetable_bounds.getWidth() * width_ratio, wavetable_bounds.getHeight() * height_ratio);
1250}
1251
1252// Configures spectral morph parameters and UI.
1253void OscillatorSection::setupSpectralMorph() {
1254 bool bipolar = isBipolarSpectralMorphType(current_spectral_morph_type_);
1255 spectral_morph_amount_->setBipolar(bipolar);
1256 spectral_morph_amount_->setDoubleClickReturnValue(true, bipolar ? 0.5f : 0.0f);
1257 spectral_morph_amount_->setActive(isActive() &&
1258 current_spectral_morph_type_ != vital::SynthOscillator::kNoSpectralMorph);
1259 spectral_morph_amount_->redoImage();
1260 spectral_morph_type_text_->setText(kSpectralMorphTypes[current_spectral_morph_type_]);
1261}
1262
1263// Configures distortion parameters and UI.
1264void OscillatorSection::setupDistortion() {
1265 bool bipolar = isBipolarDistortionType(current_distortion_type_);
1266 distortion_amount_->setBipolar(bipolar);
1267 distortion_amount_->setDoubleClickReturnValue(true, bipolar ? 0.5f : 0.0f);
1268 distortion_amount_->setActive(isActive() && current_distortion_type_ != vital::SynthOscillator::kNone);
1269 distortion_amount_->redoImage();
1270 distortion_type_text_->setText(getDistortionString(current_distortion_type_, index_));
1271}
1272
1273// Configures destination parameters and notifies listeners.
1274void OscillatorSection::setupDestination() {
1275 for (Listener* listener : listeners_)
1276 listener->oscillatorDestinationChanged(this, current_destination_);
1277
1278 destination_text_->setText(strings::kDestinationNames[current_destination_]);
1279}
1280
1281// Shows or hides the distortion phase slider and updates layout.
1282void OscillatorSection::setDistortionPhaseVisible(bool visible) {
1283 if (visible == distortion_phase_->isVisible())
1284 return;
1285 distortion_phase_->setVisible(visible);
1286 resized();
1288}
1289
1290// Notifies parent of spectral morph type change.
1291void OscillatorSection::notifySpectralMorphTypeChange() {
1292 setupSpectralMorph();
1293
1294 SynthGuiInterface* parent = findParentComponentOfClass<SynthGuiInterface>();
1295 if (parent)
1296 parent->getSynth()->valueChangedInternal(spectral_morph_control_name_, current_spectral_morph_type_);
1297}
1298
1299// Notifies parent and listeners of distortion type change.
1300void OscillatorSection::notifyDistortionTypeChange() {
1301 setupDistortion();
1302
1303 for (Listener* listener : listeners_)
1304 listener->distortionTypeChanged(this, current_distortion_type_);
1305
1306 SynthGuiInterface* parent = findParentComponentOfClass<SynthGuiInterface>();
1307 if (parent)
1308 parent->getSynth()->valueChangedInternal(distortion_control_name_, current_distortion_type_);
1309}
1310
1311// Notifies parent and listeners of destination change.
1312void OscillatorSection::notifyDestinationChange() {
1313 setupDestination();
1314
1315 SynthGuiInterface* parent = findParentComponentOfClass<SynthGuiInterface>();
1316 if (parent)
1317 parent->getSynth()->valueChangedInternal(destination_control_name_, current_destination_);
1318}
A no-op stub implementation used when authentication is disabled.
Definition authentication.h:163
void refreshToken()
No-op token refresh method.
Definition authentication.h:185
std::string token()
Returns an empty token string.
Definition authentication.h:174
A renderer for drawing a series of bars using OpenGL.
Definition bar_renderer.h:18
void setColor(const Colour &color)
Sets the color of the bars.
Definition bar_renderer.h:76
force_inline void setX(int index, float val)
Sets the x-position for all vertices of a specific bar.
Definition bar_renderer.h:141
force_inline void setBottom(int index, float val)
Sets the bottom y-position of a specific bar.
Definition bar_renderer.h:165
void setBarWidth(float bar_width)
Sets the relative width of each bar.
Definition bar_renderer.h:94
virtual void render(OpenGlWrapper &open_gl, bool animate) override
Renders the bars using the current OpenGL context.
Definition bar_renderer.cpp:149
force_inline void setY(int index, float val)
Sets the top y-position of a specific bar.
Definition bar_renderer.h:154
static CurveLookAndFeel * instance()
Gets the singleton instance of CurveLookAndFeel.
Definition curve_look_and_feel.h:52
static Fonts * instance()
Gets the singleton instance of the Fonts class.
Definition fonts.h:52
The main GUI container for the entire synthesizer interface.
Definition full_interface.h:61
std::string getWavetableName(int index)
Gets the current wavetable name for a given oscillator.
Definition full_interface.cpp:788
bool loadAudioAsWavetable(int index, const String &name, InputStream *audio_stream, WavetableCreator::AudioFileLoadStyle style)
Loads an audio file as a wavetable into the given oscillator editor.
Definition full_interface.cpp:863
void resynthesizeToWavetable(int index)
Performs resynthesis of the current wavetable for the given oscillator.
Definition full_interface.cpp:830
void loadDefaultWavetable(int index)
Loads a default wavetable into the given oscillator editor.
Definition full_interface.cpp:825
void saveWavetable(int index)
Opens a save dialog to save the current wavetable of an oscillator.
Definition full_interface.cpp:835
void showWavetableEditSection(int index)
Shows the wavetable edit section for a given oscillator index.
Definition full_interface.cpp:763
void loadWavetableFile(int index, const File &wavetable)
Loads a wavetable from a file into the given oscillator editor.
Definition full_interface.cpp:815
void loadWavetable(int index, json &wavetable_data)
Loads a wavetable from a JSON object into the given oscillator editor.
Definition full_interface.cpp:820
A slider with no visible UI, used internally.
Definition oscillator_section.cpp:344
void drawShadow(Graphics &g) override
Overridden to prevent drawing shadows.
Definition oscillator_section.cpp:362
void paint(Graphics &g) override
Overridden to prevent drawing the slider graphics.
Definition oscillator_section.cpp:356
InvisibleSlider(String name)
Constructs an InvisibleSlider.
Definition oscillator_section.cpp:350
static const std::string kAdditionalWavetableFoldersName
Definition load_save.h:79
static void savePreferredTTWTLanguage(std::string language)
Saves a preferred Text-To-Wavetable (TTWT) language to the config.
Definition load_save.cpp:1268
static File getShiftedFile(const String directory_name, const String &extensions, const std::string &additional_folders_name, const File &current_file, int shift)
Given a directory name and extensions, returns a file shifted by some offset from the current file.
Definition load_save.cpp:1921
static std::string getPreferredTTWTLanguage()
Returns the preferred Text-To-Wavetable language, if set.
Definition load_save.cpp:1661
static std::vector< File > getWavetableDirectories()
Gets directories that should contain wavetables.
Definition load_save.cpp:1768
static const std::string kWavetableFolderName
Definition load_save.h:75
void setQuad(int i, float x, float y, float w, float h)
Sets the position and size of a quad in normalized device space.
Definition open_gl_multi_quad.h:313
force_inline void setColor(Colour color)
Sets the base color for the quads.
Definition open_gl_multi_quad.h:102
void setRounding(float rounding)
Sets the rounding radius of the quads.
Definition open_gl_multi_quad.h:347
void textEditorReturnKeyPressed(TextEditor &text_editor) override
Handles the return key press in the text editor.
Definition oscillator_section.cpp:940
void setIndexSelected()
Sets the language index for the text-to-wavetable functionality.
Definition oscillator_section.cpp:1078
void setLanguage(int index)
Sets the language for text-to-wavetable processing.
Definition oscillator_section.cpp:1085
virtual ~OscillatorSection()
Destructor.
void textToWavetable() override
Converts entered text to a wavetable (TTWT).
Definition oscillator_section.cpp:1203
void languageSelectCancelled()
Cancels the language selection for TTWT.
Definition oscillator_section.cpp:1096
void loadBrowserState()
Loads the browser state for wavetable preset selection.
Definition oscillator_section.cpp:1071
void resetOscillatorModulationDistortionType()
Resets the oscillator modulation distortion type to default.
Definition oscillator_section.cpp:1143
Rectangle< float > getWavetableRelativeBounds()
Gets the relative bounds of the wavetable display area.
Definition oscillator_section.cpp:1244
void setName(String name)
Sets the display name of the oscillator section.
Definition oscillator_section.cpp:988
void loadWavetable(json &wavetable_data) override
Loads a wavetable from JSON data.
Definition oscillator_section.cpp:1170
void setSkinValues(const Skin &skin, bool top_level) override
Sets visual skin values.
Definition oscillator_section.cpp:633
void setSpectralMorphSelected(int selection)
Sets the currently selected spectral morph type.
Definition oscillator_section.cpp:1048
void setActive(bool active) override
Sets the active state of the oscillator section.
Definition oscillator_section.cpp:980
void buttonClicked(Button *clicked_button) override
Handles button clicks.
Definition oscillator_section.cpp:840
Slider * getWaveFrameSlider()
Gets the wave frame slider.
Definition oscillator_section.cpp:1034
void nextClicked() override
Loads the next wavetable in the browser.
Definition oscillator_section.cpp:1114
void timerCallback() override
Timer callback for handling transient states (e.g. error messages).
Definition oscillator_section.cpp:972
void textEditorFocusLost(TextEditor &text_editor) override
Handles focus loss in the text editor.
Definition oscillator_section.cpp:962
void setDistortionSelected(int selection)
Sets the currently selected distortion type.
Definition oscillator_section.cpp:1039
bool loadAudioAsWavetable(String name, InputStream *audio_stream, WavetableCreator::AudioFileLoadStyle style) override
Loads audio data as a wavetable.
Definition oscillator_section.cpp:1152
void setDestinationSelected(int selection)
Sets the currently selected destination routing.
Definition oscillator_section.cpp:1055
void loadDefaultWavetable() override
Loads the default (init) wavetable.
Definition oscillator_section.cpp:1183
static constexpr float kSectionWidthRatio
Relative width ratio of the oscillator section.
Definition oscillator_section.h:35
void resynthesizeToWavetable() override
Resynthesizes the current source to a wavetable.
Definition oscillator_section.cpp:1194
void quantizeUpdated() override
Called when transpose quantization is updated.
Definition oscillator_section.cpp:1135
void loadFile(const File &wavetable_file) override
Loads a wavetable file from disk.
Definition oscillator_section.cpp:1223
void resized() override
Called when the component is resized. Handles layout.
Definition oscillator_section.cpp:701
void paintBackground(Graphics &g) override
Paints the background of this section.
Definition oscillator_section.cpp:644
OscillatorSection(Authentication *auth, int index, const vital::output_map &mono_modulations, const vital::output_map &poly_modulations)
Constructs a new OscillatorSection.
Definition oscillator_section.cpp:366
void prevClicked() override
Loads the previous wavetable in the browser.
Definition oscillator_section.cpp:1104
void textMouseDown(const MouseEvent &e) override
Handles mouse-down events on textual components.
Definition oscillator_section.cpp:1124
std::string loadWavetableFromText(const String &text)
Loads a wavetable from text input (TTWT - text to wavetable).
Definition oscillator_section.cpp:1005
void saveWavetable() override
Saves the current wavetable to disk.
Definition oscillator_section.cpp:1216
void toggleFilterInput(int filter_index, bool on)
Toggles filter input on or off.
Definition oscillator_section.cpp:1061
void setAllValues(vital::control_map &controls) override
Sets all control values from a given control map.
Definition oscillator_section.cpp:919
int index() const
Gets the oscillator index.
Definition oscillator_section.h:310
static Path pencil()
Definition paths.h:725
static Path next()
Creates a 'next' arrow icon path.
Definition paths.h:176
static Path prev()
Creates a 'previous' arrow icon path.
Definition paths.h:157
Manages and provides access to vertex and fragment shaders used by the OpenGL rendering pipeline.
Definition shaders.h:19
Manages the overall color and value theme (or "skin") of the user interface.
Definition skin.h:24
float getValue(ValueId value_id) const
Gets a global UI value.
Definition skin.h:308
@ kWidgetMargin
Definition skin.h:103
@ kLabelBackgroundHeight
Definition skin.h:73
@ kLabelHeight
Definition skin.h:72
@ kWavetableVerticalAngle
Definition skin.h:111
@ kTitleWidth
Definition skin.h:80
@ kTextComponentOffset
Definition skin.h:85
@ kWavetableYOffset
Definition skin.h:114
@ kWavetableHorizontalAngle
Definition skin.h:110
@ kTextButtonHeight
Definition skin.h:87
@ kWavetableWaveHeight
Definition skin.h:113
@ kLabelBackgroundRounding
Definition skin.h:74
@ kWidgetRoundedCorner
Definition skin.h:104
@ kWavetableDrawWidth
Definition skin.h:112
@ kUiButtonPressed
Definition skin.h:195
@ kIconButtonOff
Definition skin.h:185
@ kUiButtonHover
Definition skin.h:194
@ kWidgetPrimary1
Definition skin.h:165
@ kIconButtonOffHover
Definition skin.h:186
@ kBodyText
Definition skin.h:133
@ kUiButton
Definition skin.h:192
@ kOverlayScreen
Definition skin.h:140
@ kIconButtonOffPressed
Definition skin.h:187
@ kTextComponentBackground
Definition skin.h:147
@ kTextEditorSelection
Definition skin.h:203
@ kTextEditorCaret
Definition skin.h:202
@ kOscillator
Definition skin.h:35
void valueChangedInternal(const std::string &name, vital::mono_float value)
Handles internal value changes, updating the parameter and optionally notifying the host.
Definition synth_base.cpp:54
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
virtual void buttonClicked(Button *clicked_button) override
Called when a button is clicked. Updates the synth parameter accordingly.
Definition synth_section.cpp:398
void drawLabelConnectionForComponents(Graphics &g, Component *left, Component *right)
Draws a rectangular connection between labels of two components.
Definition synth_section.cpp:745
float getSliderWidth()
Definition synth_section.cpp:637
void placeKnobsInArea(Rectangle< int > area, std::vector< Component * > knobs)
Definition synth_section.cpp:601
void addSlider(SynthSlider *slider, bool show=true, bool listen=true)
Definition synth_section.cpp:445
void paintJointControl(Graphics &g, int x, int y, int width, int height, const std::string &name)
Definition synth_section.cpp:564
void addSubSection(SynthSection *section, bool show=true)
Adds a subsection (another SynthSection) as a child.
Definition synth_section.cpp:457
virtual void setSkinValues(const Skin &skin, bool top_level)
Sets skin values (colors, sizes) and applies them to sub-sections.
Definition synth_section.cpp:86
virtual void resized() override
Called when the component is resized. Arranges layout of child components.
Definition synth_section.cpp:35
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 updatePopupBrowser(SynthSection *owner)
Updates the currently visible popup browser if any.
Definition synth_section.cpp:113
void paintKnobShadows(Graphics &g)
Paints knob shadows for all sliders.
Definition synth_section.cpp:253
virtual void setActive(bool active)
Sets the active state of this section and sub-sections.
Definition synth_section.cpp:806
void drawLabelForComponent(Graphics &g, String text, Component *component, bool text_component=false)
Draws a label for a given component.
Definition synth_section.h:548
void setLabelFont(Graphics &g)
Sets the Graphics context font and color for labels.
Definition synth_section.cpp:740
float getSliderOverlap()
Definition synth_section.cpp:641
virtual void paintHeadingText(Graphics &g)
Paints the heading text for this section, either sideways or horizontally.
Definition synth_section.cpp:66
void showPopupSelector(Component *source, Point< int > position, const PopupItems &options, std::function< void(int)> callback, std::function< void()> cancel={ })
Shows a popup selector with options.
Definition synth_section.cpp:119
float size_ratio_
Definition synth_section.h:821
void addButton(OpenGlToggleButton *button, bool show=true)
Definition synth_section.cpp:428
Rectangle< int > getLabelBackgroundBounds(Rectangle< int > bounds, bool text_component=false)
Gets the background bounds for a label.
Definition synth_section.cpp:782
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
bool isActive() const
Checks if the section is currently active.
Definition synth_section.h:683
float getKnobSectionHeight()
Definition synth_section.cpp:633
void setActivator(SynthButton *activator)
Definition synth_section.cpp:504
void addOpenGlComponent(OpenGlComponent *open_gl_component, bool to_beginning=false)
Definition synth_section.cpp:489
virtual void setAllValues(vital::control_map &controls)
Sets values for all known parameters from a control map.
Definition synth_section.cpp:827
float getSliderOverlapWithSpace()
Definition synth_section.cpp:648
void setPresetSelector(PresetSelector *preset_selector, bool half=false)
Definition synth_section.h:779
float getTitleWidth()
Definition synth_section.cpp:629
void setSkinOverride(Skin::SectionOverride skin_override)
Definition synth_section.h:303
virtual void repaintBackground()
Requests a repaint of the background.
Definition synth_section.cpp:96
void placeJointControls(int x, int y, int width, int height, SynthSlider *left, SynthSlider *right, Component *widget=nullptr)
Definition synth_section.cpp:572
virtual void paintContainer(Graphics &g)
Paints the container background, body, heading, etc.
Definition synth_section.cpp:146
void showPopupBrowser(SynthSection *owner, Rectangle< int > bounds, std::vector< File > directories, String extensions, std::string passthrough_name, std::string additional_folders_name)
Shows a file browser popup (e.g., for loading samples or wavetables).
Definition synth_section.cpp:105
float getWidgetMargin()
Definition synth_section.cpp:676
A specialized slider with extended functionality for modulation, parameter control,...
Definition synth_slider.h:314
static TextLookAndFeel * instance()
Singleton instance access.
Definition text_look_and_feel.h:106
A component for visualizing unison voices distribution and detune.
Definition oscillator_section.cpp:236
void setDetunePowerSlider(SynthSlider *slider)
Sets the slider for detune power.
Definition oscillator_section.cpp:286
UnisonViewer(int index, const vital::output_map &mono_modulations, const vital::output_map &poly_modulations)
Constructs a UnisonViewer.
Definition oscillator_section.cpp:244
void render(OpenGlWrapper &open_gl, bool animate) override
Renders the unison visualization.
Definition oscillator_section.cpp:293
static vital::poly_float getOutputsTotal(std::pair< vital::Output *, vital::Output * > outputs, vital::poly_float default_value, bool animate)
Calculates total output values from given output pairs.
Definition oscillator_section.cpp:263
void setDetuneSlider(SynthSlider *slider)
Sets the slider for detune.
Definition oscillator_section.cpp:280
void setVoicesSlider(SynthSlider *slider)
Sets the slider for voices.
Definition oscillator_section.cpp:274
RenderType
Render types for different visualization modes.
Definition wavetable_3d.h:80
@ kNumRenderTypes
Definition wavetable_3d.h:84
AudioFileLoadStyle
Defines how audio files are interpreted when loading into a wavetable.
Definition wavetable_creator.h:33
@ kWavetableSplice
Slice the audio into segments mapping onto wavetable frames.
Definition wavetable_creator.h:35
@ kTtwt
Similar to vocoded but optimized for TTWT (text-to-wavetable).
Definition wavetable_creator.h:37
static force_inline int getFirstModulationIndex(int index)
Helper function to determine the first modulation index for a given oscillator index.
Definition producers_module.h:50
static force_inline int getSecondModulationIndex(int index)
Helper function to determine the second modulation index for a given oscillator index.
Definition producers_module.h:60
static bool isFirstModulation(int type)
Checks if distortion type uses the first modulation oscillator.
Definition synth_oscillator.h:185
DistortionType
Types of distortion/waveshaping used by the oscillator.
Definition synth_oscillator.h:145
@ kRmOscillatorB
RM using oscillator B.
Definition synth_oscillator.h:157
@ kFmOscillatorA
FM using oscillator A.
Definition synth_oscillator.h:153
@ kFmOscillatorB
FM using oscillator B.
Definition synth_oscillator.h:154
@ kNone
No distortion.
Definition synth_oscillator.h:146
@ kSqueeze
Squeeze distortion.
Definition synth_oscillator.h:151
@ kFormant
Formant shifting.
Definition synth_oscillator.h:148
@ kRmOscillatorA
RM using oscillator A.
Definition synth_oscillator.h:156
@ kBend
Bend distortion.
Definition synth_oscillator.h:150
@ kNumDistortionTypes
Definition synth_oscillator.h:159
@ kSync
Sync distortion.
Definition synth_oscillator.h:147
static bool usesDistortionPhase(DistortionType distortion_type)
Checks if a given distortion type uses a separate distortion_phase (kSync, kQuantize,...
Definition synth_oscillator.cpp:1189
@ kFormScale
Formant scaling.
Definition synth_oscillator.h:129
@ kHarmonicScale
Harmonic scaling.
Definition synth_oscillator.h:130
@ kInharmonicScale
Inharmonic scaling.
Definition synth_oscillator.h:131
@ kNoSpectralMorph
No spectral morph effect.
Definition synth_oscillator.h:127
@ kNumSpectralMorphTypes
Definition synth_oscillator.h:139
@ kPhaseDisperse
Phase dispersion.
Definition synth_oscillator.h:136
@ kVocode
Vocode morph.
Definition synth_oscillator.h:128
static constexpr int kMaxUnison
Maximum number of unison voices.
Definition synth_oscillator.h:199
static bool isSecondModulation(int type)
Checks if distortion type uses the second modulation oscillator.
Definition synth_oscillator.h:194
nlohmann::json json
Definition line_generator.h:7
const std::string kPhaseDistortionNames[]
Names of different phase distortion modes.
Definition synth_strings.h:429
const std::string kWavetableDimensionNames[]
Names for wavetable dimension display modes.
Definition synth_strings.h:27
const std::string kDestinationNames[vital::constants::kNumSourceDestinations+vital::constants::kNumEffects]
Names of possible audio routing destinations (filters, effects).
Definition synth_strings.h:387
const std::string kDestinationMenuNames[vital::constants::kNumSourceDestinations+vital::constants::kNumEffects]
Names for destinations as displayed in menus.
Definition synth_strings.h:408
const std::string kSpectralMorphNames[]
Names for spectral morphing modes in the wavetable.
Definition synth_strings.h:449
SourceDestination
Represents routing destinations for oscillators and other sound sources through the signal chain.
Definition synth_constants.h:115
@ kNumSourceDestinations
Definition synth_constants.h:121
force_inline mono_float powerScale(mono_float value, mono_float power)
A power-scaling function to map a linear range to a curved response.
Definition futils.h:455
Contains classes and functions used within the Vital synthesizer framework.
std::map< std::string, Output * > output_map
Maps parameter names to Output pointers, representing output signals from various modules.
Definition synth_types.h:229
constexpr int kNotesPerOctave
Number of semitones per octave.
Definition common.h:51
const std::string kWavetableExtension
File extension for Vital wavetable files.
Definition synth_constants.h:88
const std::string kWavetableExtensionsList
A semicolon-separated list of supported wavetable file extensions, including external formats like ....
Definition synth_constants.h:91
std::map< std::string, Value * > control_map
Maps parameter names to Value pointers representing synth control parameters.
Definition synth_types.h:214
Declares the PresetSelector class which provides a UI component for selecting presets.
A helper struct containing references to OpenGL context, shaders, and display scale.
Definition shaders.h:174
A hierarchical structure of popup menu items for a selector component.
Definition synth_section.h:29
void addItem(int sub_id, const std::string &sub_name, bool sub_selected=false)
Adds a new item as a submenu entry.
Definition synth_section.h:51
Represents a vector of floating-point values using SIMD instructions.
Definition poly_values.h:600
Declares classes for OpenGL-based buttons used in the Vital synth UI.
Declares the SynthSlider and related classes, providing various slider styles and functionality in th...
Declares the TextSelector class and PaintPatternSelector class for selecting text-based options and d...
const std::unordered_map< std::string, std::string > & getTooltips()
Definition tooltipText.cpp:22
Declares the Wavetable3d class, which provides a 3D and 2D visualization for wavetables.