diff --git a/source/dsp/eq_match/eq_match_analyzer.cpp b/source/dsp/eq_match/eq_match_analyzer.cpp index 4ace0f7..4ff27bc 100644 --- a/source/dsp/eq_match/eq_match_analyzer.cpp +++ b/source/dsp/eq_match/eq_match_analyzer.cpp @@ -154,7 +154,8 @@ namespace zlEqMatch { } } // center diffs - const auto diffC = std::reduce(diffs.begin(), diffs.end(), 0.f) / static_cast(diffs.size()); + const auto diffC = std::reduce( + diffs.begin(), diffs.end(), 0.f) / static_cast(diffs.size()) - shift.load(); for (auto &diff: diffs) { diff -= diffC; } diff --git a/source/dsp/eq_match/eq_match_analyzer.hpp b/source/dsp/eq_match/eq_match_analyzer.hpp index b42a68c..f41bc57 100644 --- a/source/dsp/eq_match/eq_match_analyzer.hpp +++ b/source/dsp/eq_match/eq_match_analyzer.hpp @@ -57,6 +57,8 @@ namespace zlEqMatch { void setSlope(const float x) { slope.store(x); } + void setShift(const float x) { shift.store(x); } + std::array, pointNum> &getTarget() { return atomicTargetDBs; } std::array, pointNum> &getDiffs() { return atomicDiffs; } @@ -70,7 +72,7 @@ namespace zlEqMatch { std::array loadDBs{}; std::atomic toUpdateFromLoadDBs{false}; - std::atomic smooth{.5f}, slope{.0f}; + std::atomic smooth{.5f}, slope{.0f}, shift{0.f}; std::atomic toUpdateSmooth{true}; std::array smoothKernel{}; float rescale = 1.f; diff --git a/source/gui/interface_definitions.hpp b/source/gui/interface_definitions.hpp index 8a8f5ce..7cb62de 100644 --- a/source/gui/interface_definitions.hpp +++ b/source/gui/interface_definitions.hpp @@ -44,6 +44,7 @@ namespace zlInterface { matchPanelFit, matchLowCut, matchHighCut, + matchShift, matchFitRunning, settingNum }; @@ -52,7 +53,7 @@ namespace zlInterface { juce::Identifier("ui_setting_panel_show"), juce::Identifier("match_panel_show"), juce::Identifier("match_panel_fit"), juce::Identifier("match_low_cut"), juce::Identifier("match_high_cut"), - juce::Identifier("match_fit_running") + juce::Identifier("match_shift"), juce::Identifier("match_fit_running") }; inline std::array colourNames{ diff --git a/source/panel/curve_panel/curve_panel.cpp b/source/panel/curve_panel/curve_panel.cpp index 4f98df8..fa4c3f6 100644 --- a/source/panel/curve_panel/curve_panel.cpp +++ b/source/panel/curve_panel/curve_panel.cpp @@ -130,6 +130,9 @@ namespace zlPanel { for (const auto &panel : singlePanels) { panel->updateDragger(); } + if (showMatchPanel.load()) { + matchPanel.updateDraggers(); + } repaint(); currentT = nowT; } diff --git a/source/panel/curve_panel/match_panel/match_analyzer_panel.cpp b/source/panel/curve_panel/match_panel/match_analyzer_panel.cpp index aee206f..505424f 100644 --- a/source/panel/curve_panel/match_panel/match_analyzer_panel.cpp +++ b/source/panel/curve_panel/match_panel/match_analyzer_panel.cpp @@ -14,7 +14,7 @@ namespace zlPanel { juce::AudioProcessorValueTreeState ¶metersNA, zlInterface::UIBase &base) : analyzerRef(analyzer), parametersNARef(parametersNA), uiBase(base), - lowDragger(base), highDragger(base), + lowDragger(base), highDragger(base), shiftDragger(base), labelLAF(uiBase) { parametersNARef.addParameterListener(zlState::maximumDB::ID, this); parameterChanged(zlState::maximumDB::ID, parametersNARef.getRawParameterValue(zlState::maximumDB::ID)->load()); @@ -24,12 +24,20 @@ namespace zlPanel { runningLabel.setJustificationType(juce::Justification::centred); labelLAF.setFontScale(5.f); runningLabel.setLookAndFeel(&labelLAF); - addChildComponent(runningLabel); - lowDragger.getLAF().setDraggerShape(zlInterface::DraggerLookAndFeel::DraggerShape::rightArrow); - highDragger.getLAF().setDraggerShape(zlInterface::DraggerLookAndFeel::DraggerShape::leftArrow); - for (auto &d : {&lowDragger, &highDragger}) { - d->setYPortion(.5f); - d->setXYEnabled(true, false); + addChildComponent(runningLabel); { + lowDragger.getLAF().setDraggerShape(zlInterface::DraggerLookAndFeel::DraggerShape::rightArrow); + lowDragger.setYPortion(.5f); + lowDragger.setXYEnabled(true, false); + } { + highDragger.getLAF().setDraggerShape(zlInterface::DraggerLookAndFeel::DraggerShape::leftArrow); + highDragger.setYPortion(.5f); + highDragger.setXYEnabled(true, false); + } { + shiftDragger.getLAF().setDraggerShape(zlInterface::DraggerLookAndFeel::DraggerShape::upDownArrow); + shiftDragger.setXPortion(0.508304953195832f); + shiftDragger.setXYEnabled(false, true); + } + for (auto &d: {&lowDragger, &highDragger, &shiftDragger}) { d->setScale(scale); d->setActive(true); d->getButton().setToggleState(true, juce::dontSendNotification); @@ -47,8 +55,10 @@ namespace zlPanel { } void MatchAnalyzerPanel::paint(juce::Graphics &g) { - for (auto &d : {&lowDragger, &highDragger}) { - d->updateButton(); + if (std::abs(currentMaximumDB - maximumDB.load()) >= 1e-3f) { + currentMaximumDB = maximumDB.load(); + const auto actualShift = static_cast(uiBase.getProperty(zlInterface::settingIdx::matchShift)) * .5f; + shiftDragger.setYPortion(actualShift / currentMaximumDB + .5f); } g.fillAll(uiBase.getColourByIdx(zlInterface::backgroundColour).withAlpha(backgroundAlpha)); const auto thickness = uiBase.getFontSize() * 0.2f * uiBase.getSumCurveThickness(); @@ -83,7 +93,7 @@ namespace zlPanel { } void MatchAnalyzerPanel::resized() { - const auto bound = getLocalBounds().toFloat(); + auto bound = getLocalBounds().toFloat(); leftCorner.store({bound.getX() * 0.9f, bound.getBottom() * 1.1f}); rightCorner.store({bound.getRight() * 1.1f, bound.getBottom() * 1.1f}); atomicBound.store(bound); @@ -92,15 +102,14 @@ namespace zlPanel { bound.getWidth() * .5f, uiBase.getFontSize() * 5.f).toNearestInt()); lowDragger.setBounds(getLocalBounds()); highDragger.setBounds(getLocalBounds()); + shiftDragger.setBounds(getLocalBounds()); + shiftDragger.setPadding(0.f, 0.f, uiBase.getFontSize(), uiBase.getFontSize()); } void MatchAnalyzerPanel::updatePaths() { - const auto currentMaximumDB = - zlState::maximumDB::dBs[static_cast( - parametersNARef.getRawParameterValue(zlState::maximumDB::ID)->load())]; analyzerRef.updatePaths(path1, path2, path3, atomicBound.load(), - {-72.f, -72.f, -currentMaximumDB * dBScale.load()}); { + {-72.f, -72.f, -maximumDB.load() * dBScale.load()}); { juce::GenericScopedLock lock{pathLock}; recentPath1 = path1; recentPath2 = path2; @@ -112,16 +121,18 @@ namespace zlPanel { void MatchAnalyzerPanel::visibilityChanged() { lowDragger.setXPortion(0.f); highDragger.setXPortion(1.f); + shiftDragger.setYPortion(.5f); draggerValueChanged(&lowDragger); draggerValueChanged(&highDragger); + draggerValueChanged(&shiftDragger); } void MatchAnalyzerPanel::valueTreePropertyChanged(juce::ValueTree &, const juce::Identifier &property) { - if (property == zlInterface::identifiers[static_cast(zlInterface::settingIdx::matchPanelFit)]) { + if (zlInterface::UIBase::isProperty(zlInterface::settingIdx::matchPanelFit, property)) { const auto f = static_cast(uiBase.getProperty(zlInterface::settingIdx::matchPanelFit)); backgroundAlpha = f ? .2f : .5f; showAverage = !f; - } else if (uiBase.isProperty(zlInterface::settingIdx::matchFitRunning, property)) { + } else if (zlInterface::UIBase::isProperty(zlInterface::settingIdx::matchFitRunning, property)) { runningLabel.setVisible(static_cast(uiBase.getProperty(zlInterface::settingIdx::matchFitRunning))); } } @@ -132,7 +143,7 @@ namespace zlPanel { } void MatchAnalyzerPanel::lookAndFeelChanged() { - for (auto &d : {&lowDragger, &highDragger}) { + for (auto &d: {&lowDragger, &highDragger, &shiftDragger}) { d->getLAF().setColour(uiBase.getTextColor()); } } @@ -142,6 +153,16 @@ namespace zlPanel { uiBase.setProperty(zlInterface::settingIdx::matchLowCut, lowDragger.getXPortion()); } else if (dragger == &highDragger) { uiBase.setProperty(zlInterface::settingIdx::matchHighCut, highDragger.getXPortion()); + } else if (dragger == &shiftDragger) { + const auto actualShift = (shiftDragger.getYPortion() - .5f) * maximumDB.load() * 2.f; + uiBase.setProperty(zlInterface::settingIdx::matchShift, actualShift); + analyzerRef.setShift(actualShift); + } + } + + void MatchAnalyzerPanel::updateDraggers() { + for (auto &d: {&lowDragger, &highDragger, &shiftDragger}) { + d->updateButton(); } } } // zlPanel diff --git a/source/panel/curve_panel/match_panel/match_analyzer_panel.hpp b/source/panel/curve_panel/match_panel/match_analyzer_panel.hpp index faed670..e73d280 100644 --- a/source/panel/curve_panel/match_panel/match_analyzer_panel.hpp +++ b/source/panel/curve_panel/match_panel/match_analyzer_panel.hpp @@ -34,6 +34,8 @@ namespace zlPanel { void updatePaths(); + void updateDraggers(); + private: zlEqMatch::EqMatchAnalyzer &analyzerRef; juce::AudioProcessorValueTreeState ¶metersNARef; @@ -46,8 +48,9 @@ namespace zlPanel { float backgroundAlpha = .5f; bool showAverage{true}; std::atomic dBScale{1.f}; + float currentMaximumDB{zlState::maximumDB::dBs[static_cast(zlState::maximumDB::defaultI)]}; std::atomic maximumDB{zlState::maximumDB::dBs[static_cast(zlState::maximumDB::defaultI)]}; - zlInterface::Dragger lowDragger, highDragger; + zlInterface::Dragger lowDragger, highDragger, shiftDragger; zlInterface::NameLookAndFeel labelLAF; juce::Label runningLabel; static constexpr auto scale = 1.5f; diff --git a/source/panel/curve_panel/match_panel/match_panel.hpp b/source/panel/curve_panel/match_panel/match_panel.hpp index 346bf9f..b843389 100644 --- a/source/panel/curve_panel/match_panel/match_panel.hpp +++ b/source/panel/curve_panel/match_panel/match_panel.hpp @@ -27,6 +27,10 @@ namespace zlPanel { matchAnalyzerPanel.updatePaths(); } + void updateDraggers() { + matchAnalyzerPanel.updateDraggers(); + } + void visibilityChanged() override { matchAnalyzerPanel.visibilityChanged(); }