diff --git a/CrystalizerEQ/AXIOMDesignSystem.h b/CrystalizerEQ/AXIOMDesignSystem.h index f8eaa81..716c77b 100644 --- a/CrystalizerEQ/AXIOMDesignSystem.h +++ b/CrystalizerEQ/AXIOMDesignSystem.h @@ -24,12 +24,12 @@ namespace AXIOM { static inline const juce::Colour ACCENTWEAKCOLOUR = juce::Colour::fromRGB(61, 183, 183); // #3DB7B7 //===================== HOVER COLORS ====================// - static inline const juce::Colour ACCENTHOVER = juce::Colour::fromRGB(140, 255, 255); // #8CFFFF - static inline const juce::Colour BACKGROUNDHOVER = juce::Colour::fromRGB(70, 70, 70); // #464646 - static inline const juce::Colour FOREGROUNDHOVER = juce::Colour::fromRGB(255, 255, 255); // #FFFFFF - static inline const juce::Colour SURFACEHOVER = juce::Colour::fromRGB(48, 48, 48); // #303030 - static inline const juce::Colour MUTEDTEXTHOVER = juce::Colour::fromRGB(235, 235, 235); // #EBEBEB - static inline const juce::Colour ACCENTWEAKHOVER = juce::Colour::fromRGB(100, 225, 225); // #64E1E1 + static inline const juce::Colour ACCENTHOVER = juce::Colour::fromRGB(140, 255, 255); // #8CFFFF + static inline const juce::Colour BACKGROUNDHOVER = juce::Colour::fromRGB(70, 70, 70); // #464646 + static inline const juce::Colour FOREGROUNDHOVER = juce::Colour::fromRGB(255, 255, 255); // #FFFFFF + static inline const juce::Colour SURFACEHOVER = juce::Colour::fromRGB(48, 48, 48); // #303030 + static inline const juce::Colour MUTEDTEXTHOVER = juce::Colour::fromRGB(235, 235, 235); // #EBEBEB + static inline const juce::Colour ACCENTWEAKHOVER = juce::Colour::fromRGB(100, 225, 225); // #64E1E1 //=====================BYPASS-COLORS========================// static inline const juce::Colour ACCENTBYPASS = juce::Colour::fromRGB(110, 255, 255); // #6EFFFF @@ -38,7 +38,6 @@ namespace AXIOM { static inline const juce::Colour SURFACEBYPASS = juce::Colour::fromRGB(42, 42, 42); // #2A2A2A static inline const juce::Colour MUTEDTEXTBYPASS = juce::Colour::fromRGB(230, 230, 230); // #E6E6E6 static inline const juce::Colour ACCENTWEAKBYPASS = juce::Colour::fromRGB(82, 210, 210); // #52D2D2 - }; struct Spacing { @@ -123,11 +122,11 @@ namespace AXIOM { float snappedUnits; switch (mode) { case SnapMode::Nearest: snappedUnits = std::round(units); - break; + break; case SnapMode::Floor: snappedUnits = std::floor(units + 1e-6f); - break; + break; case SnapMode::Ceiling: snappedUnits = std::ceil(units - 1e-6f); - break; + break; } return snappedUnits * grid; }; @@ -142,15 +141,15 @@ namespace AXIOM { static void setUiScale(uiScaleMode mode) noexcept { switch (mode) { case uiScaleMode::XS: scale.uiScale = 0.5f; - break; + break; case uiScaleMode::S: scale.uiScale = 0.75f; - break; + break; case uiScaleMode::M: scale.uiScale = 1.0f; - break; + break; case uiScaleMode::L: scale.uiScale = 1.5f; - break; + break; case uiScaleMode::XL: scale.uiScale = 1.75f; - break; + break; } scale.uiScale = juce::jlimit(0.3f, 3.0f, scale.uiScale); } @@ -291,12 +290,14 @@ namespace AXIOM { L, XL }; + enum class StrokeMode { Hairline, Thin, Regular, Bold }; + enum class CornerStyle { Rounded, Cut, @@ -313,6 +314,7 @@ namespace AXIOM { static constexpr float MINSTROKE = 1.0f; static constexpr float MAXSTROKE = 3.0f; }; + inline static Scale scale{}; static constexpr int getRadiusUnits(RadiusMode mode) { @@ -359,7 +361,6 @@ namespace AXIOM { width = juce::jlimit(scale.MINSTROKE, scale.MAXSTROKE, width); return width; }; - }; struct Shadows { @@ -369,30 +370,35 @@ namespace AXIOM { static constexpr float MINALPHA = 0.04f; static constexpr float MAXALPHA = 0.95f; static constexpr float MUTEDMUL = 0.5f; + struct AlphaToken { enum class Role { Text, Icon, Surface, Overlay, Stroke, FocusGlow, Disabled, InteractiveFill }; + enum class State { Rest, Hover, Active, Checked, Dragged, Disabled }; + enum class Emphasis { High, Medium, Low, Muted }; + Role role; State state; Emphasis emphasis; }; - static AlphaToken getAlphaToken(AlphaToken::Role role, AlphaToken::State state, AlphaToken::Emphasis emphasis) { - return AlphaToken{ role, state, emphasis }; + static AlphaToken getAlphaToken(AlphaToken::Role role, AlphaToken::State state, + AlphaToken::Emphasis emphasis) { + return AlphaToken{role, state, emphasis}; }; static float getAlphaFactor(AlphaToken::Role role, AlphaToken::State state, AlphaToken::Emphasis emphasis) { float alphaFactor; if (role == AlphaToken::Role::Text || role == AlphaToken::Role::Icon) { alphaFactor = fromEmphasis(emphasis); - }else { + } else { alphaFactor = fromRole(role); } alphaFactor += fromState(state); @@ -403,23 +409,23 @@ namespace AXIOM { static float fromEmphasis(AlphaToken::Emphasis emphasis) { switch (emphasis) { - case AlphaToken::Emphasis::High: return 0.92f; + case AlphaToken::Emphasis::High: return 0.92f; case AlphaToken::Emphasis::Medium: return 0.72f; - case AlphaToken::Emphasis::Low: return 0.56f; - case AlphaToken::Emphasis::Muted: return 0.42f; + case AlphaToken::Emphasis::Low: return 0.56f; + case AlphaToken::Emphasis::Muted: return 0.42f; } return 0.92f; } static float fromRole(AlphaToken::Role role) { switch (role) { - case AlphaToken::Role::Surface: return 0.96f; - case AlphaToken::Role::Overlay: return 0.28f; - case AlphaToken::Role::Stroke: return 0.14f; - case AlphaToken::Role::FocusGlow: return 0.18f; - case AlphaToken::Role::Disabled: return 0.45f; + case AlphaToken::Role::Surface: return 0.96f; + case AlphaToken::Role::Overlay: return 0.28f; + case AlphaToken::Role::Stroke: return 0.14f; + case AlphaToken::Role::FocusGlow: return 0.18f; + case AlphaToken::Role::Disabled: return 0.45f; case AlphaToken::Role::InteractiveFill: return 0.95f; - default: return 1.0f; + default: return 1.0f; } } @@ -527,20 +533,16 @@ namespace AXIOM { };*/ struct Components { - class BypassButtonLookAndFeel : public juce::LookAndFeel_V4 { public: - BypassButtonLookAndFeel() - { - svgXml = juce::XmlDocument::parse(BinaryData::bypass_icon_svg);} + BypassButtonLookAndFeel() { + svgXml = juce::XmlDocument::parse(BinaryData::bypass_icon_svg); + } - - void drawToggleButton(juce::Graphics& g, juce::ToggleButton& button, - bool shouldDrawButtonAsHighlighted, - bool shouldDrawButtonAsDown) override - { - + void drawToggleButton(juce::Graphics &g, juce::ToggleButton &button, + bool shouldDrawButtonAsHighlighted, + bool shouldDrawButtonAsDown) override { bool isHovered = button.isMouseOverOrDragging(); bool isToggled = button.getToggleState(); bool isEnabled = button.isEnabled(); @@ -549,36 +551,32 @@ namespace AXIOM { auto hoverFactor = isHovered ? 1.05f : 1.0f; auto iconBounds = juce::Rectangle(iconSize * hoverFactor, iconSize * hoverFactor) - .withCentre(bounds.getCentre()); + .withCentre(bounds.getCentre()); float bypassOpacity = 1.0f; if (svgXml != nullptr) { // WICHTIG: Erstelle für jeden Frame ein NEUES Drawable! auto icon = juce::Drawable::createFromSVG(*svgXml); - if (icon != nullptr) - { - + if (icon != nullptr) { juce::Colour colour; if (!isEnabled) { colour = isToggled ? Colours::SURFACEBYPASS : Colours::ACCENTWEAKCOLOUR; - } - else if (isHovered) { + } else if (isHovered) { colour = isToggled ? Colours::SURFACEHOVER : Colours::ACCENTHOVER; } else { colour = isToggled - ? Colours::SURFACECOLOUR - : Colours::ACCENTCOLOUR; + ? Colours::SURFACECOLOUR + : Colours::ACCENTCOLOUR; } // Icon zeichnen icon->replaceColour(juce::Colours::black, colour); icon->drawWithin(g, iconBounds, - juce::RectanglePlacement::centred, bypassOpacity); + juce::RectanglePlacement::centred, bypassOpacity); } } - } private: @@ -587,16 +585,13 @@ namespace AXIOM { class PresetMenuButtonLookAndFeel : public juce::LookAndFeel_V4 { public: - PresetMenuButtonLookAndFeel() - { + PresetMenuButtonLookAndFeel() { presetMenuButton = juce::XmlDocument::parse(BinaryData::preset_menu_icon_svg); } - void drawToggleButton(juce::Graphics& g, juce::ToggleButton& button, - bool shouldDrawButtonAsHighlighted, - bool shouldDrawButtonAsDown) override - { - + void drawToggleButton(juce::Graphics &g, juce::ToggleButton &button, + bool shouldDrawButtonAsHighlighted, + bool shouldDrawButtonAsDown) override { bool isHovered = button.isMouseOverOrDragging(); bool isToggled = button.getToggleState(); bool isEnabled = button.isEnabled(); @@ -605,7 +600,7 @@ namespace AXIOM { auto hoverFactor = isHovered ? 1.05f : 1.0f; auto iconBounds = juce::Rectangle(iconSize * hoverFactor, iconSize * hoverFactor) - .withCentre(bounds.getCentre()); + .withCentre(bounds.getCentre()); float bypassOpacity = 1.0f; @@ -616,17 +611,16 @@ namespace AXIOM { colour = isToggled ? Colours::ACCENTHOVER : Colours::BACKGROUNDHOVER; } else { colour = isToggled - ? Colours::ACCENTCOLOUR - : Colours::BACKGROUNDCOLOUR; + ? Colours::ACCENTCOLOUR + : Colours::BACKGROUNDCOLOUR; } // Icon zeichnen menuIcon->replaceColour(juce::Colours::black, colour); menuIcon->drawWithin(g, iconBounds, - juce::RectanglePlacement::centred, 1.0f); + juce::RectanglePlacement::centred, 1.0f); } - } private: @@ -643,58 +637,48 @@ namespace AXIOM { float activeIconOpacity = 0.0f; - void drawToggleButton(juce::Graphics& g, juce::ToggleButton& button, - bool shouldDrawButtonAsHighlighted, - bool shouldDrawButtonAsDown) override { - - + void drawToggleButton(juce::Graphics &g, juce::ToggleButton &button, + bool shouldDrawButtonAsHighlighted, + bool shouldDrawButtonAsDown) override { const bool isHovered = button.isMouseOverOrDragging(); const bool isToggled = button.getToggleState(); auto bounds = button.getLocalBounds().toFloat(); - auto iconSize = juce::jmin(bounds.getWidth(), bounds.getHeight()) * 0.5f; + auto iconSize = juce::jmin(bounds.getWidth(), bounds.getHeight()) * 2 * 0.95f; auto hoverFactor = isHovered ? 1.05f : 1.0f; auto iconBounds = juce::Rectangle(iconSize * hoverFactor, iconSize * hoverFactor) - .withCentre(bounds.getCentre()); + .withCentre(bounds.getCentre()); auto passiveIcon = juce::Drawable::createFromSVG(*passiveSvg); auto activeIcon = juce::Drawable::createFromSVG(*activeSvg); if (passiveIcon != nullptr && activeIcon != nullptr) { - activeIcon->drawWithin(g, iconBounds, - juce::RectanglePlacement::centred, activeIconOpacity); + juce::RectanglePlacement::centred, activeIconOpacity); passiveIcon->drawWithin(g, iconBounds, - juce::RectanglePlacement::centred, passiveIconOpacity); - + juce::RectanglePlacement::centred, passiveIconOpacity); } } private: std::unique_ptr passiveSvg; std::unique_ptr activeSvg; - }; class lowBandButtonLookAndFeel : public juce::LookAndFeel_V4 { public: - lowBandButtonLookAndFeel() - { + lowBandButtonLookAndFeel() { lowBypassIcon = juce::XmlDocument::parse(BinaryData::bypass_icon_svg); lowCutIcon = juce::XmlDocument::parse(BinaryData::low_cut_icon_svg); lowBellIcon = juce::XmlDocument::parse(BinaryData::bell_icon_svg); lowShelfIcon = juce::XmlDocument::parse(BinaryData::low_shelf_icon_svg); - } - - void drawToggleButton(juce::Graphics& g, juce::ToggleButton& button, - bool shouldDrawButtonAsHighlighted, - bool shouldDrawButtonAsDown) override - { - + void drawToggleButton(juce::Graphics &g, juce::ToggleButton &button, + bool shouldDrawButtonAsHighlighted, + bool shouldDrawButtonAsDown) override { bool isHovered = button.isMouseOverOrDragging(); bool isToggled = button.getToggleState(); bool isEnabled = button.isEnabled(); @@ -703,30 +687,29 @@ namespace AXIOM { auto hoverFactor = isHovered ? 1.05f : 1.0f; auto iconBounds = juce::Rectangle(iconSize * hoverFactor, iconSize * hoverFactor) - .withCentre(bounds.getCentre()); + .withCentre(bounds.getCentre()); float bypassOpacity = 1.0f; - if (lowBypassIcon != nullptr && lowCutIcon != nullptr && lowBellIcon != nullptr && lowShelfIcon != nullptr) { + if (lowBypassIcon != nullptr && lowCutIcon != nullptr && lowBellIcon != nullptr && lowShelfIcon != + nullptr) { // WICHTIG: Erstelle für jeden Frame ein NEUES Drawable! auto bypassIcon = juce::Drawable::createFromSVG(*lowBypassIcon); auto cutIcon = juce::Drawable::createFromSVG(*lowCutIcon); auto bellIcon = juce::Drawable::createFromSVG(*lowBellIcon); auto shelfIcon = juce::Drawable::createFromSVG(*lowShelfIcon); - if (bypassIcon != nullptr && cutIcon != nullptr && bellIcon != nullptr && shelfIcon != nullptr) - { - + if (bypassIcon != nullptr && cutIcon != nullptr && bellIcon != nullptr && shelfIcon != + nullptr) { juce::Colour colour; if (!isEnabled) { colour = isToggled ? Colours::ACCENTWEAKCOLOUR : Colours::SURFACEBYPASS; - } - else if (isHovered) { + } else if (isHovered) { colour = isToggled ? Colours::ACCENTHOVER : Colours::SURFACEHOVER; } else { colour = isToggled - ? Colours::ACCENTCOLOUR - : Colours::SURFACECOLOUR; + ? Colours::ACCENTCOLOUR + : Colours::SURFACECOLOUR; } @@ -734,27 +717,22 @@ namespace AXIOM { if (button.getName() == "LowBypass") { bypassIcon->replaceColour(juce::Colours::black, colour); bypassIcon->drawWithin(g, iconBounds, - juce::RectanglePlacement::centred, bypassOpacity); - } - else if (button.getName() == "LowCut") { + juce::RectanglePlacement::centred, bypassOpacity); + } else if (button.getName() == "LowCut") { cutIcon->replaceColour(juce::Colours::black, colour); cutIcon->drawWithin(g, iconBounds, - juce::RectanglePlacement::centred, bypassOpacity); - } - else if (button.getName() == "LowBell") { + juce::RectanglePlacement::centred, bypassOpacity); + } else if (button.getName() == "LowBell") { bellIcon->replaceColour(juce::Colours::black, colour); bellIcon->drawWithin(g, iconBounds, - juce::RectanglePlacement::centred, bypassOpacity); - } - else if (button.getName() == "LowShelf") { + juce::RectanglePlacement::centred, bypassOpacity); + } else if (button.getName() == "LowShelf") { shelfIcon->replaceColour(juce::Colours::black, colour); shelfIcon->drawWithin(g, iconBounds, - juce::RectanglePlacement::centred, bypassOpacity); + juce::RectanglePlacement::centred, bypassOpacity); } - } } - } private: @@ -766,22 +744,17 @@ namespace AXIOM { class highBandButtonLookAndFeel : public juce::LookAndFeel_V4 { public: - highBandButtonLookAndFeel() - { + highBandButtonLookAndFeel() { highBypassIcon = juce::XmlDocument::parse(BinaryData::bypass_icon_svg); highCutIcon = juce::XmlDocument::parse(BinaryData::high_cut_icon_svg); highBellIcon = juce::XmlDocument::parse(BinaryData::bell_icon_svg); highShelfIcon = juce::XmlDocument::parse(BinaryData::high_shelf_icon_svg); - } - - void drawToggleButton(juce::Graphics& g, juce::ToggleButton& button, - bool shouldDrawButtonAsHighlighted, - bool shouldDrawButtonAsDown) override - { - + void drawToggleButton(juce::Graphics &g, juce::ToggleButton &button, + bool shouldDrawButtonAsHighlighted, + bool shouldDrawButtonAsDown) override { bool isHovered = button.isMouseOverOrDragging(); bool isToggled = button.getToggleState(); bool isEnabled = button.isEnabled(); @@ -790,30 +763,29 @@ namespace AXIOM { auto hoverFactor = isHovered ? 1.05f : 1.0f; auto iconBounds = juce::Rectangle(iconSize * hoverFactor, iconSize * hoverFactor) - .withCentre(bounds.getCentre()); + .withCentre(bounds.getCentre()); float bypassOpacity = 1.0f; - if (highBypassIcon != nullptr && highCutIcon != nullptr && highBellIcon != nullptr && highShelfIcon != nullptr) { + if (highBypassIcon != nullptr && highCutIcon != nullptr && highBellIcon != nullptr && highShelfIcon + != nullptr) { // WICHTIG: Erstelle für jeden Frame ein NEUES Drawable! auto bypassIcon = juce::Drawable::createFromSVG(*highBypassIcon); auto cutIcon = juce::Drawable::createFromSVG(*highCutIcon); auto bellIcon = juce::Drawable::createFromSVG(*highBellIcon); auto shelfIcon = juce::Drawable::createFromSVG(*highShelfIcon); - if (bypassIcon != nullptr && cutIcon != nullptr && bellIcon != nullptr && shelfIcon != nullptr) - { - + if (bypassIcon != nullptr && cutIcon != nullptr && bellIcon != nullptr && shelfIcon != + nullptr) { juce::Colour colour; if (!isEnabled) { colour = isToggled ? Colours::ACCENTWEAKCOLOUR : Colours::SURFACEBYPASS; - } - else if (isHovered) { + } else if (isHovered) { colour = isToggled ? Colours::ACCENTHOVER : Colours::SURFACEHOVER; } else { colour = isToggled - ? Colours::ACCENTCOLOUR - : Colours::SURFACECOLOUR; + ? Colours::ACCENTCOLOUR + : Colours::SURFACECOLOUR; } @@ -821,26 +793,22 @@ namespace AXIOM { if (button.getName() == "HighBypass") { bypassIcon->replaceColour(juce::Colours::black, colour); bypassIcon->drawWithin(g, iconBounds, - juce::RectanglePlacement::centred, bypassOpacity); - } - else if (button.getName() == "HighCut") { + juce::RectanglePlacement::centred, bypassOpacity); + } else if (button.getName() == "HighCut") { cutIcon->replaceColour(juce::Colours::black, colour); cutIcon->drawWithin(g, iconBounds, - juce::RectanglePlacement::centred, bypassOpacity); - } - else if (button.getName() == "HighBell") { + juce::RectanglePlacement::centred, bypassOpacity); + } else if (button.getName() == "HighBell") { bellIcon->replaceColour(juce::Colours::black, colour); bellIcon->drawWithin(g, iconBounds, - juce::RectanglePlacement::centred, bypassOpacity); - } - else if (button.getName() == "HighShelf") { + juce::RectanglePlacement::centred, bypassOpacity); + } else if (button.getName() == "HighShelf") { shelfIcon->replaceColour(juce::Colours::black, colour); shelfIcon->drawWithin(g, iconBounds, - juce::RectanglePlacement::centred, bypassOpacity); + juce::RectanglePlacement::centred, bypassOpacity); } } } - } private: @@ -855,23 +823,21 @@ namespace AXIOM { }; - class BaseSliderLookAndFeel : public juce::LookAndFeel_V4 - { + class BaseSliderLookAndFeel : public juce::LookAndFeel_V4 { public: - juce::Label* createSliderTextBox(juce::Slider& slider) override - { - auto* label = juce::LookAndFeel_V4::createSliderTextBox(slider); + juce::Label *createSliderTextBox(juce::Slider &slider) override { + auto *label = juce::LookAndFeel_V4::createSliderTextBox(slider); label->setColour(juce::Label::backgroundColourId, juce::Colours::transparentBlack); label->setColour(juce::Label::outlineColourId, juce::Colours::transparentBlack); label->setColour(juce::Label::textColourId, Colours::FOREGROUNDCOLOUR); label->setJustificationType(juce::Justification::centred); - label->setInterceptsMouseClicks (false, false); + label->setInterceptsMouseClicks(false, false); Typography::applyToLabel(*label, Typography::Style::Mono, 1.f); return label; } - juce::Slider::SliderLayout getSliderLayout (juce::Slider& slider) override - { + + juce::Slider::SliderLayout getSliderLayout(juce::Slider &slider) override { juce::Slider::SliderLayout layout; if (slider.getName() == "LowBand Slope" || slider.getName() == "HighBand Slope") { layout.textBoxBounds = {}; @@ -883,7 +849,7 @@ namespace AXIOM { const int w = slider.getWidth(); const int h = slider.getHeight(); - layout.textBoxBounds = juce::Rectangle ( + layout.textBoxBounds = juce::Rectangle( r.getCentreX() - w / 2, r.getCentreY() - h / 2, w, h); @@ -893,10 +859,9 @@ namespace AXIOM { return layout; } - void drawRotarySlider(juce::Graphics& g, int x, int y, int width, int height, - float sliderPos, float rotaryStartAngle, float rotaryEndAngle, - juce::Slider& slider) override - { + void drawRotarySlider(juce::Graphics &g, int x, int y, int width, int height, + float sliderPos, float rotaryStartAngle, float rotaryEndAngle, + juce::Slider &slider) override { // Basis-Implementation - wird in Subklassen überschrieben auto radius = juce::jmin(width / 2, height / 2) - 4.0f; auto centreX = x + width * 0.5f; @@ -918,13 +883,12 @@ namespace AXIOM { g.fillPath(p); } }; - class GainSliderLookAndFeel : public BaseSliderLookAndFeel - { + + class GainSliderLookAndFeel : public BaseSliderLookAndFeel { public: - void drawRotarySlider(juce::Graphics& g, int x, int y, int width, int height, - float sliderPos, float rotaryStartAngle, float rotaryEndAngle, - juce::Slider& slider) override - { + void drawRotarySlider(juce::Graphics &g, int x, int y, int width, int height, + float sliderPos, float rotaryStartAngle, float rotaryEndAngle, + juce::Slider &slider) override { bool isHovered = slider.isMouseOverOrDragging(); auto isEnabled = slider.isEnabled(); float hoverFactor = 1.0f; @@ -949,7 +913,7 @@ namespace AXIOM { // Background g.setColour(Colours::BACKGROUNDCOLOUR); - g.fillEllipse(centreX - radius, centreY - radius, radius * 2.0f , radius * 2.0f); + g.fillEllipse(centreX - radius, centreY - radius, radius * 2.0f, radius * 2.0f); g.setColour(surfaceCol); g.drawEllipse(centreX - radius, centreY - radius, radius * 2.0f, radius * 2.0f, arcPathWidth); @@ -958,27 +922,25 @@ namespace AXIOM { // Arc für Gain-Anzeige juce::Path valueArc; valueArc.addCentredArc(centreX, centreY, radius, radius, - 0.0f, mid, angle, true); + 0.0f, mid, angle, true); g.setColour(accentCol); g.strokePath(valueArc, juce::PathStrokeType(arcPathWidth)); // Pointer juce::Path p; - p.addRectangle(-arcPathWidth / 2, (-radius - arcPathWidth) * hoverFactor, arcPathWidth, radius * 0.5f * hoverFactor); + p.addRectangle(-arcPathWidth / 2, (-radius - arcPathWidth) * hoverFactor, arcPathWidth, + radius * 0.5f * hoverFactor); p.applyTransform(juce::AffineTransform::rotation(angle).translated(centreX, centreY)); g.fillPath(p); - } }; - class FreqQSliderLookAndFeel : public BaseSliderLookAndFeel - { + class FreqQSliderLookAndFeel : public BaseSliderLookAndFeel { public: - void drawRotarySlider(juce::Graphics& g, int x, int y, int width, int height, - float sliderPos, float rotaryStartAngle, float rotaryEndAngle, - juce::Slider& slider) override - { + void drawRotarySlider(juce::Graphics &g, int x, int y, int width, int height, + float sliderPos, float rotaryStartAngle, float rotaryEndAngle, + juce::Slider &slider) override { auto radius = juce::jmin(width / 2, height / 2) - 4.0f; auto centreX = x + width * 0.5f; auto centreY = y + height * 0.5f; @@ -1005,13 +967,14 @@ namespace AXIOM { juce::Path valueArc; valueArc.addCentredArc(centreX, centreY, radius, radius, - 0.0f, rotaryStartAngle, angle, true); + 0.0f, rotaryStartAngle, angle, true); g.setColour(accentCol); g.strokePath(valueArc, juce::PathStrokeType(arcPathWidth)); // Dünner Pointer juce::Path p; - p.addRectangle(-1.0f, (-radius - arcPathWidth) * hoverFactor, arcPathWidth, radius * 0.4f * hoverFactor); + p.addRectangle(-1.0f, (-radius - arcPathWidth) * hoverFactor, arcPathWidth, + radius * 0.4f * hoverFactor); p.applyTransform(juce::AffineTransform::rotation(angle).translated(centreX, centreY)); g.setColour(accentCol); @@ -1023,8 +986,7 @@ namespace AXIOM { public: static constexpr float labelPadding = 20.0f; - juce::Slider::SliderLayout getSliderLayout(juce::Slider& slider) override - { + juce::Slider::SliderLayout getSliderLayout(juce::Slider &slider) override { juce::Slider::SliderLayout layout; auto bounds = slider.getLocalBounds(); @@ -1043,10 +1005,9 @@ namespace AXIOM { return layout; } - void drawRotarySlider(juce::Graphics& g, int x, int y, int width, int height, - float sliderPos, float rotaryStartAngle, float rotaryEndAngle, - juce::Slider& slider) override - { + void drawRotarySlider(juce::Graphics &g, int x, int y, int width, int height, + float sliderPos, float rotaryStartAngle, float rotaryEndAngle, + juce::Slider &slider) override { // Basis-Implementation - wird in Subklassen überschrieben auto radius = juce::jmin(width / 2, height / 2) - 4.0f; auto centreX = x + width * 0.5f; @@ -1082,24 +1043,24 @@ namespace AXIOM { g.setFont(12.0f); auto value = slider.getValue(); - for (int i = 0; i < labels.size(); ++i) - { - const double labelVal = labels[i].getDoubleValue(); // "12" -> 12.0 usw. + for (int i = 0; i < labels.size(); ++i) { + const double labelVal = labels[i].getDoubleValue(); // "12" -> 12.0 usw. const bool isMatch = value == i; // Toleranz: 0.5 juce::Colour colour; if (!isEnabled) { - colour = isMatch ? Colours::ACCENTWEAKCOLOUR : Colours::FOREGROUNDCOLOUR.withMultipliedAlpha (0.4f); - } - else { colour = isMatch - ? Colours::ACCENTCOLOUR - : Colours::FOREGROUNDCOLOUR; + ? Colours::ACCENTWEAKCOLOUR + : Colours::FOREGROUNDCOLOUR.withMultipliedAlpha(0.4f); + } else { + colour = isMatch + ? Colours::ACCENTCOLOUR + : Colours::FOREGROUNDCOLOUR; } g.setColour(colour); - const double position = (double)i / 3.0; + const double position = (double) i / 3.0; const float ang = rotaryStartAngle + position * (rotaryEndAngle - rotaryStartAngle); juce::Point pos( @@ -1112,17 +1073,14 @@ namespace AXIOM { g.drawText(labels[i], textRect, juce::Justification::centred); } - } }; - class GlobalSliderLookAndFeel : public BaseSliderLookAndFeel - { + class GlobalSliderLookAndFeel : public BaseSliderLookAndFeel { public: - void drawRotarySlider(juce::Graphics& g, int x, int y, int width, int height, - float sliderPos, float rotaryStartAngle, float rotaryEndAngle, - juce::Slider& slider) override - { + void drawRotarySlider(juce::Graphics &g, int x, int y, int width, int height, + float sliderPos, float rotaryStartAngle, float rotaryEndAngle, + juce::Slider &slider) override { auto radius = juce::jmin(width / 2, height / 2) - 4.0f; auto centreX = x + width * 0.5f; auto centreY = y + height * 0.5f; @@ -1149,20 +1107,21 @@ namespace AXIOM { // Einfacher Ring g.setColour(surfaceCol); - g.fillEllipse(centreX - radius, centreY - radius, radius * 2.0f , radius * 2.0f); + g.fillEllipse(centreX - radius, centreY - radius, radius * 2.0f, radius * 2.0f); g.setColour(ringCol); g.drawEllipse(centreX - radius, centreY - radius, radius * 2.0f, radius * 2.0f, arcPathWidth); juce::Path valueArc; valueArc.addCentredArc(centreX, centreY, radius, radius, - 0.0f, mid, angle, true); + 0.0f, mid, angle, true); g.setColour(accentCol); g.strokePath(valueArc, juce::PathStrokeType(arcPathWidth)); // Dünner Pointer juce::Path p; - p.addRectangle(-1.0f, (-radius - arcPathWidth) * hoverFactor, arcPathWidth, radius * 0.4f * hoverFactor); + p.addRectangle(-1.0f, (-radius - arcPathWidth) * hoverFactor, arcPathWidth, + radius * 0.4f * hoverFactor); p.applyTransform(juce::AffineTransform::rotation(angle).translated(centreX, centreY)); g.setColour(accentCol); @@ -1180,6 +1139,7 @@ namespace AXIOM { Global, Mix }; + static float getSliderSizeMod(SizeMode mode) { switch (mode) { case SizeMode::Gain: return 1.25f; @@ -1191,7 +1151,6 @@ namespace AXIOM { default: return 1.0f; } } - }; }; @@ -1209,7 +1168,6 @@ namespace AXIOM { }; struct Layout { - /// /// @param mode Spacing mode -- e.g. Spacing::SizeMode::XS /// @return Gap size in px as int @@ -1228,21 +1186,20 @@ namespace AXIOM { return rect; } - static juce::FlexItem flexItem(juce::Component& component, + static juce::FlexItem flexItem(juce::Component &component, float flexGrow = 1.f, float flexShrink = 1.f, float basisPx = -1.f, Spacing::SizeMode margin = Spacing::SizeMode::XS) { - - juce::FlexItem item{ component }; - item.flexGrow = flexGrow; + juce::FlexItem item{component}; + item.flexGrow = flexGrow; item.flexShrink = flexShrink; if (basisPx >= 0.f) item.flexBasis = basisPx; const float half = (float) gap(margin) * 0.5f; - item.margin = juce::FlexItem::Margin{ half, half, half, half }; + item.margin = juce::FlexItem::Margin{half, half, half, half}; return item; } @@ -1252,18 +1209,17 @@ namespace AXIOM { Spacing::SizeMode gapSize, juce::FlexBox::JustifyContent justifyContent, juce::FlexBox::AlignItems alignItems - ) { + ) { const auto pad = padding(gapSize); juce::FlexBox fb; - fb.flexDirection = juce::FlexBox::Direction::row; - fb.flexWrap = juce::FlexBox::Wrap::noWrap; + fb.flexDirection = juce::FlexBox::Direction::row; + fb.flexWrap = juce::FlexBox::Wrap::noWrap; fb.justifyContent = justifyContent; - fb.alignItems = alignItems; + fb.alignItems = alignItems; fb.items.addArray(items); fb.performLayout(content(bounds, pad)); - } static void flexColumn(juce::Rectangle bounds, @@ -1271,13 +1227,13 @@ namespace AXIOM { Spacing::SizeMode gapSize, juce::FlexBox::JustifyContent justifyContent, juce::FlexBox::AlignItems alignItems - ) { + ) { const auto pad = padding(gapSize); juce::FlexBox fb; - fb.flexDirection = juce::FlexBox::Direction::column; - fb.flexWrap = juce::FlexBox::Wrap::noWrap; + fb.flexDirection = juce::FlexBox::Direction::column; + fb.flexWrap = juce::FlexBox::Wrap::noWrap; fb.justifyContent = justifyContent; - fb.alignItems = alignItems; + fb.alignItems = alignItems; fb.items.addArray(items); fb.performLayout(content(bounds, pad)); @@ -1301,37 +1257,35 @@ namespace AXIOM { struct GridSpec { std::vector cols; std::vector rows; - Spacing::SizeMode colGap { Spacing::SizeMode::M }; - Spacing::SizeMode rowGap { Spacing::SizeMode::M }; - juce::BorderSize pad { 0, 0, 0, 0 }; + Spacing::SizeMode colGap{Spacing::SizeMode::M}; + Spacing::SizeMode rowGap{Spacing::SizeMode::M}; + juce::BorderSize pad{0, 0, 0, 0}; }; - static juce::GridItem area(juce::Component& c, - int rowStart, int colStart, - int rowEnd, int colEnd) - { + static juce::GridItem area(juce::Component &c, + int rowStart, int colStart, + int rowEnd, int colEnd) { return juce::GridItem(c) - .withArea(rowStart, colStart, rowEnd, colEnd); - + .withArea(rowStart, colStart, rowEnd, colEnd); } static void grid(juce::Rectangle bounds, - const GridSpec& spec, + const GridSpec &spec, std::initializer_list children, juce::Grid::AutoFlow autoFlow = juce::Grid::AutoFlow::row) { juce::Grid g; - for (const auto& t : spec.cols) g.templateColumns.add(t); - for (const auto& t : spec.rows) g.templateRows.add(t); + for (const auto &t: spec.cols) g.templateColumns.add(t); + for (const auto &t: spec.rows) g.templateRows.add(t); - g.autoFlow = autoFlow; + g.autoFlow = autoFlow; g.autoColumns = juce::Grid::TrackInfo(juce::Grid::Fr(1)); - g.autoRows = juce::Grid::TrackInfo(juce::Grid::Fr(1)); + g.autoRows = juce::Grid::TrackInfo(juce::Grid::Fr(1)); - g.columnGap = px((float) gap(spec.colGap)); - g.rowGap = px((float) gap(spec.rowGap)); + g.columnGap = px((float) gap(spec.colGap)); + g.rowGap = px((float) gap(spec.rowGap)); - for (const auto& c : children) + for (const auto &c: children) g.items.add(c); const auto inner = spec.pad.subtractedFrom(bounds); @@ -1341,40 +1295,40 @@ namespace AXIOM { class PresetMenu : public juce::Component { public: - PresetMenu(juce::TextEditor* inputField, - juce::TextButton* saveButton, - juce::TextButton* deleteButton) { + PresetMenu(juce::TextEditor *inputField, + juce::TextButton *saveButton, + juce::TextButton *deleteButton) { addAndMakeVisible(*inputField); addAndMakeVisible(*saveButton); addAndMakeVisible(*deleteButton); } - }; + class PresetMenuLookAndFeel : public juce::LookAndFeel_V4 { public: - void drawCallOutBoxBackground(juce::CallOutBox &callOutBox, juce::Graphics &g, const juce::Path &path, juce::Image &image) override { + void drawCallOutBoxBackground(juce::CallOutBox &callOutBox, juce::Graphics &g, const juce::Path &path, + juce::Image &image) override { g.setColour(Colours::SURFACECOLOUR); g.fillPath(path); - g.setColour (Colours::FOREGROUNDCOLOUR.withAlpha(0.3f)); - g.strokePath (path, juce::PathStrokeType (1.0f)); + g.setColour(Colours::FOREGROUNDCOLOUR.withAlpha(0.3f)); + g.strokePath(path, juce::PathStrokeType(1.0f)); }; - int getCallOutBoxBorderSize (const juce::CallOutBox&) override - { + int getCallOutBoxBorderSize(const juce::CallOutBox &) override { return 4; } }; class PresetButtonsLookAndFeel : public juce::LookAndFeel_V4 { public: - - void drawButtonText(juce::Graphics &g, juce::TextButton &button, bool shouldDrawButtonAsHighlighted, bool shouldDrawButtonAsDown) override { + void drawButtonText(juce::Graphics &g, juce::TextButton &button, bool shouldDrawButtonAsHighlighted, + bool shouldDrawButtonAsDown) override { auto bounds = button.getLocalBounds(); // Text holen - auto text = button.getButtonText(); + auto text = button.getButtonText(); // Farbe wählen auto isHovered = button.isMouseOver(); @@ -1396,66 +1350,244 @@ namespace AXIOM { juce::Justification::centred, 1); } - void drawButtonBackground(juce::Graphics& g, juce::Button& button, - const juce::Colour& backgroundColour, - bool shouldDrawButtonAsHighlighted, - bool shouldDrawButtonAsDown) override - { - auto bounds = button.getLocalBounds().toFloat(); - bool isHovered = button.isMouseOver(); + void drawButtonBackground(juce::Graphics &g, juce::Button &button, + const juce::Colour &backgroundColour, + bool shouldDrawButtonAsHighlighted, + bool shouldDrawButtonAsDown) override { + auto bounds = button.getLocalBounds().toFloat(); + + bool isHovered = button.isMouseOver(); bool isEnabled = button.isEnabled(); - auto colour = isHovered ? Colours::BACKGROUNDHOVER : Colours::BACKGROUNDCOLOUR; + auto colour = isHovered ? Colours::BACKGROUNDHOVER : Colours::BACKGROUNDCOLOUR; if (!isEnabled) colour = colour.withMultipliedAlpha(0.6f); - g.setColour(colour); - g.fillRoundedRectangle(bounds.reduced(1.0f), 4.0f); - } - }; + g.setColour(colour); + g.fillRoundedRectangle(bounds.reduced(1.0f), 4.0f); + } + }; - class PresetComboBoxLookAndFeel : public juce::LookAndFeel_V4 { + class ClickableTextEditor : public juce::TextEditor { public: - juce::PopupMenu::Options getOptionsForComboBoxPopupMenu(juce::ComboBox& box, - juce::Label& label) override - { - // Basis-Options holen - auto options = juce::LookAndFeel_V4::getOptionsForComboBoxPopupMenu(box, label); + std::function onMouseDown; - // Anzahl der sichtbaren Einträge - const int visibleRows = 5; + void mouseDown(const juce::MouseEvent &event) override { + juce::TextEditor::mouseDown(event); // Wichtig: Original-Verhalten beibehalten + if (onMouseDown) + onMouseDown(); + } + }; - // Höhe einer Zeile - auto font = getComboBoxFont(box); - int rowHeight = (int)std::ceil(font.getHeight() * 1.6f); + class PresetInputLookAndFeel : public juce::LookAndFeel_V4 { + public: + void fillTextEditorBackground(juce::Graphics &g, int width, int height, + juce::TextEditor &textEditor) override { + // Hintergrundfarbe + if (textEditor.isEnabled()) { + g.setColour(Colours::SURFACECOLOUR); + } else { + g.setColour(Colours::SURFACEBYPASS); + } + g.fillRoundedRectangle(0, 0, width, height, + Shape::getRadius(Shape::RadiusMode::S, + juce::Rectangle(0, 0, width, height))); - // Maximale Höhe des Popups - int maxPopupHeight = visibleRows * rowHeight; + if (textEditor.getText().isEmpty() && !textEditor.hasKeyboardFocus(true)) { + g.setColour(placeholderColour); + g.setFont(Typography::getFont(Typography::Style::Body, 1.0f)); - // Screen-Bounds der ComboBox - auto boxScreen = box.getScreenBounds(); + auto textBounds = juce::Rectangle(0, 0, width, height).reduced(5); + g.drawText(placeholderText, textBounds, juce::Justification::centred, true); + } + } - // Wichtig: Ein sehr breiter aber in der Höhe begrenzter Bereich - // JUCE wird das Popup darin zentrieren - juce::Rectangle constrainedArea( - 0, // X: ganze Screen-Breite - boxScreen.getBottom(), // Y: direkt unter der Box - juce::Desktop::getInstance().getDisplays() - .getPrimaryDisplay()->totalArea.getWidth(), - maxPopupHeight // Höhe: nur unsere gewünschten Zeilen - ); + void drawTextEditorOutline(juce::Graphics &g, int width, int height, + juce::TextEditor &textEditor) override { + // Rahmen + auto bounds = juce::Rectangle(0, 0, width, height); + auto radius = Shape::getRadius(Shape::RadiusMode::S, bounds); + auto strokeWidth = Shape::getStrokeWidth(Shape::StrokeMode::Thin); - options = options.withTargetScreenArea(constrainedArea) - .withStandardItemHeight(rowHeight); + juce::Colour outlineColour; - return options; + if (!textEditor.isEnabled()) { + outlineColour = Colours::FOREGROUNDBYPASS.withAlpha(0.3f); + } else if (textEditor.hasKeyboardFocus(true)) { + // Fokussiert - Accent-Farbe + outlineColour = Colours::ACCENTCOLOUR; + } else if (textEditor.isMouseOver()) { + // Hover + outlineColour = Colours::FOREGROUNDHOVER.withAlpha(0.5f); + } else { + // Normal + outlineColour = Colours::FOREGROUNDCOLOUR.withAlpha(0.3f); + } + + g.setColour(outlineColour); + g.drawRoundedRectangle(bounds.reduced(strokeWidth * 0.5f), radius, strokeWidth); + } + + juce::CaretComponent *createCaretComponent(juce::Component *keyFocusOwner) override { + auto *caret = new juce::CaretComponent(keyFocusOwner); + caret->setColour(juce::CaretComponent::caretColourId, Colours::ACCENTCOLOUR); + return caret; + } + + private: + juce::String placeholderText = "Preset Name"; + juce::Colour placeholderColour = Colours::MUTEDTEXTCOLOUR; + }; + + class PresetComboBoxLookAndFeel : public juce::LookAndFeel_V4, + private juce::ComponentListener +{ +public: + PresetComboBoxLookAndFeel() = default; + + ~PresetComboBoxLookAndFeel() override + { + } + + void getIdealPopupMenuItemSize (const juce::String& text, bool /*isSeparator*/, + int /*standardMenuItemHeight*/, int& idealWidth, + int& idealHeight) override + { + idealHeight = 50; + + auto font = Typography::getFont (Typography::Style::Body, 1.0f); + idealWidth = font.getStringWidth (text); + } + + void drawPopupMenuUpDownArrow(juce::Graphics& g, int width, int height, + bool isScrollUpArrow) override + { + g.setColour(Colours::ACCENTCOLOUR); + + auto arrowZone = juce::Rectangle(0.0f, 0.0f, (float)width, (float)height); + auto arrowWidth = arrowZone.getWidth() * 0.1f; + auto arrowHeight = arrowZone.getHeight() * 0.1f; + + juce::Path arrow; + arrow.startNewSubPath(arrowZone.getCentreX() - arrowWidth * 0.5f, + arrowZone.getCentreY() + (isScrollUpArrow ? arrowHeight * 0.5f : -arrowHeight * 0.5f)); + arrow.lineTo(arrowZone.getCentreX(), + arrowZone.getCentreY() + (isScrollUpArrow ? -arrowHeight * 0.5f : arrowHeight * 0.5f)); + arrow.lineTo(arrowZone.getCentreX() + arrowWidth * 0.5f, + arrowZone.getCentreY() + (isScrollUpArrow ? arrowHeight * 0.5f : -arrowHeight * 0.5f)); + + g.strokePath(arrow, juce::PathStrokeType(1.5f)); + } + + void drawPopupMenuBackground(juce::Graphics& g, int width, int height) override + { + g.fillAll(Colours::SURFACECOLOUR); + + } + + void drawPopupMenuItem (juce::Graphics& g, const juce::Rectangle& area, + bool isSeparator, bool isActive, bool isHighlighted, + bool isTicked, bool hasSubMenu, const juce::String& text, + const juce::String& shortcutKeyText, const juce::Drawable* icon, + const juce::Colour* textColourToUse) override { + + juce::Colour backGroundColour = isHighlighted ? Colours::SURFACEHOVER : Colours::SURFACECOLOUR; + + g.fillAll(backGroundColour); + + g.setFont (Typography::getFont (Typography::Style::Mono, 1.0f)); + if (isTicked) { + juce::Colour textColour = isHighlighted ? Colours::ACCENTHOVER : Colours::ACCENTCOLOUR; + g.setColour (textColour); + } else { + juce::Colour textColour = isHighlighted ? Colours::FOREGROUNDHOVER : Colours::FOREGROUNDCOLOUR; + g.setColour (textColour); } - }; + g.drawFittedText (text, area.reduced (10), juce::Justification::centredLeft, 1); +} + + void drawComboBox(juce::Graphics& g, int width, int height, bool isButtonDown, + int buttonX, int buttonY, int buttonW, int buttonH, + juce::ComboBox& box) override +{ + auto bounds = juce::Rectangle(0, 0, (float)width, (float)height); + auto cornerSize = Shape::getRadius(Shape::RadiusMode::S, bounds); + + bool isHovered = box.isMouseOver(); + bool isEnabled = box.isEnabled(); + + juce::Colour bgColour; + if (!isEnabled) { + bgColour = Colours::SURFACEBYPASS; + } else if (isButtonDown) { + bgColour = Colours::SURFACEHOVER; + } else if (isHovered) { + bgColour = Colours::SURFACECOLOUR.brighter(0.1f); + } else { + bgColour = Colours::SURFACECOLOUR; + } + + g.setColour(bgColour); + g.fillRoundedRectangle(bounds, cornerSize); + + juce::Colour outlineColour; + if (!isEnabled) { + outlineColour = Colours::FOREGROUNDCOLOUR.withAlpha(0.2f); + } else if (isButtonDown) { + outlineColour = Colours::ACCENTCOLOUR; + } else if (isHovered) { + outlineColour = Colours::FOREGROUNDHOVER.withAlpha(0.5f); + } else { + outlineColour = Colours::FOREGROUNDCOLOUR.withAlpha(0.3f); + } + + auto strokeWidth = Shape::getStrokeWidth(Shape::StrokeMode::Thin); + g.setColour(outlineColour); + g.drawRoundedRectangle(bounds.reduced(strokeWidth * 0.5f), cornerSize, strokeWidth); + + auto arrowZone = juce::Rectangle((float)buttonX, (float)buttonY, + (float)buttonW, (float)buttonH); + + juce::Colour arrowColour = isEnabled ? Colours::ACCENTCOLOUR : Colours::ACCENTWEAKCOLOUR; + if (isHovered && isEnabled) { + arrowColour = Colours::ACCENTHOVER; + } + + g.setColour(arrowColour); + + juce::Path arrow; + auto arrowW = arrowZone.getWidth() * 0.3f; + auto arrowH = arrowZone.getHeight() * 0.15f; + auto centreX = arrowZone.getCentreX(); + auto centreY = arrowZone.getCentreY(); + + arrow.startNewSubPath(centreX - arrowW * 0.5f, centreY - arrowH * 0.5f); + arrow.lineTo(centreX, centreY + arrowH * 0.5f); + arrow.lineTo(centreX + arrowW * 0.5f, centreY - arrowH * 0.5f); + + g.strokePath(arrow, juce::PathStrokeType(1.5f)); +} + + void positionComboBoxText(juce::ComboBox& box, juce::Label& label) override + { + label.setBounds(8, 0, box.getWidth() - 30, box.getHeight()); + label.setFont(Typography::getFont(Typography::Style::Mono, 1.0f)); + label.setJustificationType(juce::Justification::centredLeft); + } + +private: + + + + +}; + + private: }; } diff --git a/CrystalizerEQ/JuceLibraryCode/BinaryData.cpp b/CrystalizerEQ/JuceLibraryCode/BinaryData.cpp index 1793c5d..214593e 100644 --- a/CrystalizerEQ/JuceLibraryCode/BinaryData.cpp +++ b/CrystalizerEQ/JuceLibraryCode/BinaryData.cpp @@ -11499,7 +11499,7 @@ static const unsigned char temp_binary_data_14[] = "\n" " \n" " \n" -" \n" +" \n" " \n" " \n" " \n" @@ -11525,51 +11525,51 @@ static const unsigned char temp_binary_data_14[] = " \n" " \n" " \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" " \n" ""; @@ -11692,7 +11692,7 @@ const char* getNamedResource (const char* resourceNameUTF8, int& numBytes) case 0x31532e06: numBytes = 353; return low_cut_icon_svg; case 0x7e8ca05e: numBytes = 410; return low_shelf_icon_svg; case 0x4df4bf1e: numBytes = 350; return preset_menu_icon_svg; - case 0xd842aaab: numBytes = 6343; return crystalize_button_active_icon_svg; + case 0xd842aaab: numBytes = 6341; return crystalize_button_active_icon_svg; case 0x885a7642: numBytes = 6279; return crystalize_button_passive_icon_svg; case 0xe49e0f15: numBytes = 406; return bypass_icon_svg; default: break; diff --git a/CrystalizerEQ/JuceLibraryCode/BinaryData.h b/CrystalizerEQ/JuceLibraryCode/BinaryData.h index 0afdacd..d5d6a91 100644 --- a/CrystalizerEQ/JuceLibraryCode/BinaryData.h +++ b/CrystalizerEQ/JuceLibraryCode/BinaryData.h @@ -51,7 +51,7 @@ namespace BinaryData const int preset_menu_icon_svgSize = 350; extern const char* crystalize_button_active_icon_svg; - const int crystalize_button_active_icon_svgSize = 6343; + const int crystalize_button_active_icon_svgSize = 6341; extern const char* crystalize_button_passive_icon_svg; const int crystalize_button_passive_icon_svgSize = 6279; diff --git a/CrystalizerEQ/PluginEditor.cpp b/CrystalizerEQ/PluginEditor.cpp index 47cf609..da4517b 100644 --- a/CrystalizerEQ/PluginEditor.cpp +++ b/CrystalizerEQ/PluginEditor.cpp @@ -22,13 +22,11 @@ using Components = DesignSystem::Components; using SliderStyles = Components::SliderStyles; - //region setupSliders void CrystalizerEQAudioProcessorEditor::setupSliders() { auto style = juce::Slider::RotaryHorizontalVerticalDrag; - for (auto* s : sliders) - { - s->setSliderStyle (style); + for (auto *s: sliders) { + s->setSliderStyle(style); } gainLookAndFeel = std::make_unique(); freqQLookAndFeel = std::make_unique(); @@ -47,90 +45,91 @@ void CrystalizerEQAudioProcessorEditor::setupSliders() { inputSlider.setLookAndFeel(globalLookAndFeel.get()); outputSlider.setLookAndFeel(globalLookAndFeel.get()); - for (auto* s : {&lowBandFreqSlider, &lowBandQSlider, &peak1FreqSlider, - &peak1QSlider, &peak2FreqSlider, &peak2QSlider, - &peak3FreqSlider, &peak3QSlider, &highBandFreqSlider, &highBandQSlider}) { + for (auto *s: { + &lowBandFreqSlider, &lowBandQSlider, &peak1FreqSlider, + &peak1QSlider, &peak2FreqSlider, &peak2QSlider, + &peak3FreqSlider, &peak3QSlider, &highBandFreqSlider, &highBandQSlider + }) { s->setLookAndFeel(freqQLookAndFeel.get()); - } + } lowBandSlopeSlider.setTextBoxStyle(juce::Slider::NoTextBox, true, 0, 0); highBandSlopeSlider.setTextBoxStyle(juce::Slider::NoTextBox, true, 0, 0); } + //endregion setupSliders //region setupAttachments void CrystalizerEQAudioProcessorEditor::setupAttachments() { - testNoiseAttach = std::make_unique(audioProcessor.apvts, "TestNoiseLevel", testNoiseSlider); - lowBandFreqAttach = std::make_unique(audioProcessor.apvts, "LowBandFreq", lowBandFreqSlider); - lowBandSlopeAttach = std::make_unique(audioProcessor.apvts, "LowBandSlope", lowBandSlopeSlider); - lowBandGainAttach = std::make_unique(audioProcessor.apvts, "LowBandGain", lowBandGainSlider); - lowBandQAttach = std::make_unique(audioProcessor.apvts, "LowBandQ", lowBandQSlider); + lowBandFreqAttach = std::make_unique(audioProcessor.apvts, "LowBandFreq", lowBandFreqSlider); + lowBandSlopeAttach = std::make_unique(audioProcessor.apvts, "LowBandSlope", lowBandSlopeSlider); + lowBandGainAttach = std::make_unique(audioProcessor.apvts, "LowBandGain", lowBandGainSlider); + lowBandQAttach = std::make_unique(audioProcessor.apvts, "LowBandQ", lowBandQSlider); - peak1FreqAttach = std::make_unique(audioProcessor.apvts, "Peak1Freq", peak1FreqSlider); - peak1GainAttach = std::make_unique(audioProcessor.apvts, "Peak1Gain", peak1GainSlider); - peak1QAttach = std::make_unique(audioProcessor.apvts, "Peak1Q", peak1QSlider); + peak1FreqAttach = std::make_unique(audioProcessor.apvts, "Peak1Freq", peak1FreqSlider); + peak1GainAttach = std::make_unique(audioProcessor.apvts, "Peak1Gain", peak1GainSlider); + peak1QAttach = std::make_unique(audioProcessor.apvts, "Peak1Q", peak1QSlider); - peak2FreqAttach = std::make_unique(audioProcessor.apvts, "Peak2Freq", peak2FreqSlider); - peak2GainAttach = std::make_unique(audioProcessor.apvts, "Peak2Gain", peak2GainSlider); - peak2QAttach = std::make_unique(audioProcessor.apvts, "Peak2Q", peak2QSlider); + peak2FreqAttach = std::make_unique(audioProcessor.apvts, "Peak2Freq", peak2FreqSlider); + peak2GainAttach = std::make_unique(audioProcessor.apvts, "Peak2Gain", peak2GainSlider); + peak2QAttach = std::make_unique(audioProcessor.apvts, "Peak2Q", peak2QSlider); - peak3FreqAttach = std::make_unique(audioProcessor.apvts, "Peak3Freq", peak3FreqSlider); - peak3GainAttach = std::make_unique(audioProcessor.apvts, "Peak3Gain", peak3GainSlider); - peak3QAttach = std::make_unique(audioProcessor.apvts, "Peak3Q", peak3QSlider); + peak3FreqAttach = std::make_unique(audioProcessor.apvts, "Peak3Freq", peak3FreqSlider); + peak3GainAttach = std::make_unique(audioProcessor.apvts, "Peak3Gain", peak3GainSlider); + peak3QAttach = std::make_unique(audioProcessor.apvts, "Peak3Q", peak3QSlider); - highBandFreqAttach = std::make_unique(audioProcessor.apvts, "HighBandFreq", highBandFreqSlider); - highBandSlopeAttach = std::make_unique(audioProcessor.apvts, "HighBandSlope", highBandSlopeSlider); - highBandGainAttach = std::make_unique(audioProcessor.apvts, "HighBandGain", highBandGainSlider); - highBandQAttach = std::make_unique(audioProcessor.apvts, "HighBandQ", highBandQSlider); + highBandFreqAttach = std::make_unique(audioProcessor.apvts, "HighBandFreq", highBandFreqSlider); + highBandSlopeAttach = std::make_unique(audioProcessor.apvts, "HighBandSlope", highBandSlopeSlider); + highBandGainAttach = std::make_unique(audioProcessor.apvts, "HighBandGain", highBandGainSlider); + highBandQAttach = std::make_unique(audioProcessor.apvts, "HighBandQ", highBandQSlider); inputAttach = std::make_unique(audioProcessor.apvts, "InputGain", inputSlider); outputAttach = std::make_unique(audioProcessor.apvts, "OutputGain", outputSlider); } + //endregion setupAttachments //region setupDisplayNames void CrystalizerEQAudioProcessorEditor::setupDisplayNames() { titleLabel.setText("Crystalizer", juce::dontSendNotification); - testNoiseSlider.setName("TestNoise"); lowBypass.setName("LowBypass"); lowBell.setName("LowBell"); lowCut.setName("LowCut"); lowShelf.setName("LowShelf"); lowBandModeBox.setName("LowBandModeBox"); - lowBandFreqSlider.setName ("LowBand Freq"); - lowBandSlopeSlider.setName ("LowBand Slope"); - lowBandGainSlider.setName ("LowBand Gain"); - lowBandQSlider.setName ("LowBand Q"); + lowBandFreqSlider.setName("LowBand Freq"); + lowBandSlopeSlider.setName("LowBand Slope"); + lowBandGainSlider.setName("LowBand Gain"); + lowBandQSlider.setName("LowBand Q"); peak1FreqSlider.setName("Peak1 Freq"); peak1GainSlider.setName("Peak1 Gain"); - peak1QSlider.setName ("Peak1 Q"); + peak1QSlider.setName("Peak1 Q"); peak2FreqSlider.setName("Peak2 Freq"); peak2GainSlider.setName("Peak2 Gain"); - peak2QSlider.setName ("Peak2 Q"); + peak2QSlider.setName("Peak2 Q"); peak3FreqSlider.setName("Peak3 Freq"); peak3GainSlider.setName("Peak3 Gain"); - peak3QSlider.setName ("Peak3 Q"); + peak3QSlider.setName("Peak3 Q"); highBypass.setName("HighBypass"); highBell.setName("HighBell"); highCut.setName("HighCut"); highShelf.setName("HighShelf"); highBandModeBox.setName("HighBandModeBox"); - highBandFreqSlider.setName ("HighBand Freq"); - highBandSlopeSlider.setName ("HighBand Slope"); - highBandGainSlider.setName ("HighBand Gain"); - highBandQSlider.setName ("HighBand Q"); + highBandFreqSlider.setName("HighBand Freq"); + highBandSlopeSlider.setName("HighBand Slope"); + highBandGainSlider.setName("HighBand Gain"); + highBandQSlider.setName("HighBand Q"); - inputSlider.setName ("Input"); - outputSlider.setName ("Output"); + inputSlider.setName("Input"); + outputSlider.setName("Output"); - testNoiseSlider.setTextValueSuffix(" Gain"); //lowBandFreqSlider.setTextValueSuffix ("\nHz"); //lowBandSlopeSlider.setTextValueSuffix ("\ndB/Oct"); @@ -156,13 +155,12 @@ void CrystalizerEQAudioProcessorEditor::setupDisplayNames() { //highBandFreqSlider.setTextValueSuffix ("\nHz"); //highBandSlopeSlider.setTextValueSuffix ("\ndB/Oct"); highBandGainSlider.setTextValueSuffix("\ndB"); - // highBandQSlider.setTextValueSuffix ("\nQ"); + // highBandQSlider.setTextValueSuffix ("\nQ"); inputSlider.setTextValueSuffix("\nIN"); outputSlider.setTextValueSuffix("\nOUT"); - testNoiseButton.setName("TestNoise"); - testNoiseButton.setButtonText("Test Noise"); + crystalizeButton.setName("CrystalizeButton"); @@ -176,8 +174,8 @@ void CrystalizerEQAudioProcessorEditor::setupDisplayNames() { deletePresetButton.setName("DeletePresetButton"); deletePresetButton.setButtonText("Delete Preset"); - } + //endregion setupDisplayNames //region setupToggleButtons @@ -210,72 +208,66 @@ void CrystalizerEQAudioProcessorEditor::setupToggleButtons() { highBell.setLookAndFeel(highBandButtonLookAndFeel.get()); highShelf.setLookAndFeel(highBandButtonLookAndFeel.get()); - for (auto* b : {&peak1BypassButton, &peak2BypassButton, &peak3BypassButton, &crystalizeButton, &masterBypassButton}) { + for (auto *b: { + &peak1BypassButton, &peak2BypassButton, &peak3BypassButton, &crystalizeButton, &masterBypassButton + }) { b->onClick = [this, b]() { juce::String paramID; // nimm juce::String statt std::string juce::String mode; if (b == &peak1BypassButton) { paramID = "Peak1Bypass"; mode = "Low-Mid"; - } - else if (b == &peak2BypassButton) { + } else if (b == &peak2BypassButton) { paramID = "Peak2Bypass"; mode = "Mid"; - } - else if (b == &peak3BypassButton) { + } else if (b == &peak3BypassButton) { paramID = "Peak3Bypass"; mode = "High-Mid"; - } - else if (b == &crystalizeButton) { + } else if (b == &crystalizeButton) { paramID = "CrystalizeButton"; - } - else if (b == &masterBypassButton) { + } else if (b == &masterBypassButton) { paramID = "MasterBypass"; mode = "Master"; } - if (auto* param = audioProcessor.apvts.getParameter(paramID)) - { + if (auto *param = audioProcessor.apvts.getParameter(paramID)) { const bool isToggled = b->getToggleState(); const float target = isToggled ? 1.0f : 0.0f; // Nur senden, wenn sich wirklich etwas ändert (Schwelle 0.5f) - if ((param->getValue() >= 0.5f) != isToggled) - { + if ((param->getValue() >= 0.5f) != isToggled) { param->beginChangeGesture(); param->setValueNotifyingHost(target); param->endChangeGesture(); } - if (mode == "Low-Mid") disableLowMidBand(target); - else if (mode == "Mid") disableMidBand(target); - else if (mode == "High-Mid") disableHighMidBand(target); - else if (mode == "Master") disableEverything(target); + if (mode == "Low-Mid") disableLowMidBand(target); + else if (mode == "Mid") disableMidBand(target); + else if (mode == "High-Mid") disableHighMidBand(target); + else if (mode == "Master") disableEverything(target); } if (b == &crystalizeButton) { isAnimatingCrystalize = true; isFadingToActive = (svgToggleButtonLookAndFeel->activeIconOpacity < 1.0f); } - }; } - } + //endregion setupToggleButtons //region disableLowBand void CrystalizerEQAudioProcessorEditor::disableLowBand(const float target) { bool isToggled = target <= 0.5f; - lowBandFreqSlider.setEnabled (isToggled); - lowBandFreqLabel.setEnabled (isToggled); - lowBandSlopeSlider.setEnabled (isToggled); - lowBandSlopeLabel.setEnabled (isToggled); + lowBandFreqSlider.setEnabled(isToggled); + lowBandFreqLabel.setEnabled(isToggled); + lowBandSlopeSlider.setEnabled(isToggled); + lowBandSlopeLabel.setEnabled(isToggled); lowBandGainSlider.setEnabled(isToggled); - lowBandGainLabel .setEnabled(isToggled); - lowBandQSlider .setEnabled(isToggled); - lowBandQLabel .setEnabled(isToggled); - + lowBandGainLabel.setEnabled(isToggled); + lowBandQSlider.setEnabled(isToggled); + lowBandQLabel.setEnabled(isToggled); }; //endregion disableLowBand @@ -289,6 +281,7 @@ void CrystalizerEQAudioProcessorEditor::disableLowMidBand(const float target) { peak1QLabel.setEnabled(isToggled); peak1FreqLabel.setEnabled(isToggled); } + //endregion disableLowMidBand //region disableMidBand @@ -301,6 +294,7 @@ void CrystalizerEQAudioProcessorEditor::disableMidBand(const float target) { peak2QLabel.setEnabled(isToggled); peak2FreqLabel.setEnabled(isToggled); } + //endregion disableMidBand //region disableHighMidBand @@ -313,19 +307,20 @@ void CrystalizerEQAudioProcessorEditor::disableHighMidBand(const float target) { peak3QLabel.setEnabled(isToggled); peak3FreqLabel.setEnabled(isToggled); } + //endregion disableHighMidBand //region disableHighBand void CrystalizerEQAudioProcessorEditor::disableHighBand(const float target) { bool isToggled = target <= 0.5f; - highBandFreqSlider.setEnabled (isToggled); - highBandFreqLabel.setEnabled (isToggled); - highBandSlopeSlider.setEnabled (isToggled); - highBandSlopeLabel.setEnabled (isToggled); + highBandFreqSlider.setEnabled(isToggled); + highBandFreqLabel.setEnabled(isToggled); + highBandSlopeSlider.setEnabled(isToggled); + highBandSlopeLabel.setEnabled(isToggled); highBandGainSlider.setEnabled(isToggled); - highBandGainLabel .setEnabled(isToggled); - highBandQSlider .setEnabled(isToggled); - highBandQLabel .setEnabled(isToggled); + highBandGainLabel.setEnabled(isToggled); + highBandQSlider.setEnabled(isToggled); + highBandQLabel.setEnabled(isToggled); }; //endregion disableHighBand @@ -333,23 +328,21 @@ void CrystalizerEQAudioProcessorEditor::disableHighBand(const float target) { void CrystalizerEQAudioProcessorEditor::disableEverything(const float target) { bool isToggled = target <= 0.5f; - for (auto* s : sliders) { + for (auto *s: sliders) { s->setEnabled(isToggled); } - for (auto* l : sliderLabels) { + for (auto *l: sliderLabels) { l->setEnabled(isToggled); } - for (auto*b : peakBypassButtons) { + for (auto *b: peakBypassButtons) { b->setEnabled(isToggled); const auto bypassTarget = b->getToggleState() ? 1.0f : 0.0f; if (b == &peak1BypassButton && isToggled) { disableLowMidBand(bypassTarget); - } - else if (b == &peak2BypassButton && isToggled) { + } else if (b == &peak2BypassButton && isToggled) { disableMidBand(bypassTarget); - } - else if (b == &peak3BypassButton && isToggled) { + } else if (b == &peak3BypassButton && isToggled) { disableHighMidBand(bypassTarget); } } @@ -364,7 +357,7 @@ void CrystalizerEQAudioProcessorEditor::disableEverything(const float target) { if (svgToggleButtonLookAndFeel->activeIconOpacity == 1.0f) { svgToggleButtonLookAndFeel->activeIconOpacity = 0.7f; crystalizeButton.repaint(); - }else if (svgToggleButtonLookAndFeel->passiveIconOpacity == 1.0f) { + } else if (svgToggleButtonLookAndFeel->passiveIconOpacity == 1.0f) { svgToggleButtonLookAndFeel->passiveIconOpacity = 0.7f; crystalizeButton.repaint(); } @@ -372,15 +365,13 @@ void CrystalizerEQAudioProcessorEditor::disableEverything(const float target) { if (svgToggleButtonLookAndFeel->activeIconOpacity == 0.7f) { svgToggleButtonLookAndFeel->activeIconOpacity = 1.0f; crystalizeButton.repaint(); - }else if (svgToggleButtonLookAndFeel->passiveIconOpacity == 0.7f) { + } else if (svgToggleButtonLookAndFeel->passiveIconOpacity == 0.7f) { svgToggleButtonLookAndFeel->passiveIconOpacity = 1.0f; crystalizeButton.repaint(); } } - - - } + //endregion disableEverything //region addComponentsToLayout @@ -397,16 +388,13 @@ void CrystalizerEQAudioProcessorEditor::addComponentsToLayout() { headerBar.addAndMakeVisible(presetMenu); - addAndMakeVisible(mainPanel); mainPanel.addAndMakeVisible(analyzerArea); mainPanel.addAndMakeVisible(crystalizeButton); //FILTERAREA { - mainPanel.addAndMakeVisible(filterArea); - - { + mainPanel.addAndMakeVisible(filterArea); { filterArea.addAndMakeVisible(lowFilterArea); lowBandModeBox.addAndMakeVisible(lowBandModeLabel); @@ -435,9 +423,7 @@ void CrystalizerEQAudioProcessorEditor::addComponentsToLayout() { lowFilterArea.addAndMakeVisible(lowBandGainSlider); lowFilterArea.addAndMakeVisible(lowBandQSlider); lowFilterArea.addAndMakeVisible(lowBandFreqSlider); - } - - { + } { filterArea.addAndMakeVisible(lowMidFilterArea); lowMidFilterArea.addAndMakeVisible(peak1FreqLabel); lowMidFilterArea.addAndMakeVisible(peak1GainLabel); @@ -446,9 +432,7 @@ void CrystalizerEQAudioProcessorEditor::addComponentsToLayout() { lowMidFilterArea.addAndMakeVisible(peak1GainSlider); lowMidFilterArea.addAndMakeVisible(peak1QSlider); lowMidFilterArea.addAndMakeVisible(peak1BypassButton); - } - - { + } { filterArea.addAndMakeVisible(midFilterArea); midFilterArea.addAndMakeVisible(peak2FreqLabel); midFilterArea.addAndMakeVisible(peak2GainLabel); @@ -457,9 +441,7 @@ void CrystalizerEQAudioProcessorEditor::addComponentsToLayout() { midFilterArea.addAndMakeVisible(peak2GainSlider); midFilterArea.addAndMakeVisible(peak2QSlider); midFilterArea.addAndMakeVisible(peak2BypassButton); - } - - { + } { filterArea.addAndMakeVisible(highMidFilterArea); highMidFilterArea.addAndMakeVisible(peak3FreqLabel); highMidFilterArea.addAndMakeVisible(peak3GainLabel); @@ -468,9 +450,7 @@ void CrystalizerEQAudioProcessorEditor::addComponentsToLayout() { highMidFilterArea.addAndMakeVisible(peak3GainSlider); highMidFilterArea.addAndMakeVisible(peak3QSlider); highMidFilterArea.addAndMakeVisible(peak3BypassButton); - } - - { + } { filterArea.addAndMakeVisible(highFilterArea); highBandModeBox.addAndMakeVisible(highBandModeLabel); @@ -499,7 +479,6 @@ void CrystalizerEQAudioProcessorEditor::addComponentsToLayout() { highFilterArea.addAndMakeVisible(highBandQSlider); highFilterArea.addAndMakeVisible(highBandFreqSlider); } - } @@ -509,25 +488,25 @@ void CrystalizerEQAudioProcessorEditor::addComponentsToLayout() { footerBar.addAndMakeVisible(globalControlArea); addAndMakeVisible(footerBar); } + //endregion addComponentsToLayout //region setupLabels void CrystalizerEQAudioProcessorEditor::setupLabels() { - auto setupLabel = [] (juce::Label& label, const juce::String& text) - { - label.setText (text, juce::dontSendNotification); - label.setJustificationType (juce::Justification::centred); - label.setColour (juce::Label::textColourId, juce::Colours::black); - label.setInterceptsMouseClicks (false, false); // Klicks gehen an den Slider + auto setupLabel = [](juce::Label &label, const juce::String &text) { + label.setText(text, juce::dontSendNotification); + label.setJustificationType(juce::Justification::centred); + label.setColour(juce::Label::textColourId, juce::Colours::black); + label.setInterceptsMouseClicks(false, false); // Klicks gehen an den Slider }; //SetupLabels { //LOW-BAND - setupLabel (lowBandFreqLabel, "Low\nHz"); - setupLabel (lowBandSlopeLabel, "Slope"); - setupLabel (lowBandGainLabel, "Low\nGain"); - setupLabel(lowBandQLabel, "Low\nQ"); + setupLabel(lowBandFreqLabel, "Low\nHz"); + setupLabel(lowBandSlopeLabel, "Slope"); + setupLabel(lowBandGainLabel, "Low\nGain"); + setupLabel(lowBandQLabel, "Low\nQ"); setupLabel(lowBandModeLabel, "Band Mode"); setupLabel(low12, "12"); setupLabel(low24, "24"); @@ -536,25 +515,25 @@ void CrystalizerEQAudioProcessorEditor::setupLabels() { setupLabel(lowdBOctLabel, "dB/Oct"); //PEAK 1 - setupLabel (peak1FreqLabel,"Low-Mid\nHz"); - setupLabel (peak1GainLabel,"Low-Mid\nGain"); - setupLabel (peak1QLabel, "Low-Mid\nQ"); + setupLabel(peak1FreqLabel, "Low-Mid\nHz"); + setupLabel(peak1GainLabel, "Low-Mid\nGain"); + setupLabel(peak1QLabel, "Low-Mid\nQ"); //PEAK 2 - setupLabel (peak2FreqLabel,"Mid\nHz"); - setupLabel (peak2GainLabel,"Mid\nGain"); - setupLabel (peak2QLabel, "Mid\nQ"); + setupLabel(peak2FreqLabel, "Mid\nHz"); + setupLabel(peak2GainLabel, "Mid\nGain"); + setupLabel(peak2QLabel, "Mid\nQ"); //PEAK 3 - setupLabel (peak3FreqLabel,"High-Mid\nHz"); - setupLabel (peak3GainLabel,"High-Mid\nGain"); - setupLabel (peak3QLabel, "High-Mid\nQ"); + setupLabel(peak3FreqLabel, "High-Mid\nHz"); + setupLabel(peak3GainLabel, "High-Mid\nGain"); + setupLabel(peak3QLabel, "High-Mid\nQ"); //HIGH-BAND - setupLabel (highBandFreqLabel, "High\nHz"); - setupLabel (highBandSlopeLabel, "Slope"); - setupLabel (highBandGainLabel, "High\nGain"); - setupLabel(highBandQLabel, "High\nQ"); + setupLabel(highBandFreqLabel, "High\nHz"); + setupLabel(highBandSlopeLabel, "Slope"); + setupLabel(highBandGainLabel, "High\nGain"); + setupLabel(highBandQLabel, "High\nQ"); setupLabel(highBandModeLabel, "Band Mode"); setupLabel(high12, "12"); setupLabel(high24, "24"); @@ -569,6 +548,7 @@ void CrystalizerEQAudioProcessorEditor::setupLabels() { setupLabel(outputLabel, "OUT");*/ } } + //endregion setupLabels void CrystalizerEQAudioProcessorEditor::setupFontsWithColours() { @@ -578,39 +558,32 @@ void CrystalizerEQAudioProcessorEditor::setupFontsWithColours() { Typography::applyToLabel(presetBoxLabel, Typography::Style::H3, 1.f); presetBoxLabel.setColour(juce::Label::textColourId, Colours::FOREGROUNDCOLOUR); - for (auto* l : sliderLabels) { + for (auto *l: sliderLabels) { l->setColour(juce::Label::textColourId, Colours::FOREGROUNDCOLOUR); Typography::applyToLabel(*l, Typography::Style::Mono, 1.f); - } - } //region setupSliderTextBoxes void CrystalizerEQAudioProcessorEditor::setupSliderTextBoxes() { baseLookAndFeel = std::make_unique(); - for (auto* s : sliders) { + for (auto *s: sliders) { s->setLookAndFeel(baseLookAndFeel.get()); } } + //endregion setupSliderTextBoxes //region handleLowBandModes void CrystalizerEQAudioProcessorEditor::handleLowBandModes() { - for (int i = 0; i < lowBandModeButtons.size(); ++i) - { - lowBandModeButtons[i]->onClick = [this, i] - { - if (!lowBandBools[i]) - { - if (auto* param = audioProcessor.apvts.getParameter("LowBandModes")) - { + for (int i = 0; i < lowBandModeButtons.size(); ++i) { + lowBandModeButtons[i]->onClick = [this, i] { + if (!lowBandBools[i]) { + if (auto *param = audioProcessor.apvts.getParameter("LowBandModes")) { param->beginChangeGesture(); - for (int j = 0; j < lowBandBools.size(); ++j) - { - if (j != i) - { + for (int j = 0; j < lowBandBools.size(); ++j) { + if (j != i) { lowBandBools[j] = false; param->setValueNotifyingHost(param->convertTo0to1(0.0f)); lowBandModeButtons[j]->setToggleState(false, juce::dontSendNotification); @@ -618,59 +591,56 @@ void CrystalizerEQAudioProcessorEditor::handleLowBandModes() { } // Aktuellen aktivieren lowBandBools[i] = true; - param->setValueNotifyingHost(param->convertTo0to1((float)i)); + param->setValueNotifyingHost(param->convertTo0to1((float) i)); param->endChangeGesture(); + + updateFrequencyRanges(); } - } - else if (lowBandBools[i]) { + } else if (lowBandBools[i]) { lowBandModeButtons[i]->setToggleState(true, juce::dontSendNotification); } }; } } + //endregion handleLowBandModes //region handleHighBandModes void CrystalizerEQAudioProcessorEditor::handleHighBandModes() { - for (int i = 0; i < highBandModeButtons.size(); ++i) - { - highBandModeButtons[i]->onClick = [this, i] - { - if (!highBandBools[i]) - { - if (auto* param = audioProcessor.apvts.getParameter("HighBandModes")) - { + for (int i = 0; i < highBandModeButtons.size(); ++i) { + highBandModeButtons[i]->onClick = [this, i] { + if (!highBandBools[i]) { + if (auto *param = audioProcessor.apvts.getParameter("HighBandModes")) { param->beginChangeGesture(); - for (int j = 0; j < highBandBools.size(); ++j) - { - if (j != i) - { + for (int j = 0; j < highBandBools.size(); ++j) { + if (j != i) { highBandBools[j] = false; param->setValueNotifyingHost(param->convertTo0to1(0.0f)); highBandModeButtons[j]->setToggleState(false, juce::dontSendNotification); } } highBandBools[i] = true; - param->setValueNotifyingHost(param->convertTo0to1((float)i)); + param->setValueNotifyingHost(param->convertTo0to1((float) i)); param->endChangeGesture(); + updateFrequencyRanges(); } - } - else if (highBandBools[i]) { + + } else if (highBandBools[i]) { highBandModeButtons[i]->setToggleState(true, juce::dontSendNotification); } }; } } + //endregion handleHighBandModes - + //region setupEventListeners void CrystalizerEQAudioProcessorEditor::setupEventListeners() { presetMenuButton.onClick = [this]() { - - auto* menu = new DesignSystem::PresetMenu(&presetNameInput, &savePresetButton, &deletePresetButton); + auto *menu = new DesignSystem::PresetMenu(&presetNameInput, &savePresetButton, &deletePresetButton); const auto presetMenuBounds = presetMenu.getLocalBounds(); menu->setBounds(presetMenuBounds); @@ -678,24 +648,26 @@ void CrystalizerEQAudioProcessorEditor::setupEventListeners() { juce::Rectangle areaToPointTo = presetMenuButton.getScreenBounds(); - auto* menuRaw = menu; + auto *menuRaw = menu; presetMenuSafePtr = menuRaw; - auto& box = juce::CallOutBox::launchAsynchronously( + auto &box = juce::CallOutBox::launchAsynchronously( std::unique_ptr(menu), areaToPointTo, nullptr ); box.setLookAndFeel(presetMenuLookAndFeel.get()); - + /*juce::Timer::callAfterDelay(100, [this]() { + presetNameInput.giveAwayKeyboardFocus(); + });*/ }; savePresetButton.onClick = [this]() { if (presetNameInput.getText() != "") - audioProcessor.setPresetName (presetNameInput.getText()); + audioProcessor.setPresetName(presetNameInput.getText()); else - audioProcessor.setPresetName ("Preset"); + audioProcessor.setPresetName("Preset"); const auto presetName = audioProcessor.savePresetToFile(); @@ -705,15 +677,12 @@ void CrystalizerEQAudioProcessorEditor::setupEventListeners() { const auto updatedPresets = audioProcessor.getPresetNamesArray(); presetBox.addItemList(updatedPresets, 1); - for (int i = 0; i < presetBox.getNumItems(); i++) - { + for (int i = 0; i < presetBox.getNumItems(); i++) { if (presetName != presetBox.getItemText(i)) continue; presetBox.setSelectedId(i + 1, juce::dontSendNotification); } presetNameInput.setText(""); - - }; deletePresetButton.onClick = [this]() { @@ -727,80 +696,96 @@ void CrystalizerEQAudioProcessorEditor::setupEventListeners() { const auto updatedPresets = audioProcessor.getPresetNamesArray(); presetBox.addItemList(updatedPresets, 1); presetBox.setSelectedId(1, juce::dontSendNotification); - }; presetBox.onChange = [this]() { auto selectedPreset = presetBox.getText(); if (selectedPreset == "Init") { audioProcessor.resetAllParameters(); + updateModeButtons(); return; } const auto selectedPresetWithExt = selectedPreset + ".xml"; audioProcessor.loadPreset(selectedPresetWithExt); + updateModeButtons(); // ← NEU! + updateFrequencyRanges(); }; - resetButton.onClick = [this]() - { + resetButton.onClick = [this]() { audioProcessor.resetAllParameters(); if (crystalizeButton.getToggleState()) { isAnimatingCrystalize = true; isFadingToActive = (svgToggleButtonLookAndFeel->activeIconOpacity < 1.0f); } resetAllCheckboxes(); - for (auto* s : sliders) { + for (auto *s: sliders) { s->setEnabled(true); } - for (auto* l : sliderLabels) { + for (auto *l: sliderLabels) { l->setEnabled(true); } presetBox.setSelectedId(1, juce::dontSendNotification); - - - + updateFrequencyRanges(); }; handleLowBandModes(); handleHighBandModes(); - - + presetNameInput.onMouseDown = [this]() { + inputFocused = true; + }; } -//endregion setupEventListeners +//endregion setupEventListeners +void CrystalizerEQAudioProcessorEditor::updateModeButtons() { + // Low Band Modes aktualisieren + int lowMode = static_cast(audioProcessor.apvts.getRawParameterValue("LowBandModes")->load()); + + for (int i = 0; i < lowBandModeButtons.size(); ++i) { + lowBandBools[i] = (i == lowMode); + lowBandModeButtons[i]->setToggleState(lowBandBools[i], juce::dontSendNotification); + } + + // High Band Modes aktualisieren + int highMode = static_cast(audioProcessor.apvts.getRawParameterValue("HighBandModes")->load()); + + for (int i = 0; i < highBandModeButtons.size(); ++i) { + highBandBools[i] = (i == highMode); + highBandModeButtons[i]->setToggleState(highBandBools[i], juce::dontSendNotification); + } +} //region initPresetSystem void CrystalizerEQAudioProcessorEditor::initPresetSystem() { auto presets = audioProcessor.getPresetNamesArray(); presetBox.addItemList(presets, 1); presetBox.setSelectedId(1, juce::dontSendNotification); - presetMenuButton.setName("PresetMenuButton"); - presetMenuButton.setColour (juce::ToggleButton::textColourId, juce::Colours::black); + presetMenuButton.setColour(juce::ToggleButton::textColourId, juce::Colours::black); presetMenuButton.setColour(juce::ToggleButton::tickColourId, juce::Colours::black); presetMenuButton.setToggleState(false, juce::dontSendNotification); - presetNameInput.setTextToShowWhenEmpty("Preset Name", juce::Colours::grey); presetNameInput.setJustification(juce::Justification::centred); - presetNameInput.setColour(juce::TextEditor::backgroundColourId, juce::Colours::black); - presetNameInput.setColour(juce::TextEditor::textColourId, juce::Colours::white); + presetButtonLookAndFeel = std::make_unique(); presetComboBoxLookAndFeel = std::make_unique(); + presetInputLookAndFeel = std::make_unique(); savePresetButton.setLookAndFeel(presetButtonLookAndFeel.get()); deletePresetButton.setLookAndFeel(presetButtonLookAndFeel.get()); resetButton.setLookAndFeel(presetButtonLookAndFeel.get()); - // TODO: presetBox.setLookAndFeel(presetComboBoxLookAndFeel.get()); + presetNameInput.setLookAndFeel(presetInputLookAndFeel.get()); + presetBox.setLookAndFeel(presetComboBoxLookAndFeel.get()); } + //endregion initPresetSystem //============================================================================== -CrystalizerEQAudioProcessorEditor::CrystalizerEQAudioProcessorEditor (CrystalizerEQAudioProcessor& p) - : AudioProcessorEditor (&p), audioProcessor (p), spectrumAnalyzer(p.audioFIFO, p) { - - setSize (1280, 720); +CrystalizerEQAudioProcessorEditor::CrystalizerEQAudioProcessorEditor(CrystalizerEQAudioProcessor &p) + : AudioProcessorEditor(&p), audioProcessor(p), spectrumAnalyzer(p.audioFIFO, p) { + setSize(1280, 720); startTimerHz(60); addComponentsToLayout(); setupLabels(); @@ -813,40 +798,18 @@ CrystalizerEQAudioProcessorEditor::CrystalizerEQAudioProcessorEditor (Crystalize setupSliderTextBoxes(); setupSliders(); initPresetSystem(); + updateFrequencyRanges(); - - - auto logoIcon = juce::XmlDocument::parse (BinaryData::logo_icon_svg); + auto logoIcon = juce::XmlDocument::parse(BinaryData::logo_icon_svg); if (logoIcon != nullptr) - logoDrawable = juce::Drawable::createFromSVG (*logoIcon); - - addAndMakeVisible (testNoiseButton); - - testNoiseButton.onClick = [this]() { - if (auto* param = audioProcessor.apvts.getParameter("TestNoiseEnabled")) - { - if (param->getValue() == false) { - param->beginChangeGesture(); - - param->setValueNotifyingHost (1.0f); - - param->endChangeGesture(); - } else { - param->beginChangeGesture(); - - param->setValueNotifyingHost (0.0f); // -> true - - param->endChangeGesture(); - } - } - }; + logoDrawable = juce::Drawable::createFromSVG(*logoIcon); } CrystalizerEQAudioProcessorEditor::~CrystalizerEQAudioProcessorEditor() { stopTimer(); - for (auto* s : sliders) { + for (auto *s: sliders) { s->setLookAndFeel(nullptr); } peak1BypassButton.setLookAndFeel(nullptr); @@ -855,45 +818,33 @@ CrystalizerEQAudioProcessorEditor::~CrystalizerEQAudioProcessorEditor() { masterBypassButton.setLookAndFeel(nullptr); crystalizeButton.setLookAndFeel(nullptr); presetMenuButton.setLookAndFeel(nullptr); + presetNameInput.setLookAndFeel(nullptr); + presetBox.setLookAndFeel(nullptr); - for (auto* b : lowBandModeButtons) { + for (auto *b: lowBandModeButtons) { b->setLookAndFeel(nullptr); } - for (auto* b : highBandModeButtons) { + for (auto *b: highBandModeButtons) { b->setLookAndFeel(nullptr); } }; float CrystalizerEQAudioProcessorEditor::getInterpolatedDb(float exactBin) { - int bin0 = static_cast(std::floor(exactBin)) - 1; int bin1 = static_cast(std::floor(exactBin)); int bin2 = static_cast(std::ceil(exactBin)); - int bin3 = static_cast(std::ceil(exactBin)) + 1; const int maxBin = static_cast(spectrumAnalyzer.renderValuesDb.size()) - 1; - bin0 = juce::jlimit(0, maxBin, bin0); bin1 = juce::jlimit(0, maxBin, bin1); bin2 = juce::jlimit(0, maxBin, bin2); - bin3 = juce::jlimit(0, maxBin, bin3); - float y0 = spectrumAnalyzer.renderValuesDb[bin0]; - float y1 = spectrumAnalyzer.renderValuesDb[bin1]; - float y2 = spectrumAnalyzer.renderValuesDb[bin2]; - float y3 = spectrumAnalyzer.renderValuesDb[bin3]; + if (bin1 == bin2) return spectrumAnalyzer.renderValuesDb[bin1]; + + float y1 = juce::jlimit(spectrumAnalyzer.MINDB, spectrumAnalyzer.MAXDB, spectrumAnalyzer.renderValuesDb[bin1]); + float y2 = juce::jlimit(spectrumAnalyzer.MINDB, spectrumAnalyzer.MAXDB, spectrumAnalyzer.renderValuesDb[bin2]); float fraction = exactBin - bin1; - - // Catmull-Rom Spline Interpolation - float a0 = -0.5f * y0 + 1.5f * y1 - 1.5f * y2 + 0.5f * y3; - float a1 = y0 - 2.5f * y1 + 2.0f * y2 - 0.5f * y3; - float a2 = -0.5f * y0 + 0.5f * y2; - float a3 = y1; - - return a0 * fraction * fraction * fraction + - a1 * fraction * fraction + - a2 * fraction + - a3; + return y1 + fraction * (y2 - y1); } //region paintAnalyzer @@ -922,9 +873,11 @@ void CrystalizerEQAudioProcessorEditor::paintAnalyzer(juce::Graphics &g) { const float minDb = spectrumAnalyzer.MINDB; const float maxDb = spectrumAnalyzer.MAXDB; const float dbRange = maxDb - minDb; // = 96 dB + const float zeroDbY = analyzerBottom - (analyzerHeight * (0.0f - minDb) / dbRange); // Position von 0dB - const float minFreq = spectrumAnalyzer.MINFREQ; // 20 Hz + + const float minFreq = spectrumAnalyzer.MINFREQ; // 20 Hz const float maxFreq = spectrumAnalyzer.MAXFREQ; // 20 kHz float sampleRate = spectrumAnalyzer.sampleRate; @@ -1001,7 +954,7 @@ float CrystalizerEQAudioProcessorEditor::mapFrequencyToX(float freq, float minFr return normalized * width; } -void CrystalizerEQAudioProcessorEditor::drawFrequencyGrid(juce::Graphics& g, const float dbRange) { +void CrystalizerEQAudioProcessorEditor::drawFrequencyGrid(juce::Graphics &g, const float dbRange) { g.setColour(Colours::FOREGROUNDCOLOUR.withAlpha(0.3f)); const float minFreq = spectrumAnalyzer.MINFREQ; @@ -1013,7 +966,7 @@ void CrystalizerEQAudioProcessorEditor::drawFrequencyGrid(juce::Graphics& g, con const float analyzerHeight = analyzerRect.getHeight(); const float analyzerBottom = analyzerRect.getBottom(); - std::vector gridFreqs = {0, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000}; + std::vector gridFreqs = {50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000}; std::vector gridDB = {0, -12, -24, -36, -48, -60, -72}; @@ -1028,21 +981,21 @@ void CrystalizerEQAudioProcessorEditor::drawFrequencyGrid(juce::Graphics& g, con float pixelHeight = normalized * analyzerHeight; float y = analyzerBottom - pixelHeight; - g.drawHorizontalLine(static_cast(y), static_cast(analyzerRect.getX()), static_cast(analyzerRect.getRight())); + g.drawHorizontalLine(static_cast(y), static_cast(analyzerRect.getX()), + static_cast(analyzerRect.getRight())); g.setFont(Typography::getFont(Typography::Style::Mono, 1.0f)); juce::String label = juce::String(gridDB[i]); g.drawText(label, analyzerRect.getX(), y, 30, 15, juce::Justification::centred); - } - for (float freq : gridFreqs) { + for (float freq: gridFreqs) { float x = mapFrequencyToX(freq, minFreq, maxFreq, analyzerWidth); x += analyzerRect.getX(); g.drawVerticalLine(static_cast(x), - static_cast(analyzerRect.getY()), - static_cast(analyzerRect.getBottom())); + static_cast(analyzerRect.getY()), + static_cast(analyzerRect.getBottom())); // Optional: Frequenz-Label zeichnen if (freq == 20) continue; @@ -1051,19 +1004,18 @@ void CrystalizerEQAudioProcessorEditor::drawFrequencyGrid(juce::Graphics& g, con g.drawText(label, static_cast(x) - 15, analyzerRect.getY(), 30, 15, juce::Justification::centred); } - } //endregion paintAnalyzer void CrystalizerEQAudioProcessorEditor::paintModeBoxBorders(juce::Graphics &g) { - for (auto* b : lowBandModeButtons) { + for (auto *b: lowBandModeButtons) { if (b->getToggleState()) { auto r = getLocalArea(&lowBandModeBox, b->getBounds()); int side = juce::jmin(r.getWidth(), r.getHeight()); r = r.withSizeKeepingCentre(side, side); - auto rf = r.toFloat(); + auto rf = r.toFloat(); auto rfFilled = rf.toNearestInt().toFloat(); const float stroke = 1.0f; auto rfStroke = rfFilled.reduced(stroke * 0.5f); @@ -1074,16 +1026,12 @@ void CrystalizerEQAudioProcessorEditor::paintModeBoxBorders(juce::Graphics &g) { g.drawRoundedRectangle(rfStroke, 5, stroke); } } - - } //============================================================================== -void CrystalizerEQAudioProcessorEditor::paint (juce::Graphics& g) -{ - - g.fillAll (Colours::BACKGROUNDCOLOUR); - g.setColour (AXIOM::DesignSystem::Colours::FOREGROUNDCOLOUR); +void CrystalizerEQAudioProcessorEditor::paint(juce::Graphics &g) { + g.fillAll(Colours::BACKGROUNDCOLOUR); + g.setColour(AXIOM::DesignSystem::Colours::FOREGROUNDCOLOUR); const auto mP = getLocalArea(&mainPanel, mainPanel.getLocalBounds()); @@ -1102,10 +1050,7 @@ void CrystalizerEQAudioProcessorEditor::paint (juce::Graphics& g) auto hBPad = ((hBY + mPY) - hBH) / 2; g.fillRect(hBX, hBY, hBW, mPY - hBPad); - const auto logoArea = hB.toFloat().reduced(hBPad); - logoDrawable->drawWithin(g, logoArea, - juce::RectanglePlacement::xRight, // oder xLeft, yTop etc. - 1.0f); + g.setColour(Colours::SURFACECOLOUR); const auto pA = getLocalArea(&presetArea, presetArea.getLocalBounds()); @@ -1115,8 +1060,11 @@ void CrystalizerEQAudioProcessorEditor::paint (juce::Graphics& g) auto pAHeight = pA.getHeight(); g.fillRoundedRectangle(pAX, pAY - 10.f, pAWidth, pAHeight + 10.f, 10.0f); + /*auto logoArea = hB.toFloat().reduced(hBPad); + logoArea = logoArea.withLeft(pAWidth + pAWidth / 2 + pAWidth / 4 + pAWidth / 8); + logoDrawable->drawWithin(g, logoArea, juce::RectanglePlacement::centred, 1.0f);*/ const auto fA = getLocalArea(&filterArea, filterArea.getLocalBounds()); @@ -1128,7 +1076,7 @@ void CrystalizerEQAudioProcessorEditor::paint (juce::Graphics& g) g.setColour(Colours::SURFACECOLOUR); g.fillRect(fABorder); - fABorder = fABorder.withX(fABorder.getX() - 2* fABorderWidth).withY(fABorder.getY() - 2 * fABorderWidth); + fABorder = fABorder.withX(fABorder.getX() - 2 * fABorderWidth).withY(fABorder.getY() - 2 * fABorderWidth); //g.setColour(Colours::FOREGROUNDBYPASS); g.fillRect(fABorder); @@ -1142,140 +1090,12 @@ void CrystalizerEQAudioProcessorEditor::paint (juce::Graphics& g) g.fillRect(fB); paintBorderLines(g); + /* + auto logoArea = fB.toFloat().reduced(hBPad); - if constexpr (false) // -> auf false setzen, wenn nicht gebraucht - { - for (auto* c : getChildren()) // headerBar, mainPanel, footerBar - { - auto r = c->getBounds(); - g.setColour(juce::Colours::magenta.withAlpha(0.9f)); - g.drawRect(r, 1.0f); // nur Rahmen, kein fillRect - g.setColour(juce::Colours::white); - g.drawText(c->getName(), r, juce::Justification::centred, false); - } - for (auto* c : headerBar.getChildren()) - { + logoDrawable->drawWithin(g, logoArea, juce::RectanglePlacement::xLeft, 1.0f); + */ - auto r = c->getBounds(); // <-- lokal zu headerBar - r = r.translated(headerBar.getX(), headerBar.getY()); // <-- in Editor-Koordinaten bringen! - g.setColour(juce::Colours::cyan.withAlpha(0.3f)); - g.fillRect(r); - g.setColour(juce::Colours::cyan.withAlpha(0.9f)); - g.drawRect(r, 1.0f); - } - for (auto* c : presetArea.getChildren()) - { - auto r = c->getBounds(); // lokal in presetArea - r = r.translated(headerBar.getX() + presetArea.getX(), - headerBar.getY() + presetArea.getY()); // beide Offsets addieren - g.setColour(juce::Colours::yellow.withAlpha(0.3f)); - g.fillRect(r); - g.setColour(juce::Colours::yellow.withAlpha(0.9f)); - g.drawRect(r, 1.0f); - } - - for (auto* c : mainPanel.getChildren()) - { - - auto r = c->getBounds(); // <-- lokal zu headerBar - r = r.translated(mainPanel.getX(), mainPanel.getY()); // <-- in Editor-Koordinaten bringen! - g.setColour(juce::Colours::cyan.withAlpha(0.3f)); - g.fillRect(r); - g.setColour(juce::Colours::cyan.withAlpha(0.9f)); - g.drawRect(r, 1.0f); - } - - - - for (auto* c : filterArea.getChildren()) - { - auto r = c->getBounds(); // lokal in presetArea - r = r.translated(mainPanel.getX() + filterArea.getX(), - mainPanel.getY() + filterArea.getY()); // beide Offsets addieren - g.setColour(juce::Colours::yellow.withAlpha(0.3f)); - g.fillRect(r); - g.setColour(juce::Colours::yellow.withAlpha(0.9f)); - g.drawRect(r, 1.0f); - } - { - for (auto* c : lowFilterArea.getChildren()) - { - auto r = getLocalArea(&lowFilterArea, c->getBounds()); // lokal in presetArea - - g.setColour(juce::Colours::cyan.withAlpha(0.3f)); - g.fillRect(r); - g.setColour(juce::Colours::cyan.withAlpha(0.9f)); - g.drawRect(r, 1.0f); - } - for (auto* c : lowBandModeBox.getChildren()) - { - auto r = getLocalArea(&lowBandModeBox, c->getBounds()); // lokal in presetArea - - g.setColour(juce::Colours::yellow.withAlpha(0.3f)); - g.fillRect(r); - g.setColour(juce::Colours::yellow.withAlpha(0.9f)); - g.drawRect(r, 1.0f); - } - for (auto* c : lowMidFilterArea.getChildren()) - { - auto r = getLocalArea(&lowMidFilterArea, c->getBounds()); // lokal in presetArea - - g.setColour(juce::Colours::cyan.withAlpha(0.3f)); - g.fillRect(r); - g.setColour(juce::Colours::cyan.withAlpha(0.9f)); - g.drawRect(r, 1.0f); - } - for (auto* c : midFilterArea.getChildren()) - { - auto r = getLocalArea(&midFilterArea, c->getBounds()); // lokal in presetArea - - g.setColour(juce::Colours::cyan.withAlpha(0.3f)); - g.fillRect(r); - g.setColour(juce::Colours::cyan.withAlpha(0.9f)); - g.drawRect(r, 1.0f); - } - for (auto* c : highMidFilterArea.getChildren()) - { - auto r = getLocalArea(&highMidFilterArea, c->getBounds()); // lokal in presetArea - - g.setColour(juce::Colours::cyan.withAlpha(0.3f)); - g.fillRect(r); - g.setColour(juce::Colours::cyan.withAlpha(0.9f)); - g.drawRect(r, 1.0f); - } - for (auto* c : highFilterArea.getChildren()) - { - auto r = getLocalArea(&highFilterArea, c->getBounds()); // lokal in presetArea - - g.setColour(juce::Colours::cyan.withAlpha(0.3f)); - g.fillRect(r); - g.setColour(juce::Colours::cyan.withAlpha(0.9f)); - g.drawRect(r, 1.0f); - } - } - - for (auto* c : footerBar.getChildren()) - { - - auto r = c->getBounds(); // <-- lokal zu headerBar - r = r.translated(footerBar.getX(), footerBar.getY()); // <-- in Editor-Koordinaten bringen! - g.setColour(juce::Colours::cyan.withAlpha(0.3f)); - g.fillRect(r); - g.setColour(juce::Colours::cyan.withAlpha(0.9f)); - g.drawRect(r, 1.0f); - } - - for (auto* c : globalControlArea.getChildren()) - { - auto r = getLocalArea(&globalControlArea, c->getBounds()); // lokal in presetArea - - g.setColour(juce::Colours::yellow.withAlpha(0.3f)); - g.fillRect(r); - g.setColour(juce::Colours::yellow.withAlpha(0.9f)); - g.drawRect(r, 1.0f); - } - - } } //region paintBorderLines @@ -1283,12 +1103,12 @@ void CrystalizerEQAudioProcessorEditor::paintBorderLines(juce::Graphics &g) { g.setColour(DesignSystem::Colours::BACKGROUNDCOLOUR); auto prevRight = (float) lowFilterArea.getRight(); - for (auto* c : filterAreas) { + for (auto *c: filterAreas) { if (c == &lowFilterArea) continue; const auto area = getLocalArea(c, c->getLocalBounds()); const float xAvg = ((float) area.getX() - prevRight) / 2; - const int x = area.getX() - xAvg + (filterAreaMargin / 2); + const int x = area.getX() - xAvg + (filterAreaMargin / 2); prevRight = (float) c->getRight(); const auto top = (float) area.getY(); @@ -1297,18 +1117,17 @@ void CrystalizerEQAudioProcessorEditor::paintBorderLines(juce::Graphics &g) { const float center = (top + bot) * 0.5f; const float halfLen = (bot - top) * 0.375f; - g.drawVerticalLine(x,center - halfLen, center + halfLen); - + g.drawVerticalLine(x, center - halfLen, center + halfLen); } g.setColour(DesignSystem::Colours::SURFACECOLOUR); auto prevRightGlobal = (float) globalControlArea.getRight(); - for (auto* c : globalControlArea.getChildren()) { + for (auto *c: globalControlArea.getChildren()) { if (c == &inputSlider) continue; if (c == &masterBypassButton) continue; const auto area = getLocalArea(c, c->getLocalBounds()); const float xAvg = ((float) area.getX() - prevRightGlobal) / 2; - const int x = area.getX() - xAvg; + const int x = area.getX() - xAvg; prevRightGlobal = (float) c->getRight(); const auto top = (float) area.getY(); @@ -1317,9 +1136,10 @@ void CrystalizerEQAudioProcessorEditor::paintBorderLines(juce::Graphics &g) { const float center = (top + bot) * 0.5f; const float halfLen = (bot - top) * 0.375f; - g.drawVerticalLine(x,center - halfLen, center + halfLen); + g.drawVerticalLine(x, center - halfLen, center + halfLen); } } + //endregion paintBorderLines //region setKnobVisibility @@ -1334,16 +1154,16 @@ void CrystalizerEQAudioProcessorEditor::setKnobVisibility() { disableLowBand(target); } - lowBandFreqSlider.setEnabled (lowMode >= 1); - lowBandFreqLabel.setEnabled (lowMode >= 1); - lowBandSlopeSlider.setEnabled (lowMode == 1); - lowBandSlopeLabel.setEnabled (lowMode == 1); - lowdBOctLabel.setEnabled (lowMode == 1); + lowBandFreqSlider.setEnabled(lowMode >= 1); + lowBandFreqLabel.setEnabled(lowMode >= 1); + lowBandSlopeSlider.setEnabled(lowMode == 1); + lowBandSlopeLabel.setEnabled(lowMode == 1); + lowdBOctLabel.setEnabled(lowMode == 1); lowBandGainSlider.setEnabled(lowMode >= 2); - lowBandGainLabel .setEnabled(lowMode >= 2); - lowBandQSlider .setEnabled(lowMode >= 1); - lowBandQLabel .setEnabled(lowMode >= 1); - lowBandModeLabel.setEnabled (lowMode >= 1); + lowBandGainLabel.setEnabled(lowMode >= 2); + lowBandQSlider.setEnabled(lowMode >= 1); + lowBandQLabel.setEnabled(lowMode >= 1); + lowBandModeLabel.setEnabled(lowMode >= 1); int highMode = (int) audioProcessor.apvts .getRawParameterValue("HighBandModes")->load(); // 0..3 @@ -1352,43 +1172,85 @@ void CrystalizerEQAudioProcessorEditor::setKnobVisibility() { highMode = 0; disableHighBand(target); } - highBandFreqSlider.setEnabled (highMode >= 1); - highBandFreqLabel.setEnabled (highMode >= 1); - highBandSlopeSlider.setEnabled (highMode == 1); - highBandSlopeLabel.setEnabled (highMode == 1); - highdBOctLabel.setEnabled (highMode == 1); + highBandFreqSlider.setEnabled(highMode >= 1); + highBandFreqLabel.setEnabled(highMode >= 1); + highBandSlopeSlider.setEnabled(highMode == 1); + highBandSlopeLabel.setEnabled(highMode == 1); + highdBOctLabel.setEnabled(highMode == 1); highBandGainSlider.setEnabled(highMode >= 2); - highBandGainLabel .setEnabled(highMode >= 2); - highBandQSlider .setEnabled(highMode >= 1); - highBandQLabel .setEnabled(highMode >= 1); - highBandModeLabel.setEnabled (highMode >= 1); + highBandGainLabel.setEnabled(highMode >= 2); + highBandQSlider.setEnabled(highMode >= 1); + highBandQLabel.setEnabled(highMode >= 1); + highBandModeLabel.setEnabled(highMode >= 1); } + //endregion setKnobVisibility +void CrystalizerEQAudioProcessorEditor::updateFrequencyRanges() +{ + // Low Band Range anpassen + int lowMode = (int)audioProcessor.apvts.getRawParameterValue("LowBandModes")->load(); + + if (lowMode == 3) // Bell Mode + { + // Begrenzter Bereich für Low Bell + lowBandFreqSlider.setRange(20.0, 500.0, 1.0); + + // Aktuellen Wert prüfen und ggf. anpassen + float currentFreq = audioProcessor.apvts.getRawParameterValue("LowBandFreq")->load(); + if (currentFreq > 500.0f) + { + lowBandFreqSlider.setValue(500.0, juce::sendNotificationSync); + } + } + else if (lowMode >= 1) // Cut oder Shelf Mode + { + // Volle Bandbreite + lowBandFreqSlider.setRange(20.0, 20000.0, 1.0); + } + + lowBandFreqSlider.repaint(); + // High Band Range anpassen + int highMode = (int)audioProcessor.apvts.getRawParameterValue("HighBandModes")->load(); + + if (highMode == 3) // Bell Mode + { + // Begrenzter Bereich für High Bell + highBandFreqSlider.setRange(8000.0, 20000.0, 1.0); + + // Aktuellen Wert prüfen und ggf. anpassen + float currentFreq = audioProcessor.apvts.getRawParameterValue("HighBandFreq")->load(); + if (currentFreq < 8000.0f) + { + highBandFreqSlider.setValue(8000.0, juce::sendNotificationSync); + } + } + else if (highMode >= 1) // Cut oder Shelf Mode + { + // Volle Bandbreite + highBandFreqSlider.setRange(20.0, 20000.0, 1.0); + } + highBandFreqSlider.repaint(); +} + //region animateCrystalizeButton void CrystalizerEQAudioProcessorEditor::animateCrystalizeButton() { if (isAnimatingCrystalize) { - const float step = 0.1f; - if (isFadingToActive) - { + if (isFadingToActive) { svgToggleButtonLookAndFeel->activeIconOpacity += step; svgToggleButtonLookAndFeel->passiveIconOpacity -= step; - if (svgToggleButtonLookAndFeel->activeIconOpacity >= 1.0f) - { + if (svgToggleButtonLookAndFeel->activeIconOpacity >= 1.0f) { svgToggleButtonLookAndFeel->activeIconOpacity = 1.0f; svgToggleButtonLookAndFeel->passiveIconOpacity = 0.0f; isAnimatingCrystalize = false; } - } - else - { + } else { svgToggleButtonLookAndFeel->activeIconOpacity -= step; svgToggleButtonLookAndFeel->passiveIconOpacity += step; - if (svgToggleButtonLookAndFeel->passiveIconOpacity >= 1.0f) - { + if (svgToggleButtonLookAndFeel->passiveIconOpacity >= 1.0f) { svgToggleButtonLookAndFeel->activeIconOpacity = 0.0f; svgToggleButtonLookAndFeel->passiveIconOpacity = 1.0f; isAnimatingCrystalize = false; @@ -1397,43 +1259,35 @@ void CrystalizerEQAudioProcessorEditor::animateCrystalizeButton() { crystalizeButton.repaint(); } } + //endregion animateCrystalizeButton //region timerCallback -void CrystalizerEQAudioProcessorEditor::timerCallback() -{ +void CrystalizerEQAudioProcessorEditor::timerCallback() { setKnobVisibility(); spectrumAnalyzer.processSamples(); repaint(analyzerRect); resized(); animateCrystalizeButton(); + updateFrequencyRanges(); - if (presetMenuSafePtr == nullptr) - { + if (presetMenuSafePtr == nullptr) { presetMenuButton.setToggleState(false, juce::dontSendNotification); + inputFocused = false; + } else if (!inputFocused) { + presetNameInput.giveAwayKeyboardFocus(); } } + //endregion timerCallback -void CrystalizerEQAudioProcessorEditor::resized() -{ - - +void CrystalizerEQAudioProcessorEditor::resized() { auto pluginArea = getLocalBounds(); scalePluginWindow(pluginArea); setupMainGrid(pluginArea); setupHeader(); setupBody(); setupFooter(); - //setSliderSizes(); - - - - - const auto testBounds = mainPanel.getLocalBounds(); - const auto testWidth = testBounds.getWidth(); - const auto testHeight = testBounds.getHeight(); - testNoiseButton.setBounds(50, testHeight / 2, testWidth / 8, testHeight / 8); } @@ -1456,17 +1310,18 @@ void CrystalizerEQAudioProcessorEditor::resetAllCheckboxes() { highBell.setToggleState(false, notify); highShelf.setToggleState(true, notify); } + //endregion resetAllCheckboxes //region scalePluginWindow void CrystalizerEQAudioProcessorEditor::scalePluginWindow(juce::Rectangle area) { - - if (area.getWidth() < 520) Spacing::setUiScale(Spacing::uiScaleMode::XS); - else if (area.getWidth() < 720) Spacing::setUiScale(Spacing::uiScaleMode::S); + if (area.getWidth() < 520) Spacing::setUiScale(Spacing::uiScaleMode::XS); + else if (area.getWidth() < 720) Spacing::setUiScale(Spacing::uiScaleMode::S); else if (area.getWidth() < 1024) Spacing::setUiScale(Spacing::uiScaleMode::M); else if (area.getWidth() < 1366) Spacing::setUiScale(Spacing::uiScaleMode::L); - else Spacing::setUiScale(Spacing::uiScaleMode::XL); + else Spacing::setUiScale(Spacing::uiScaleMode::XL); } + //endregion scalePluginWindow //region setupMainGrid @@ -1474,21 +1329,21 @@ void CrystalizerEQAudioProcessorEditor::setupMainGrid(juce::Rectangle area) const float headerHeight = static_cast(getHeight()) * 0.1f; const float footerHeight = static_cast(getHeight()) * 0.1f; - Layout::GridSpec spec { - /* cols */ { Layout::fr(1) }, // eine Spalte, füllt Breite - /* rows */ { Layout::pxTrack(headerHeight), Layout::fr(1), Layout::pxTrack(footerHeight) }, // Header / Body / Footer + Layout::GridSpec spec{ + /* cols */ {Layout::fr(1)}, // eine Spalte, füllt Breite + /* rows */ {Layout::pxTrack(headerHeight), Layout::fr(1), Layout::pxTrack(footerHeight)}, + // Header / Body / Footer /* colGap */ Spacing::SizeMode::S, /* rowGap */ Spacing::SizeMode::S, /* pad */ Layout::padding(Spacing::SizeMode::XS) }; - Layout::grid(area, spec, { &headerBar, &mainPanel, &footerBar }); - + Layout::grid(area, spec, {&headerBar, &mainPanel, &footerBar}); } + //endregion setupMainGrid //region setupHeader void CrystalizerEQAudioProcessorEditor::setupHeader() { - const auto bounds = headerBar.getLocalBounds(); const float presetAreaWidth = static_cast(bounds.getWidth()) * 0.5f; @@ -1496,62 +1351,61 @@ void CrystalizerEQAudioProcessorEditor::setupHeader() { const auto titleWidthCentre = titleLabel.getFont().getStringWidth("Crystalizer") / 4; Layout::GridSpec headerSpec{ - /* cols */ { Layout::fr(1), Layout::pxTrack(presetAreaWidth), Layout::fr(1) }, - /* rows */ { Layout::fr(1) }, + /* cols */ {Layout::fr(1), Layout::pxTrack(presetAreaWidth), Layout::fr(1)}, + /* rows */ {Layout::fr(1)}, /* colGap */ Spacing::SizeMode::XS, /* rowGap */ Spacing::SizeMode::XS, /* pad */ Layout::padding(Spacing::SizeMode::XS) }; Layout::grid(bounds, headerSpec, { - Layout::area(presetArea, 1, 2, 2, 3), - Layout::area(titleLabel, 1, 1, 2, 2) - .withMargin(juce::GridItem::Margin(0, 0, 0, titleWidthCentre)), - Layout::area(presetMenu, 1, 3, 2, 4), - }); + Layout::area(presetArea, 1, 2, 2, 3), + Layout::area(titleLabel, 1, 1, 2, 2) + .withMargin(juce::GridItem::Margin(0, 0, 0, titleWidthCentre)), + Layout::area(presetMenu, 1, 3, 2, 4), + }); const auto presetMenuBounds = presetMenu.getLocalBounds(); Layout::GridSpec presetMenuSpec{ - /* cols */ { Layout::fr(1), Layout::fr(1) }, - /* rows */ { Layout::fr(1), Layout::fr(1) }, + /* cols */ {Layout::fr(1), Layout::fr(1)}, + /* rows */ {Layout::fr(1), Layout::fr(1)}, /* colGap */ Spacing::SizeMode::XS, /* rowGap */ Spacing::SizeMode::XS, /* pad */ Layout::padding(Spacing::SizeMode::XS) }; Layout::grid(presetMenuBounds, presetMenuSpec, { - Layout::area(presetNameInput, 1, 1, 2, 3), - Layout::area(savePresetButton, 2, 1, 3, 2), - Layout::area(deletePresetButton, 2, 2, 3, 3), - }); + Layout::area(presetNameInput, 1, 1, 2, 3), + Layout::area(savePresetButton, 2, 1, 3, 2), + Layout::area(deletePresetButton, 2, 2, 3, 3), + }); const auto presetAreaBounds = presetArea.getLocalBounds(); const auto presetBoxWidth = static_cast(presetArea.getWidth()); const auto presetBoxHeight = static_cast(presetArea.getHeight()); const float rowHeight = presetBoxHeight * 0.25f; - const float iconSize = rowHeight; + const float iconSize = rowHeight; Layout::GridSpec presetSpec{ - /* cols */ { Layout::fr(1), Layout::pxTrack(presetBoxWidth * 0.5f), Layout::fr(1)}, - /* rows */ { Layout::pxTrack(rowHeight), Layout::pxTrack(rowHeight)}, + /* cols */ {Layout::fr(1), Layout::pxTrack(presetBoxWidth * 0.5f), Layout::fr(1)}, + /* rows */ {Layout::pxTrack(rowHeight), Layout::pxTrack(rowHeight)}, /* colGap */ Spacing::SizeMode::XS, /* rowGap */ Spacing::SizeMode::XS, /* pad */ Layout::padding(Spacing::SizeMode::S) }; Layout::grid(presetAreaBounds, presetSpec, { - // Label über beide Spalten (row1, col1..2) - Layout::area(presetBoxLabel, 1, 2, 2, 3), - // Box unten links (row2, col1) - Layout::area(presetBox, 2, 2, 3, 3), - Layout::area(resetButton, 2, 1, 2, 2), - // Menütaste unten rechts (row2, col2) - Layout::area(presetMenuButton, 2, 3, 3, 4) - .withWidth(iconSize) - .withHeight(iconSize) - - }); - + // Label über beide Spalten (row1, col1..2) + Layout::area(presetBoxLabel, 1, 2, 2, 3), + // Box unten links (row2, col1) + Layout::area(presetBox, 2, 2, 3, 3), + Layout::area(resetButton, 2, 1, 2, 2), + // Menütaste unten rechts (row2, col2) + Layout::area(presetMenuButton, 2, 3, 3, 4) + .withWidth(iconSize) + .withHeight(iconSize) + }); } + //endregion setupHeader //region setupBody @@ -1561,22 +1415,31 @@ void CrystalizerEQAudioProcessorEditor::setupBody() { const auto bodyHeight = static_cast(bounds.getHeight()); const auto bodyWidth = static_cast(bounds.getWidth()); const auto bodyColWidth = bodyWidth / 5.0f; + const auto crystalizeIconSize = 140.0f; Layout::GridSpec bodySpec{ - /* cols */ { Layout::fr(1), Layout::pxTrack(bodyColWidth), Layout::pxTrack(bodyColWidth), Layout::pxTrack(bodyColWidth), Layout::fr(1) }, - /* rows */ { Layout::fr(1), Layout::fr(1) }, + /* cols */ + { + Layout::fr(1), Layout::pxTrack(bodyColWidth), Layout::pxTrack(bodyColWidth), Layout::pxTrack(bodyColWidth), + Layout::fr(1) + }, + /* rows */ {Layout::fr(1), Layout::fr(1)}, /* colGap */ Spacing::SizeMode::XS, /* rowGap */ Spacing::SizeMode::XS, /* pad */ Layout::padding(Spacing::SizeMode::XS) }; Layout::grid(bounds, bodySpec, { - Layout::area(analyzerArea, 1, 2, 2, 5) - .withMargin(juce::GridItem::Margin(filterAreaMargin, 0, filterAreaMargin, 0)), - Layout::area(crystalizeButton, 1, 5, 2, 6), - Layout::area(filterArea, 2, 1, 3, 6) - .withMargin(juce::GridItem::Margin(0, filterAreaMargin, 0, filterAreaMargin)) + Layout::area(analyzerArea, 1, 2, 2, 5) + .withMargin(juce::GridItem::Margin(filterAreaMargin, 0, filterAreaMargin, 0)), + Layout::area(crystalizeButton, 1, 5, 2, 6) + .withWidth(crystalizeIconSize) + .withHeight(crystalizeIconSize * 0.5f) + .withAlignSelf(juce::GridItem::AlignSelf::center) +.withJustifySelf(juce::GridItem::JustifySelf::center), + Layout::area(filterArea, 2, 1, 3, 6) + .withMargin(juce::GridItem::Margin(0, filterAreaMargin, 0, filterAreaMargin)) - }); + }); const auto analyzerAreaBounds = analyzerArea.getLocalBounds(); const auto analyzerAreaWidth = static_cast(analyzerArea.getWidth()); @@ -1588,30 +1451,33 @@ void CrystalizerEQAudioProcessorEditor::setupBody() { const auto filterColWidth = filterAreaWidth * 0.2f; - Layout::GridSpec filterSpec{ - /* cols */ { Layout::fr(1), Layout::pxTrack(filterColWidth), Layout::pxTrack(filterColWidth), Layout::pxTrack(filterColWidth), Layout::fr(1) }, - /* rows */ { Layout::fr(1)}, + /* cols */ + { + Layout::fr(1), Layout::pxTrack(filterColWidth), Layout::pxTrack(filterColWidth), + Layout::pxTrack(filterColWidth), Layout::fr(1) + }, + /* rows */ {Layout::fr(1)}, /* colGap */ Spacing::SizeMode::XS, /* rowGap */ Spacing::SizeMode::XS, /* pad */ Layout::padding(Spacing::SizeMode::S) }; Layout::grid(filterAreaBounds, filterSpec, { - Layout::area(lowFilterArea, 1, 1, 2, 2), - Layout::area(lowMidFilterArea, 1, 2, 2, 3), - Layout::area(midFilterArea, 1, 3, 2, 4), - Layout::area(highMidFilterArea, 1, 4, 2, 5), - Layout::area(highFilterArea, 1, 5, 2, 6), + Layout::area(lowFilterArea, 1, 1, 2, 2), + Layout::area(lowMidFilterArea, 1, 2, 2, 3), + Layout::area(midFilterArea, 1, 3, 2, 4), + Layout::area(highMidFilterArea, 1, 4, 2, 5), + Layout::area(highFilterArea, 1, 5, 2, 6), - }); + }); setupLowBandLayout(); setupLowMidBandLayout(); setupMidBandLayout(); setupHighMidBandLayout(); setupHighBandLayout(); - } + //endregion setupBody //region setupLowBandLayout @@ -1629,55 +1495,55 @@ void CrystalizerEQAudioProcessorEditor::setupLowBandLayout() { const float labelPadding = Components::SlopeSliderLookAndFeel::labelPadding * 2; Layout::GridSpec lowBandSpec{ - /* cols */ { Layout::fr(1), Layout::pxTrack(knobColWidth), Layout::fr(1) }, - /* rows */ { Layout::fr(1), Layout::pxTrack(knobRowHeight * 1.25f), Layout::fr(1)}, + /* cols */ {Layout::fr(1), Layout::pxTrack(knobColWidth), Layout::fr(1)}, + /* rows */ {Layout::fr(1), Layout::pxTrack(knobRowHeight * 1.25f), Layout::fr(1)}, /* colGap */ Spacing::SizeMode::XS, /* rowGap */ Spacing::SizeMode::XS, /* pad */ Layout::padding(Spacing::SizeMode::XS) }; Layout::grid(bounds, lowBandSpec, { - Layout::area(lowBandFreqSlider, 2, 1, 3, 2) - .withWidth(refW * freqMod * 0.8f) - .withHeight(refH * freqMod * 0.8f) - .withAlignSelf(juce::GridItem::AlignSelf::center) - .withJustifySelf(juce::GridItem::JustifySelf::center), + Layout::area(lowBandFreqSlider, 2, 1, 3, 2) + .withWidth(refW * freqMod * 0.8f) + .withHeight(refH * freqMod * 0.8f) + .withAlignSelf(juce::GridItem::AlignSelf::center) + .withJustifySelf(juce::GridItem::JustifySelf::center), - Layout::area(lowBandGainSlider, 2, 2, 3, 3) - .withWidth(refW * gainMod * 0.8f) - .withHeight(refH * gainMod * 0.8f) - .withAlignSelf(juce::GridItem::AlignSelf::center) - .withJustifySelf(juce::GridItem::JustifySelf::center), + Layout::area(lowBandGainSlider, 2, 2, 3, 3) + .withWidth(refW * gainMod * 0.8f) + .withHeight(refH * gainMod * 0.8f) + .withAlignSelf(juce::GridItem::AlignSelf::center) + .withJustifySelf(juce::GridItem::JustifySelf::center), - Layout::area(lowBandQSlider, 2, 3, 3, 4) - .withWidth(refW * qMod * 0.8f) - .withHeight(refH * qMod * 0.8f) - .withAlignSelf(juce::GridItem::AlignSelf::center) - .withJustifySelf(juce::GridItem::JustifySelf::center), + Layout::area(lowBandQSlider, 2, 3, 3, 4) + .withWidth(refW * qMod * 0.8f) + .withHeight(refH * qMod * 0.8f) + .withAlignSelf(juce::GridItem::AlignSelf::center) + .withJustifySelf(juce::GridItem::JustifySelf::center), - Layout::area(lowBandSlopeSlider, 3, 1, 4, 2) - .withWidth(refW * slopeMod + labelPadding) - .withHeight(refH * slopeMod + labelPadding) - .withAlignSelf(juce::GridItem::AlignSelf::center) - .withJustifySelf(juce::GridItem::JustifySelf::center), + Layout::area(lowBandSlopeSlider, 3, 1, 4, 2) + .withWidth(refW * slopeMod + labelPadding) + .withHeight(refH * slopeMod + labelPadding) + .withAlignSelf(juce::GridItem::AlignSelf::center) + .withJustifySelf(juce::GridItem::JustifySelf::center), - Layout::area(lowBandModeBox, 3, 2, 4, 4), + Layout::area(lowBandModeBox, 3, 2, 4, 4), - Layout::area(lowBandFreqLabel, 2, 1, 3, 2) - .withMargin(juce::GridItem::Margin(-offSetToGainTop, 0, 0, 0)), - Layout::area(lowBandGainLabel, 1, 2, 2, 3), - Layout::area(lowBandQLabel, 2, 3, 3, 4) - .withMargin(juce::GridItem::Margin(-offSetToGainTop, 0, 0, 0)), - Layout::area(lowBandSlopeLabel, 3, 1, 4, 2) - .withMargin(juce::GridItem::Margin(-offSetToGainTop / 1.5f, 0, 0, 0)), + Layout::area(lowBandFreqLabel, 2, 1, 3, 2) + .withMargin(juce::GridItem::Margin(-offSetToGainTop, 0, 0, 0)), + Layout::area(lowBandGainLabel, 1, 2, 2, 3), + Layout::area(lowBandQLabel, 2, 3, 3, 4) + .withMargin(juce::GridItem::Margin(-offSetToGainTop, 0, 0, 0)), + Layout::area(lowBandSlopeLabel, 3, 1, 4, 2) + .withMargin(juce::GridItem::Margin(-offSetToGainTop / 1.5f, 0, 0, 0)), - Layout::area(lowdBOctLabel, 3, 1, 4, 2) - .withAlignSelf(juce::GridItem::AlignSelf::center) - .withJustifySelf(juce::GridItem::JustifySelf::center), + Layout::area(lowdBOctLabel, 3, 1, 4, 2) + .withAlignSelf(juce::GridItem::AlignSelf::center) + .withJustifySelf(juce::GridItem::JustifySelf::center), - }); + }); const auto modeBoxBounds = lowBandModeBox.getLocalBounds(); const auto modeBoxAreaWidth = static_cast(modeBoxBounds.getWidth()); @@ -1686,22 +1552,23 @@ void CrystalizerEQAudioProcessorEditor::setupLowBandLayout() { const auto slopeH = lowBandSlopeSlider.getY() - lowBandModeBox.getY() + lowBandModeLabel.getFont().getHeight() / 2; Layout::GridSpec lowBandModeBoxSpec{ - /* cols */ { Layout::fr(1), Layout::fr(1), Layout::fr(1), Layout::fr(1) }, - /* rows */ { Layout::fr(1), Layout::fr(1)}, + /* cols */ {Layout::fr(1), Layout::fr(1), Layout::fr(1), Layout::fr(1)}, + /* rows */ {Layout::fr(1), Layout::fr(1)}, /* colGap */ Spacing::SizeMode::XS, /* rowGap */ Spacing::SizeMode::XS, /* pad */ Layout::padding(Spacing::SizeMode::XS) }; Layout::grid(modeBoxBounds, lowBandModeBoxSpec, { - Layout::area(lowBandModeLabel, 1, 2, 2, 4) - .withMargin(juce::GridItem::Margin(slopeH , 0, 0, 0)), - Layout::area(lowBypass, 1, 1, 3, 2), - Layout::area(lowCut, 1, 2, 3, 3), - Layout::area(lowBell, 1, 3, 3, 4), - Layout::area(lowShelf, 1, 4, 3, 5) - }); + Layout::area(lowBandModeLabel, 1, 2, 2, 4) + .withMargin(juce::GridItem::Margin(slopeH, 0, 0, 0)), + Layout::area(lowBypass, 1, 1, 3, 2), + Layout::area(lowCut, 1, 2, 3, 3), + Layout::area(lowBell, 1, 3, 3, 4), + Layout::area(lowShelf, 1, 4, 3, 5) + }); } + //endregion setupLowBandLayout //region setupLowMidBandLayout @@ -1718,39 +1585,40 @@ void CrystalizerEQAudioProcessorEditor::setupLowMidBandLayout() { const auto offSetToGainTop = gainSize; Layout::GridSpec lowMidBandSpec{ - /* cols */ { Layout::fr(1), Layout::pxTrack(knobColWidth), Layout::fr(1) }, - /* rows */ { Layout::fr(1), Layout::pxTrack(knobRowHeight * 1.25f), Layout::fr(1)}, + /* cols */ {Layout::fr(1), Layout::pxTrack(knobColWidth), Layout::fr(1)}, + /* rows */ {Layout::fr(1), Layout::pxTrack(knobRowHeight * 1.25f), Layout::fr(1)}, /* colGap */ Spacing::SizeMode::XS, /* rowGap */ Spacing::SizeMode::XS, /* pad */ Layout::padding(Spacing::SizeMode::XS) }; Layout::grid(bounds, lowMidBandSpec, { - Layout::area(peak1FreqSlider, 2, 1, 3, 2) - .withWidth(refW * freqMod) - .withHeight(refH * freqMod) - .withAlignSelf(juce::GridItem::AlignSelf::center) - .withJustifySelf(juce::GridItem::JustifySelf::center), - Layout::area(peak1GainSlider, 2, 2, 3, 3) - .withWidth(refW * gainMod) - .withHeight(refH * gainMod) - .withAlignSelf(juce::GridItem::AlignSelf::center) - .withJustifySelf(juce::GridItem::JustifySelf::center), - Layout::area(peak1QSlider, 2, 3, 3, 4) - .withWidth(refW * qMod) - .withHeight(refH * qMod) - .withAlignSelf(juce::GridItem::AlignSelf::center) - .withJustifySelf(juce::GridItem::JustifySelf::center), + Layout::area(peak1FreqSlider, 2, 1, 3, 2) + .withWidth(refW * freqMod) + .withHeight(refH * freqMod) + .withAlignSelf(juce::GridItem::AlignSelf::center) + .withJustifySelf(juce::GridItem::JustifySelf::center), + Layout::area(peak1GainSlider, 2, 2, 3, 3) + .withWidth(refW * gainMod) + .withHeight(refH * gainMod) + .withAlignSelf(juce::GridItem::AlignSelf::center) + .withJustifySelf(juce::GridItem::JustifySelf::center), + Layout::area(peak1QSlider, 2, 3, 3, 4) + .withWidth(refW * qMod) + .withHeight(refH * qMod) + .withAlignSelf(juce::GridItem::AlignSelf::center) + .withJustifySelf(juce::GridItem::JustifySelf::center), - Layout::area(peak1FreqLabel, 2, 1, 3, 2) - .withMargin(juce::GridItem::Margin(-offSetToGainTop, 0, 0, 0)), - Layout::area(peak1GainLabel, 1, 2, 2, 3), - Layout::area(peak1QLabel, 2, 3, 3, 4) - .withMargin(juce::GridItem::Margin(-offSetToGainTop, 0, 0, 0)), + Layout::area(peak1FreqLabel, 2, 1, 3, 2) + .withMargin(juce::GridItem::Margin(-offSetToGainTop, 0, 0, 0)), + Layout::area(peak1GainLabel, 1, 2, 2, 3), + Layout::area(peak1QLabel, 2, 3, 3, 4) + .withMargin(juce::GridItem::Margin(-offSetToGainTop, 0, 0, 0)), - Layout::area(peak1BypassButton, 3, 2, 4, 3) - }); + Layout::area(peak1BypassButton, 3, 2, 4, 3) + }); } + //endregion setupLowMidBandLayout //region setupMidBandLayout @@ -1767,8 +1635,8 @@ void CrystalizerEQAudioProcessorEditor::setupMidBandLayout() { const auto offSetToGainTop = gainSize; Layout::GridSpec midBandSpec{ - /* cols */ { Layout::fr(1), Layout::pxTrack(knobColWidth), Layout::fr(1) }, - /* rows */ { Layout::fr(1), Layout::pxTrack(knobRowHeight * 1.25f), Layout::fr(1)}, + /* cols */ {Layout::fr(1), Layout::pxTrack(knobColWidth), Layout::fr(1)}, + /* rows */ {Layout::fr(1), Layout::pxTrack(knobRowHeight * 1.25f), Layout::fr(1)}, /* colGap */ Spacing::SizeMode::XS, /* rowGap */ Spacing::SizeMode::XS, /* pad */ Layout::padding(Spacing::SizeMode::XS) @@ -1776,32 +1644,33 @@ void CrystalizerEQAudioProcessorEditor::setupMidBandLayout() { Layout::grid(bounds, midBandSpec, { - Layout::area(peak2FreqSlider, 2, 1, 3, 2) - .withWidth(refW * freqMod) - .withHeight(refH * freqMod) - .withAlignSelf(juce::GridItem::AlignSelf::center) - .withJustifySelf(juce::GridItem::JustifySelf::center), - Layout::area(peak2GainSlider, 2, 2, 3, 3) - .withWidth(refW * gainMod) - .withHeight(refH * gainMod) - .withAlignSelf(juce::GridItem::AlignSelf::center) - .withJustifySelf(juce::GridItem::JustifySelf::center), - Layout::area(peak2QSlider, 2, 3, 3, 4) - .withWidth(refW * qMod) - .withHeight(refH * qMod) - .withAlignSelf(juce::GridItem::AlignSelf::center) - .withJustifySelf(juce::GridItem::JustifySelf::center), + Layout::area(peak2FreqSlider, 2, 1, 3, 2) + .withWidth(refW * freqMod) + .withHeight(refH * freqMod) + .withAlignSelf(juce::GridItem::AlignSelf::center) + .withJustifySelf(juce::GridItem::JustifySelf::center), + Layout::area(peak2GainSlider, 2, 2, 3, 3) + .withWidth(refW * gainMod) + .withHeight(refH * gainMod) + .withAlignSelf(juce::GridItem::AlignSelf::center) + .withJustifySelf(juce::GridItem::JustifySelf::center), + Layout::area(peak2QSlider, 2, 3, 3, 4) + .withWidth(refW * qMod) + .withHeight(refH * qMod) + .withAlignSelf(juce::GridItem::AlignSelf::center) + .withJustifySelf(juce::GridItem::JustifySelf::center), - Layout::area(peak2FreqLabel, 2, 1, 3, 2) - .withMargin(juce::GridItem::Margin(-offSetToGainTop, 0, 0, 0)), - Layout::area(peak2GainLabel, 1, 2, 2, 3), + Layout::area(peak2FreqLabel, 2, 1, 3, 2) + .withMargin(juce::GridItem::Margin(-offSetToGainTop, 0, 0, 0)), + Layout::area(peak2GainLabel, 1, 2, 2, 3), - Layout::area(peak2QLabel, 2, 3, 3, 4) - .withMargin(juce::GridItem::Margin(-offSetToGainTop, 0, 0, 0)), + Layout::area(peak2QLabel, 2, 3, 3, 4) + .withMargin(juce::GridItem::Margin(-offSetToGainTop, 0, 0, 0)), - Layout::area(peak2BypassButton, 3, 2, 4, 3) - }); + Layout::area(peak2BypassButton, 3, 2, 4, 3) + }); } + //endregion setupMidBandLayout //region setupHighMidBandLayout @@ -1818,39 +1687,40 @@ void CrystalizerEQAudioProcessorEditor::setupHighMidBandLayout() { const auto offSetToGainTop = gainSize; Layout::GridSpec highMidBandSpec{ - /* cols */ { Layout::fr(1), Layout::pxTrack(knobColWidth), Layout::fr(1) }, - /* rows */ { Layout::fr(1), Layout::pxTrack(knobRowHeight * 1.25f), Layout::fr(1)}, + /* cols */ {Layout::fr(1), Layout::pxTrack(knobColWidth), Layout::fr(1)}, + /* rows */ {Layout::fr(1), Layout::pxTrack(knobRowHeight * 1.25f), Layout::fr(1)}, /* colGap */ Spacing::SizeMode::XS, /* rowGap */ Spacing::SizeMode::XS, /* pad */ Layout::padding(Spacing::SizeMode::XS) }; Layout::grid(bounds, highMidBandSpec, { - Layout::area(peak3FreqSlider, 2, 1, 3, 2) - .withWidth(refW * freqMod) - .withHeight(refH * freqMod) - .withAlignSelf(juce::GridItem::AlignSelf::center) - .withJustifySelf(juce::GridItem::JustifySelf::center), - Layout::area(peak3GainSlider, 2, 2, 3, 3) - .withWidth(refW * gainMod) - .withHeight(refH * gainMod) - .withAlignSelf(juce::GridItem::AlignSelf::center) - .withJustifySelf(juce::GridItem::JustifySelf::center), - Layout::area(peak3QSlider, 2, 3, 3, 4) - .withWidth(refW * qMod) - .withHeight(refH * qMod) - .withAlignSelf(juce::GridItem::AlignSelf::center) - .withJustifySelf(juce::GridItem::JustifySelf::center), + Layout::area(peak3FreqSlider, 2, 1, 3, 2) + .withWidth(refW * freqMod) + .withHeight(refH * freqMod) + .withAlignSelf(juce::GridItem::AlignSelf::center) + .withJustifySelf(juce::GridItem::JustifySelf::center), + Layout::area(peak3GainSlider, 2, 2, 3, 3) + .withWidth(refW * gainMod) + .withHeight(refH * gainMod) + .withAlignSelf(juce::GridItem::AlignSelf::center) + .withJustifySelf(juce::GridItem::JustifySelf::center), + Layout::area(peak3QSlider, 2, 3, 3, 4) + .withWidth(refW * qMod) + .withHeight(refH * qMod) + .withAlignSelf(juce::GridItem::AlignSelf::center) + .withJustifySelf(juce::GridItem::JustifySelf::center), - Layout::area(peak3FreqLabel, 2, 1, 3, 2) - .withMargin(juce::GridItem::Margin(-offSetToGainTop, 0, 0, 0)), - Layout::area(peak3GainLabel, 1, 2, 2, 3), - Layout::area(peak3QLabel, 2, 3, 3, 4) - .withMargin(juce::GridItem::Margin(-offSetToGainTop, 0, 0, 0)), + Layout::area(peak3FreqLabel, 2, 1, 3, 2) + .withMargin(juce::GridItem::Margin(-offSetToGainTop, 0, 0, 0)), + Layout::area(peak3GainLabel, 1, 2, 2, 3), + Layout::area(peak3QLabel, 2, 3, 3, 4) + .withMargin(juce::GridItem::Margin(-offSetToGainTop, 0, 0, 0)), - Layout::area(peak3BypassButton, 3, 2, 4, 3) - }); + Layout::area(peak3BypassButton, 3, 2, 4, 3) + }); } + //endregion setupHighMidBandLayout //region setupHighBandLayout @@ -1869,8 +1739,8 @@ void CrystalizerEQAudioProcessorEditor::setupHighBandLayout() { Layout::GridSpec highBandSpec{ - /* cols */ { Layout::fr(1), Layout::pxTrack(knobColWidth), Layout::fr(1) }, - /* rows */ { Layout::fr(1), Layout::pxTrack(knobRowHeight * 1.25f), Layout::fr(1)}, + /* cols */ {Layout::fr(1), Layout::pxTrack(knobColWidth), Layout::fr(1)}, + /* rows */ {Layout::fr(1), Layout::pxTrack(knobRowHeight * 1.25f), Layout::fr(1)}, /* colGap */ Spacing::SizeMode::XS, /* rowGap */ Spacing::SizeMode::XS, /* pad */ Layout::padding(Spacing::SizeMode::XS) @@ -1878,69 +1748,70 @@ void CrystalizerEQAudioProcessorEditor::setupHighBandLayout() { Layout::grid(bounds, highBandSpec, { + Layout::area(highBandFreqSlider, 2, 1, 3, 2) + .withWidth(refW * freqMod * 0.8f) + .withHeight(refH * freqMod * 0.8f) + .withAlignSelf(juce::GridItem::AlignSelf::center) + .withJustifySelf(juce::GridItem::JustifySelf::center), + Layout::area(highBandGainSlider, 2, 2, 3, 3) + .withWidth(refW * gainMod * 0.8f) + .withHeight(refH * gainMod * 0.8f) + .withAlignSelf(juce::GridItem::AlignSelf::center) + .withJustifySelf(juce::GridItem::JustifySelf::center), + Layout::area(highBandQSlider, 2, 3, 3, 4) + .withWidth(refW * qMod * 0.8f) + .withHeight(refH * qMod * 0.8f) + .withAlignSelf(juce::GridItem::AlignSelf::center) + .withJustifySelf(juce::GridItem::JustifySelf::center), - Layout::area(highBandFreqSlider, 2, 1, 3, 2) - .withWidth(refW * freqMod * 0.8f) - .withHeight(refH * freqMod * 0.8f) - .withAlignSelf(juce::GridItem::AlignSelf::center) - .withJustifySelf(juce::GridItem::JustifySelf::center), - Layout::area(highBandGainSlider, 2, 2, 3, 3) - .withWidth(refW * gainMod * 0.8f) - .withHeight(refH * gainMod * 0.8f) - .withAlignSelf(juce::GridItem::AlignSelf::center) - .withJustifySelf(juce::GridItem::JustifySelf::center), - Layout::area(highBandQSlider, 2, 3, 3, 4) - .withWidth(refW * qMod * 0.8f) - .withHeight(refH * qMod * 0.8f) - .withAlignSelf(juce::GridItem::AlignSelf::center) - .withJustifySelf(juce::GridItem::JustifySelf::center), - - Layout::area(highBandModeBox, 3, 1, 4, 3), + Layout::area(highBandModeBox, 3, 1, 4, 3), - Layout::area(highBandSlopeSlider, 3, 3, 4, 4) - .withWidth(refW * slopeMod + labelPadding) - .withHeight(refH * slopeMod + labelPadding) - .withAlignSelf(juce::GridItem::AlignSelf::center) - .withJustifySelf(juce::GridItem::JustifySelf::center), + Layout::area(highBandSlopeSlider, 3, 3, 4, 4) + .withWidth(refW * slopeMod + labelPadding) + .withHeight(refH * slopeMod + labelPadding) + .withAlignSelf(juce::GridItem::AlignSelf::center) + .withJustifySelf(juce::GridItem::JustifySelf::center), - Layout::area(highBandFreqLabel, 2, 1, 3, 2) - .withMargin(juce::GridItem::Margin(-offSetToGainTop, 0, 0, 0)), - Layout::area(highBandGainLabel, 1, 2, 2, 3), - Layout::area(highBandQLabel, 2, 3, 3, 4) - .withMargin(juce::GridItem::Margin(-offSetToGainTop, 0, 0, 0)), - Layout::area(highBandSlopeLabel, 3, 3, 4, 4) - .withMargin(juce::GridItem::Margin(-offSetToGainTop / 1.5f, 0, 0, 0)), + Layout::area(highBandFreqLabel, 2, 1, 3, 2) + .withMargin(juce::GridItem::Margin(-offSetToGainTop, 0, 0, 0)), + Layout::area(highBandGainLabel, 1, 2, 2, 3), + Layout::area(highBandQLabel, 2, 3, 3, 4) + .withMargin(juce::GridItem::Margin(-offSetToGainTop, 0, 0, 0)), + Layout::area(highBandSlopeLabel, 3, 3, 4, 4) + .withMargin(juce::GridItem::Margin(-offSetToGainTop / 1.5f, 0, 0, 0)), - Layout::area(highdBOctLabel, 3, 3, 4, 4) - .withAlignSelf(juce::GridItem::AlignSelf::center) - .withJustifySelf(juce::GridItem::JustifySelf::center), + Layout::area(highdBOctLabel, 3, 3, 4, 4) + .withAlignSelf(juce::GridItem::AlignSelf::center) + .withJustifySelf(juce::GridItem::JustifySelf::center), - }); + }); const auto modeBoxBounds = lowBandModeBox.getLocalBounds(); const auto modeBoxAreaWidth = static_cast(modeBoxBounds.getWidth()); const auto modeBoxAreaHeight = static_cast(modeBoxBounds.getHeight()); const auto modeBoxButtonColWidth = modeBoxAreaWidth / 4.0f; - const auto slopeH = highBandSlopeSlider.getY() - highBandModeBox.getY() + highBandModeLabel.getFont().getHeight() / 2; + const auto slopeH = highBandSlopeSlider.getY() - highBandModeBox.getY() + highBandModeLabel.getFont().getHeight() / + 2; Layout::GridSpec highBandModeBoxSpec{ - /* cols */ { Layout::fr(1), Layout::fr(1), Layout::fr(1), Layout::fr(1) }, - /* rows */ { Layout::fr(1), Layout::fr(1)}, + /* cols */ {Layout::fr(1), Layout::fr(1), Layout::fr(1), Layout::fr(1)}, + /* rows */ {Layout::fr(1), Layout::fr(1)}, /* colGap */ Spacing::SizeMode::XS, /* rowGap */ Spacing::SizeMode::XS, /* pad */ Layout::padding(Spacing::SizeMode::XS) }; Layout::grid(modeBoxBounds, highBandModeBoxSpec, { - Layout::area(highBandModeLabel, 1, 2, 2, 4) - .withMargin(juce::GridItem::Margin(slopeH , 0, 0, 0)), - Layout::area(highBypass, 1, 4, 3, 5), - Layout::area(highCut, 1, 3, 3, 4), - Layout::area(highBell, 1, 2, 3, 3), - Layout::area(highShelf, 1, 1, 3, 2) - }); + Layout::area(highBandModeLabel, 1, 2, 2, 4) + .withMargin(juce::GridItem::Margin(slopeH, 0, 0, 0)), + Layout::area(highBypass, 1, 4, 3, 5), + Layout::area(highCut, 1, 3, 3, 4), + Layout::area(highBell, 1, 2, 3, 3), + Layout::area(highShelf, 1, 1, 3, 2) + }); } + //endregion setupHighBandLayout //region setupFooter @@ -1954,15 +1825,15 @@ void CrystalizerEQAudioProcessorEditor::setupFooter() { const auto refH = getReferenceCell()[1]; Layout::GridSpec footerSpec{ - /* cols */ { Layout::fr(1), Layout::fr(1), Layout::fr(1) }, - /* rows */ { Layout::fr(1) }, + /* cols */ {Layout::fr(1), Layout::fr(1), Layout::fr(1)}, + /* rows */ {Layout::fr(1)}, /* colGap */ Spacing::SizeMode::XS, /* rowGap */ Spacing::SizeMode::XS, /* pad */ Layout::padding(Spacing::SizeMode::XS) }; Layout::grid(bounds, footerSpec, { - Layout::area(globalControlArea, 1, 3, 2, 4) - }); + Layout::area(globalControlArea, 1, 3, 2, 4) + }); const auto globalControlAreaBounds = globalControlArea.getLocalBounds(); const auto globalControlAreaWidth = static_cast(globalControlArea.getWidth()); @@ -1973,38 +1844,36 @@ void CrystalizerEQAudioProcessorEditor::setupFooter() { Layout::GridSpec globalControlAreaSpec{ - /* cols */ { Layout::fr(1), Layout::fr(1), Layout::fr(1) }, - /* rows */ { Layout::fr(1)}, + /* cols */ {Layout::fr(1), Layout::fr(1), Layout::fr(1)}, + /* rows */ {Layout::fr(1)}, /* colGap */ Spacing::SizeMode::XS, /* rowGap */ Spacing::SizeMode::XS, /* pad */ Layout::padding(Spacing::SizeMode::XS) }; Layout::grid(globalControlAreaBounds, globalControlAreaSpec, { - //TODO: Bring components closer together + Layout::area(outputSlider, 1, 2, 3, 3) + .withWidth(refW * globalMod) + .withHeight(refH * globalMod) + .withMargin(juce::GridItem::Margin(0, 0, 0, sliderRadius * 6)) + .withAlignSelf(juce::GridItem::AlignSelf::center) + .withJustifySelf(juce::GridItem::JustifySelf::center), - Layout::area(outputSlider, 1, 2, 3, 3) - .withWidth(refW * globalMod ) - .withHeight(refH * globalMod ) - .withMargin(juce::GridItem::Margin(0, 0, 0, sliderRadius * 6)) - .withAlignSelf(juce::GridItem::AlignSelf::center) - .withJustifySelf(juce::GridItem::JustifySelf::center), - - Layout::area(inputSlider, 1, 1, 3, 2) - .withWidth(refW * globalMod ) - .withHeight(refH * globalMod ) - .withMargin(juce::GridItem::Margin(0, 0, 0, sliderRadius * 10)) - .withAlignSelf(juce::GridItem::AlignSelf::center) - .withJustifySelf(juce::GridItem::JustifySelf::center), + Layout::area(inputSlider, 1, 1, 3, 2) + .withWidth(refW * globalMod) + .withHeight(refH * globalMod) + .withMargin(juce::GridItem::Margin(0, 0, 0, sliderRadius * 10)) + .withAlignSelf(juce::GridItem::AlignSelf::center) + .withJustifySelf(juce::GridItem::JustifySelf::center), - Layout::area(masterBypassButton, 1, 3, 3, 4) - .withWidth(sliderWidth) - - .withMargin(juce::GridItem::Margin(0, 0, 0, sliderRadius * 2)), - }); + Layout::area(masterBypassButton, 1, 3, 3, 4) + .withWidth(sliderWidth) + .withMargin(juce::GridItem::Margin(0, 0, 0, sliderRadius * 2)), + }); } + //endregion setupFooter //region getReferenceCell @@ -2020,6 +1889,7 @@ juce::Array CrystalizerEQAudioProcessorEditor::getReferenceCell() { const juce::Array refCell = {gainCellW, gainCellH}; return refCell; } + //endregion getReferenceCell //region processSamples @@ -2028,93 +1898,99 @@ void SpectrumAnalyzer::processSamples() { getFftFrame(samples); } + //endregion processSamples //region getFftFrame -void SpectrumAnalyzer::getFftFrame(juce::Array& samples) { +void SpectrumAnalyzer::getFftFrame(juce::Array &samples) { + const int needed = FFTSIZE - fftFrame.size(); + if (needed <= 0) + return; - const int needed = FFTSIZE - fftFrame.size(); - if (needed <= 0) - return; + const int available = samples.size(); + if (available <= 0) + return; - const int available = samples.size(); - if (available <= 0) - return; + const int take = std::min(needed, available); - const int take = std::min(needed, available); + for (int i = 0; i < take; ++i) + fftFrame.add(samples.getUnchecked(i)); - for (int i = 0; i < take; ++i) - fftFrame.add(samples.getUnchecked(i)); + samples.removeRange(0, take); - samples.removeRange(0, take); - - if (fftFrame.size() == FFTSIZE) - { - std::vector fullFrame(fftFrame.begin(), fftFrame.end()); - fftFrame.removeRange(0, HOPSIZE); - applyWindowOnFftFrame(fullFrame); - } + if (fftFrame.size() == FFTSIZE) { + std::vector fullFrame(fftFrame.begin(), fftFrame.end()); + fftFrame.removeRange(0, HOPSIZE); + applyWindowOnFftFrame(fullFrame); } +} + //endregion getFftFrame //region applyWindowOnFftFrame void SpectrumAnalyzer::applyWindowOnFftFrame(std::vector &fullFrame) { - if (fullFrame.size()!= FFTSIZE) return; - window.multiplyWithWindowingTable(fullFrame.data(), FFTSIZE); - processWindowedFrame(fullFrame); + if (fullFrame.size() != FFTSIZE) return; + window.multiplyWithWindowingTable(fullFrame.data(), FFTSIZE); + processWindowedFrame(fullFrame); } + //endregion applyWindowOnFftFrame //region processWindowedFrame void SpectrumAnalyzer::processWindowedFrame(std::vector &windowedFrame) { if (windowedFrame.size() != FFTSIZE || fftData.size() != FFTSIZE * 2) return; fillFftDataFromFrame(windowedFrame); - // fft.performRealOnlyForwardTransform(fftData.data()); - fft.performFrequencyOnlyForwardTransform(fftData.data(), true); buildMagnitudeSpectrum(); convertToDb(); applySmoothing(); renderValuesDb = getRenderValues(); - } + //endregion processWindowedFrame + + //region fillFftDataFromFrame void SpectrumAnalyzer::fillFftDataFromFrame(std::vector &windowedFrame) { for (int n = 0; n < FFTSIZE; ++n) { - /*fftData[2*n] = windowedFrame[n]; - fftData[2*n + 1] = 0.0f;*/ fftData[n] = windowedFrame[n]; } + for (int n = FFTSIZE; n < fftData.size(); ++n) { + fftData[n] = 0.0f; + } } + //endregion fillFftDataFromFrame //region buildMagnitudeSpectrum void SpectrumAnalyzer::buildMagnitudeSpectrum() { for (int k = 0; k < BINS; ++k) { float mag = fftData[k]; - mag /= (FFTSIZE * 0.5f); + mag /= FFTSIZE; + mag = std::max(mag, 1e-24f); magnitudes[k] = mag; } } + //endregion buildMagnitudeSpectrum //region convertToDb void SpectrumAnalyzer::convertToDb() { - - for (int k = 0; k < magnitudes.size(); ++k) { - float mag = magnitudes[k]; - float dB = juce::Decibels::gainToDecibels(mag); + float mag = std::max(magnitudes[k], 1e-9f); + float dB = juce::Decibels::gainToDecibels(mag); + // SOFORT auf MINDB setzen wenn unter -60dB, nicht erst limitieren + if (dB < -60.0f) { + dB = MINDB; + } - - dB = juce::jlimit(MINDB, MAXDB, dB); magnitudesDb[k] = dB; } } + //endregion convertToDb //region applySmoothing @@ -2123,6 +1999,7 @@ void SpectrumAnalyzer::applySmoothing() { applyFreqSmoothing(); applyPeakHoldAndFalloff(); } + //endregion applySmoothing //region applyEMA @@ -2131,13 +2008,12 @@ void SpectrumAnalyzer::applyEMA() { float smoothedVal = smoothingFactor * magnitudesDb[k] + (1 - smoothingFactor) * emaSmoothedMagnitudesDb[k]; emaSmoothedMagnitudesDb[k] = smoothedVal; } - } + //endregion applyEMA //region applyFreqSmoothing void SpectrumAnalyzer::applyFreqSmoothing() { - for (int k = 0; k < BINS; ++k) { double freq = k * deltaF; @@ -2152,7 +2028,10 @@ void SpectrumAnalyzer::applyFreqSmoothing() { highestBin = k; }; - if (k == 0) {lowestBin = 0; highestBin = std::min(1, BINS - 1);} + if (k == 0) { + lowestBin = 0; + highestBin = std::min(1, BINS - 1); + } float sum = 0.f; @@ -2161,10 +2040,9 @@ void SpectrumAnalyzer::applyFreqSmoothing() { } float avg = sum / static_cast(highestBin - lowestBin + 1); freqSmoothedMagnitudesDb[k] = avg; - - } } + //endregion applyFreqSmoothing //region applyPeakHoldAndFalloff @@ -2178,19 +2056,14 @@ void SpectrumAnalyzer::applyPeakHoldAndFalloff() { } } + //endregion applyPeakHoldAndFalloff //region getRenderValues std::vector SpectrumAnalyzer::getRenderValues() { - std::vector renderValues = peakHoldMagnitudesDb; + std::vector renderValues = peakHoldMagnitudesDb; + return renderValues; } + //endregion getRenderValues - - - - - - - - diff --git a/CrystalizerEQ/PluginEditor.h b/CrystalizerEQ/PluginEditor.h index 19cbba6..413ffaf 100644 --- a/CrystalizerEQ/PluginEditor.h +++ b/CrystalizerEQ/PluginEditor.h @@ -19,9 +19,11 @@ using AXIOM::DesignSystem; using Components = DesignSystem::Components; using SliderStyles = Components::SliderStyles; + class SpectrumAnalyzer { - public: - SpectrumAnalyzer(AudioFIFO& fifoRef, CrystalizerEQAudioProcessor& processor) : audioFIFO(fifoRef), audioProcessor(processor) { +public: + SpectrumAnalyzer(AudioFIFO &fifoRef, CrystalizerEQAudioProcessor &processor) : audioFIFO(fifoRef), + audioProcessor(processor) { fftData.resize(2 * FFTSIZE); magnitudes.resize(BINS); magnitudesDb.resize(BINS); @@ -33,15 +35,14 @@ class SpectrumAnalyzer { peakHoldMagnitudesDb.resize(BINS); DELTAT = static_cast(HOPSIZE) / static_cast(sampleRate); renderValuesDb.resize(BINS); - - } + ~SpectrumAnalyzer() = default; - AudioFIFO& audioFIFO; + AudioFIFO &audioFIFO; - CrystalizerEQAudioProcessor& audioProcessor; + CrystalizerEQAudioProcessor &audioProcessor; static constexpr int FFTSIZE = 4096; @@ -52,7 +53,7 @@ class SpectrumAnalyzer { juce::Array fftFrame; //CHANGE FOR LOWER/HIGHER EMA-SMOOTHING //LOWER VALUE -> MORE SMOOTHING/SLOW RESPONSE -- HIGHER VALUE -> LESS SMOOTHING/FAST RESPONSE //MAX VALUE = 1.f - float smoothingFactor = 0.3f; + float smoothingFactor = 0.5f; void processSamples(); @@ -62,21 +63,20 @@ class SpectrumAnalyzer { void applyWindowOnFftFrame(std::vector &fullFrame); juce::dsp::WindowingFunction window -{ - FFTSIZE, - juce::dsp::WindowingFunction::hann -}; + { + FFTSIZE, + juce::dsp::WindowingFunction::hann + }; void processWindowedFrame(std::vector &windowedFrame); static constexpr int FFTORDER = 12; - juce::dsp::FFT fft { FFTORDER }; + juce::dsp::FFT fft{FFTORDER}; std::vector fftData; - const float MINDB = -90.f; const float MAXDB = 0.f; @@ -103,7 +103,7 @@ class SpectrumAnalyzer { std::vector freqPerBin; //CHANGE FOR FASTER FALLOFF -- VALUE IS IN DB/S - const float FALLOFFRATE = 120.f; + const float FALLOFFRATE = 240.f; float DELTAT = 0.f; @@ -114,37 +114,43 @@ class SpectrumAnalyzer { const float MAXFREQ = static_cast(sampleRate) / 2; void fillFftDataFromFrame(std::vector &windowedFrame); - void buildMagnitudeSpectrum(); - void convertToDb(); - void applySmoothing(); - void applyEMA(); - void applyFreqSmoothing(); - void applyPeakHoldAndFalloff(); - std::vector getRenderValues(); + void buildMagnitudeSpectrum(); + + void convertToDb(); + + void applySmoothing(); + + void applyEMA(); + + void applyFreqSmoothing(); + + void applyPeakHoldAndFalloff(); + + std::vector getRenderValues(); }; -class CrystalizerEQAudioProcessorEditor : public juce::AudioProcessorEditor, private juce::Timer - -{ +class CrystalizerEQAudioProcessorEditor : public juce::AudioProcessorEditor, private juce::Timer { public: + CrystalizerEQAudioProcessorEditor(CrystalizerEQAudioProcessor &); - CrystalizerEQAudioProcessorEditor (CrystalizerEQAudioProcessor&); ~CrystalizerEQAudioProcessorEditor() override; void paintAnalyzer(juce::Graphics &g); void paintModeBoxBorders(juce::Graphics &g); - void paintBorderLines(juce::Graphics& g); + void paintBorderLines(juce::Graphics &g); //=================================================================== void timerCallback(); - void paint (juce::Graphics&) override; + + void paint(juce::Graphics &) override; void resized() override; + void resetAllCheckboxes(); using SliderAttach = juce::AudioProcessorValueTreeState::SliderAttachment; @@ -153,15 +159,15 @@ public: using ComboBoxAttach = juce::AudioProcessorValueTreeState::ComboBoxAttachment; - juce::Slider testNoiseSlider, - lowBandFreqSlider, lowBandSlopeSlider, lowBandGainSlider, lowBandQSlider, - peak1FreqSlider, peak1GainSlider, peak1QSlider, - peak2FreqSlider, peak2GainSlider, peak2QSlider, - peak3FreqSlider, peak3GainSlider, peak3QSlider, - highBandFreqSlider, highBandSlopeSlider, highBandGainSlider, highBandQSlider, - inputSlider, outputSlider; + juce::Slider + lowBandFreqSlider, lowBandSlopeSlider, lowBandGainSlider, lowBandQSlider, + peak1FreqSlider, peak1GainSlider, peak1QSlider, + peak2FreqSlider, peak2GainSlider, peak2QSlider, + peak3FreqSlider, peak3GainSlider, peak3QSlider, + highBandFreqSlider, highBandSlopeSlider, highBandGainSlider, highBandQSlider, + inputSlider, outputSlider; - const juce::Array sliders = { + const juce::Array sliders = { &lowBandGainSlider, &lowBandFreqSlider, &lowBandQSlider, &lowBandSlopeSlider, &peak1GainSlider, &peak1FreqSlider, &peak1QSlider, &peak2GainSlider, &peak2FreqSlider, &peak2QSlider, @@ -170,68 +176,69 @@ public: &inputSlider, &outputSlider }; - std::unique_ptr testNoiseAttach, - lowBandFreqAttach, lowBandSlopeAttach, lowBandGainAttach, lowBandQAttach, - peak1FreqAttach, peak1GainAttach, peak1QAttach, - peak2FreqAttach, peak2GainAttach, peak2QAttach, - peak3FreqAttach, peak3GainAttach, peak3QAttach, - highBandFreqAttach, highBandSlopeAttach, highBandGainAttach, highBandQAttach, - inputAttach, outputAttach; + std::unique_ptr + lowBandFreqAttach, lowBandSlopeAttach, lowBandGainAttach, lowBandQAttach, + peak1FreqAttach, peak1GainAttach, peak1QAttach, + peak2FreqAttach, peak2GainAttach, peak2QAttach, + peak3FreqAttach, peak3GainAttach, peak3QAttach, + highBandFreqAttach, highBandSlopeAttach, highBandGainAttach, highBandQAttach, + inputAttach, outputAttach; - juce::Label titleLabel, testNoiseLabel, - lowBandFreqLabel, lowBandSlopeLabel, lowBandGainLabel, lowBandQLabel, lowBandModeLabel, - low12, low24, low36, low48, lowdBOctLabel, - peak1FreqLabel, peak1GainLabel, peak1QLabel, - peak2FreqLabel, peak2GainLabel, peak2QLabel, - peak3FreqLabel, peak3GainLabel, peak3QLabel, - highBandFreqLabel, highBandSlopeLabel, highBandGainLabel, highBandQLabel, highBandModeLabel, - high12, high24, high36, high48, highdBOctLabel, - inputLabel, outputLabel, - presetBoxLabel; + juce::Label titleLabel, + lowBandFreqLabel, lowBandSlopeLabel, lowBandGainLabel, lowBandQLabel, lowBandModeLabel, + low12, low24, low36, low48, lowdBOctLabel, + peak1FreqLabel, peak1GainLabel, peak1QLabel, + peak2FreqLabel, peak2GainLabel, peak2QLabel, + peak3FreqLabel, peak3GainLabel, peak3QLabel, + highBandFreqLabel, highBandSlopeLabel, highBandGainLabel, highBandQLabel, highBandModeLabel, + high12, high24, high36, high48, highdBOctLabel, + inputLabel, outputLabel, + presetBoxLabel; - const juce::Array sliderLabels = { + const juce::Array sliderLabels = { &lowBandFreqLabel, &lowBandSlopeLabel, &lowBandGainLabel, &lowBandQLabel, &lowBandModeLabel, &lowdBOctLabel, - &peak1FreqLabel, &peak1GainLabel, &peak1QLabel, - &peak2FreqLabel, &peak2GainLabel, &peak2QLabel, - &peak3FreqLabel, &peak3GainLabel, &peak3QLabel, - &highBandFreqLabel, &highBandSlopeLabel, &highBandGainLabel, &highBandQLabel, &highBandModeLabel, &highdBOctLabel, - &inputLabel, &outputLabel + &peak1FreqLabel, &peak1GainLabel, &peak1QLabel, + &peak2FreqLabel, &peak2GainLabel, &peak2QLabel, + &peak3FreqLabel, &peak3GainLabel, &peak3QLabel, + &highBandFreqLabel, &highBandSlopeLabel, &highBandGainLabel, &highBandQLabel, &highBandModeLabel, + &highdBOctLabel, + &inputLabel, &outputLabel }; - const juce::Array slopeLabels = { + const juce::Array slopeLabels = { &low12, &low24, &low36, &low48, &high12, &high24, &high36, &high48 }; + juce::TextButton resetButton, savePresetButton, deletePresetButton; - juce::TextButton testNoiseButton, resetButton, savePresetButton, deletePresetButton; + juce::ToggleButton masterBypassButton, crystalizeButton, peak1BypassButton, peak2BypassButton, peak3BypassButton, + presetMenuButton; - juce::ToggleButton masterBypassButton, crystalizeButton, peak1BypassButton, peak2BypassButton, peak3BypassButton, presetMenuButton; - - const juce::Array peakBypassButtons = {&peak1BypassButton, &peak2BypassButton, &peak3BypassButton}; + const juce::Array peakBypassButtons = { + &peak1BypassButton, &peak2BypassButton, &peak3BypassButton + }; juce::ComboBox presetBox; juce::Component lowBandModeBox, highBandModeBox; - juce::Array lowBandModeButtons, highBandModeButtons; + juce::Array lowBandModeButtons, highBandModeButtons; std::array lowBandBools, highBandBools; juce::ToggleButton lowBypass, lowCut, lowBell, lowShelf, - highBypass, highCut, highBell, highShelf; + highBypass, highCut, highBell, highShelf; + + DesignSystem::ClickableTextEditor presetNameInput; - juce::TextEditor presetNameInput; private: - // This reference is provided as a quick way for your editor to // access the processor object that created it. - CrystalizerEQAudioProcessor& audioProcessor; - - + CrystalizerEQAudioProcessor &audioProcessor; void setKnobVisibility(); @@ -253,9 +260,13 @@ private: void setupToggleButtons(); void disableLowBand(float target); + void disableLowMidBand(float target); + void disableMidBand(float target); + void disableHighMidBand(float target); + void disableHighBand(float target); void disableEverything(float target); @@ -270,6 +281,10 @@ private: void initPresetSystem(); + void updateFrequencyRanges(); + + void updateModeButtons(); + std::unique_ptr baseLookAndFeel; std::unique_ptr gainLookAndFeel; @@ -284,6 +299,7 @@ private: std::unique_ptr presetMenuLookAndFeel; std::unique_ptr presetButtonLookAndFeel; std::unique_ptr presetComboBoxLookAndFeel; + std::unique_ptr presetInputLookAndFeel; //SPECRTRUM ANALYZER @@ -308,25 +324,31 @@ private: Component highMidFilterArea; Component highFilterArea; - const juce::Array filterAreas { + const juce::Array filterAreas{ &lowFilterArea, &lowMidFilterArea, &midFilterArea, &highMidFilterArea, &highFilterArea }; Component globalControlArea; - void scalePluginWindow(juce::Rectangle area); + void setupMainGrid(juce::Rectangle area); void setupLowBandLayout(); + void setupLowMidBandLayout(); + void setupMidBandLayout(); + void setupHighMidBandLayout(); + void setupHighBandLayout(); void setupHeader(); + void setupBody(); + void setupFooter(); juce::Array getReferenceCell(); @@ -344,13 +366,17 @@ private: std::unique_ptr logoDrawable; - DesignSystem::PresetMenu* test; juce::Component::SafePointer presetMenuSafePtr; + bool inputFocused = false; + float mapFrequencyToX(float freq, float minFreq, float maxFreq, float width); + int getClosestBinForFrequency(float freq); - void drawFrequencyGrid(juce::Graphics& g, const float dbRange); + + void drawFrequencyGrid(juce::Graphics &g, const float dbRange); + float getInterpolatedDb(float exactBin); - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CrystalizerEQAudioProcessorEditor) + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CrystalizerEQAudioProcessorEditor) }; diff --git a/CrystalizerEQ/PluginProcessor.cpp b/CrystalizerEQ/PluginProcessor.cpp index 36befe4..29fa9b6 100644 --- a/CrystalizerEQ/PluginProcessor.cpp +++ b/CrystalizerEQ/PluginProcessor.cpp @@ -14,11 +14,6 @@ juce::AudioProcessorValueTreeState::ParameterLayout CrystalizerEQAudioProcessor::createParameterLayout() { std::vector> params; - params.push_back (std::make_unique( - "TestNoiseEnabled", "Test Noise Enabled", false)); - - params.push_back (std::make_unique("TestNoiseLevel", "Test Noise Level", juce::NormalisableRange(-60.f, 0.f, 0.1f), 0.f)); - //LOW-BAND params.push_back (std::make_unique( @@ -429,7 +424,6 @@ void CrystalizerEQAudioProcessor::updateFilters() setCoeffs(rightChain.get<1>(), lowBand); leftChain .setBypassed<1>(false); rightChain.setBypassed<1>(false); - break; } @@ -512,7 +506,8 @@ void CrystalizerEQAudioProcessor::updateFilters() - + lowCutActive = (lowBandModes == 1); + highCutActive = (highBandModes == 1); } @@ -520,13 +515,14 @@ juce::String CrystalizerEQAudioProcessor::savePresetToFile() const { const auto nameInput = getPresetName(); - auto desktop = juce::File::getSpecialLocation(juce::File::userDesktopDirectory); + auto appData = juce::File::getSpecialLocation(juce::File::userApplicationDataDirectory); + + auto presetFolder = appData.getChildFile("AXIOM") + .getChildFile("CrystalizerEQ") + .getChildFile("Presets"); - // Unterordner auf dem Desktop anlegen - auto presetFolder = desktop.getChildFile("CrystalizerEQ_Presets"); presetFolder.createDirectory(); - // Datei vorbereiten auto file = presetFolder.getNonexistentChildFile(nameInput, ".xml"); juce::ValueTree preset ("Preset"); @@ -556,15 +552,12 @@ juce::String CrystalizerEQAudioProcessor::savePresetToFile() const { void CrystalizerEQAudioProcessor::loadPreset(const juce::String &preset){ - auto desktop = juce::File::getSpecialLocation(juce::File::userDesktopDirectory); + auto appData = juce::File::getSpecialLocation(juce::File::userApplicationDataDirectory); + auto presetFolder = appData.getChildFile("AXIOM") + .getChildFile("CrystalizerEQ") + .getChildFile("Presets"); - auto presetFolder = desktop.getChildFile("CrystalizerEQ_Presets"); - - juce::Array files = presetFolder.findChildFiles( - juce::File::findFiles, // nur Dateien (nicht Ordner) - false, // nicht rekursiv (kein Durchsuchen von Unterordnern) - "*.xml" // Pattern: alle Dateien - ); + auto files = presetFolder.findChildFiles(juce::File::findFiles, false, "*.xml"); for (const auto& f : files) { if (f.getFileName() != preset) { @@ -601,10 +594,10 @@ void CrystalizerEQAudioProcessor::loadPreset(const juce::String &preset){ } void CrystalizerEQAudioProcessor::deletePreset(const juce::String &preset) const{ - auto desktop = juce::File::getSpecialLocation(juce::File::userDesktopDirectory); - - // Unterordner auf dem Desktop anlegen - auto presetFolder = desktop.getChildFile("CrystalizerEQ_Presets"); + auto appData = juce::File::getSpecialLocation(juce::File::userApplicationDataDirectory); + auto presetFolder = appData.getChildFile("AXIOM") + .getChildFile("CrystalizerEQ") + .getChildFile("Presets"); juce::Array files = presetFolder.findChildFiles( juce::File::findFiles, // nur Dateien (nicht Ordner) @@ -644,10 +637,10 @@ void CrystalizerEQAudioProcessor::parameterChanged (const juce::String& id, floa juce::StringArray CrystalizerEQAudioProcessor::getPresetNamesArray() const{ juce::StringArray presetNames = {"Init"}; - auto desktop = juce::File::getSpecialLocation(juce::File::userDesktopDirectory); - - // Unterordner auf dem Desktop anlegen - auto presetFolder = desktop.getChildFile("CrystalizerEQ_Presets"); + auto appData = juce::File::getSpecialLocation(juce::File::userApplicationDataDirectory); + auto presetFolder = appData.getChildFile("AXIOM") + .getChildFile("CrystalizerEQ") + .getChildFile("Presets"); juce::Array files = presetFolder.findChildFiles( juce::File::findFiles, // nur Dateien (nicht Ordner) @@ -704,57 +697,11 @@ void CrystalizerEQAudioProcessor::processBlock (juce::AudioBuffer& buffer auto totalNumInputChannels = getTotalNumInputChannels(); auto totalNumOutputChannels = getTotalNumOutputChannels(); - - - - // In case we have more outputs than inputs, this code clears any output - // channels that didn't contain input data, (because these aren't - // guaranteed to be empty - they may contain garbage). - // This is here to avoid people getting screaming feedback - // when they first compile a plugin, but obviously you don't need to keep - // this code if your algorithm always overwrites all the output channels. for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i) buffer.clear (i, 0, buffer.getNumSamples()); juce::AudioBuffer lowBuf, highBuf; - - - // This is the place where you'd normally do the guts of your plugin's - // audio processing... - // Make sure to reset the state if your inner loop is processing - // the samples and the outer loop is handling the channels. - // Alternatively, you can process the samples with the channels - // interleaved by keeping the same state. - // (Einfacher Weg) – pro Block Parameter lesen & Filter updaten - - - - const bool testNoiseOn = apvts.getRawParameterValue("TestNoiseEnabled")->load() > 0.5f; - - if (testNoiseOn) - { - buffer.clear(); - const float noiseLevelDb = apvts.getRawParameterValue("TestNoiseLevel")->load(); - const float gain = juce::Decibels::decibelsToGain (noiseLevelDb); - - const int numSamples = buffer.getNumSamples(); - const int numChannels = buffer.getNumChannels(); - - for (int ch = 0; ch < numChannels; ++ch) - { - auto* write = buffer.getWritePointer (ch); - auto& rng = (ch == 0 ? noiseRandL : noiseRandR); - - for (int n = 0; n < numSamples; ++n) - { - // rng.nextFloat() ∈ [0,1) → in [-1,1) - const float white = 2.0f * rng.nextFloat() - 1.0f; - write[n] += white * gain; // ERSETZEN des Host-Inputs - } - } - } - const bool masterBypassed = apvts.getRawParameterValue("MasterBypass")->load() > 0.5f; if (masterBypassed) return; @@ -780,6 +727,7 @@ void CrystalizerEQAudioProcessor::processBlock (juce::AudioBuffer& buffer auto leftBlock = block.getSingleChannelBlock (0); auto rightBlock = block.getSingleChannelBlock (1); + juce::dsp::ProcessContextReplacing leftCtx (leftBlock); juce::dsp::ProcessContextReplacing rightCtx(rightBlock); diff --git a/CrystalizerEQ/PluginProcessor.h b/CrystalizerEQ/PluginProcessor.h index b6cb20e..cdf92c7 100644 --- a/CrystalizerEQ/PluginProcessor.h +++ b/CrystalizerEQ/PluginProcessor.h @@ -90,6 +90,9 @@ public: void resetAllParameters() const; + bool lowCutActive = false; + bool highCutActive = false; + AudioFIFO audioFIFO;