From cb9770a7574b11422580fedf438dcdbff4730c8d Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Sat, 31 Jan 2026 08:11:51 -0700 Subject: [PATCH] Log scaling for better vol control --- gui/GraphEditorWidget.cpp | 19 +++++++++++++++---- gui/WarpGraphModel.cpp | 12 ++++++++++-- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/gui/GraphEditorWidget.cpp b/gui/GraphEditorWidget.cpp index 8dc75df..b2f916d 100644 --- a/gui/GraphEditorWidget.cpp +++ b/gui/GraphEditorWidget.cpp @@ -48,9 +48,20 @@ #include #include +#include #include #include +namespace { +inline float sliderToVolume(int slider) { + float x = static_cast(slider) / 100.0f; + return x * x * x; +} +inline int volumeToSlider(float volume) { + return static_cast(std::round(std::cbrt(volume) * 100.0f)); +} +} + class DeleteVirtualNodeCommand : public QUndoCommand { public: struct Snapshot { @@ -1192,7 +1203,7 @@ void GraphEditorWidget::wireVolumeWidget(QtNodes::NodeId nodeId) { connect(vol, &NodeVolumeWidget::volumeChanged, this, [this, capturedId](int value) { auto state = m_model->nodeVolumeState(capturedId); - state.volume = static_cast(value) / 100.0f; + state.volume = sliderToVolume(value); m_model->setNodeVolumeState(capturedId, state); }); @@ -1268,7 +1279,7 @@ void GraphEditorWidget::rebuildMixerStrips() { auto *slider = new ClickSlider(Qt::Horizontal); slider->setRange(0, 100); auto state = m_model->nodeVolumeState(nodeId); - slider->setValue(static_cast(state.volume * 100.0f)); + slider->setValue(volumeToSlider(state.volume)); slider->setStyleSheet(QStringLiteral( "QSlider::groove:horizontal {" " background: #1a1a1e; border-radius: 3px; height: 6px; }" @@ -1301,7 +1312,7 @@ void GraphEditorWidget::rebuildMixerStrips() { connect(slider, &QSlider::valueChanged, this, [this, capturedId](int value) { auto s = m_model->nodeVolumeState(capturedId); - s.volume = static_cast(value) / 100.0f; + s.volume = sliderToVolume(value); m_model->setNodeVolumeState(capturedId, s); }); @@ -1330,7 +1341,7 @@ void GraphEditorWidget::rebuildMixerStrips() { return; QSignalBlocker sb(slider); QSignalBlocker mb(muteBtn); - slider->setValue(static_cast(cur.volume * 100.0f)); + slider->setValue(volumeToSlider(cur.volume)); muteBtn->setChecked(cur.mute); }); diff --git a/gui/WarpGraphModel.cpp b/gui/WarpGraphModel.cpp index dc031a6..d1af6aa 100644 --- a/gui/WarpGraphModel.cpp +++ b/gui/WarpGraphModel.cpp @@ -13,6 +13,14 @@ #include #include +#include + +namespace { +inline int volumeToSlider(float volume) { + return static_cast(std::round(std::cbrt(volume) * 100.0f)); +} +} + #include #include @@ -633,7 +641,7 @@ void WarpGraphModel::refreshFromClient() { float vol = volResult.value.volume; bool mute = volResult.value.mute; - int sliderVal = static_cast(std::round(vol * 100.0f)); + int sliderVal = volumeToSlider(vol); sliderVal = std::clamp(sliderVal, 0, 150); auto stateIt = m_volumeStates.find(qtId); @@ -820,7 +828,7 @@ void WarpGraphModel::setNodeVolumeState(QtNodes::NodeId nodeId, if (wIt != m_volumeWidgets.end()) { auto *w = qobject_cast(wIt->second); if (w) { - w->setVolume(static_cast(state.volume * 100.0f)); + w->setVolume(volumeToSlider(state.volume)); w->setMuted(state.mute); } }