diff --git a/include/Fader.h b/include/Fader.h index 00a2c5546..e43a6a561 100644 --- a/include/Fader.h +++ b/include/Fader.h @@ -118,10 +118,21 @@ private: void paintEvent(QPaintEvent* ev) override; void paintLevels(QPaintEvent* ev, QPainter& painter, bool linear = false); + void paintFaderTicks(QPainter& painter); int calculateKnobPosYFromModel() const; void setVolumeByLocalPixelValue(int y); + // Computes the scaled ratio between the maximum dB value supported by the model and the minimum + // dB value that's supported by the fader from the given actual dB value. + // If the provided input value lies inside the aforementioned interval then the result will be + // a value between 0 (value == minimum value) and 1 (value == maximum model value). + // If you look at the graphical representation of the fader then 0 represents a point at the bottom + // of the fader and 1 a point at the top of the fader. + // The ratio is scaled by an internal exponent which is an implementation detail that cannot be + // changed for now. + float computeScaledRatio(float dBValue) const; + void setPeak(float fPeak, float& targetPeak, float& persistentPeak, QElapsedTimer& lastPeakTimer); void updateTextFloat(); diff --git a/src/gui/widgets/Fader.cpp b/src/gui/widgets/Fader.cpp index b5a1f0709..422e60b9f 100644 --- a/src/gui/widgets/Fader.cpp +++ b/src/gui/widgets/Fader.cpp @@ -322,18 +322,16 @@ int Fader::calculateKnobPosYFromModel() const } else { - auto const maxDb = ampToDbfs(maxV); - // Make sure that we do not get values less that the minimum fader dbFS // for the calculations that will follow. auto const actualDb = std::max(m_faderMinDb, ampToDbfs(value)); - auto const ratio = (actualDb - m_faderMinDb) / (maxDb - m_faderMinDb); + const auto scaledRatio = computeScaledRatio(actualDb); // This returns results between: // * m_knob.height() for a ratio of 1 // * height() for a ratio of 0 - return height() - (height() - m_knob.height()) * std::pow(ratio, c_dBScalingExponent); + return height() - (height() - m_knob.height()) * scaledRatio; } } else @@ -409,6 +407,15 @@ void Fader::setVolumeByLocalPixelValue(int y) } } +float Fader::computeScaledRatio(float dBValue) const +{ + const auto maxDb = ampToDbfs(model()->maxValue()); + + const auto ratio = (dBValue - m_faderMinDb) / (maxDb - m_faderMinDb); + + return std::pow(ratio, c_dBScalingExponent); +} + /// /// Set peak value (0.0 .. 1.0) @@ -501,6 +508,11 @@ void Fader::paintEvent(QPaintEvent* ev) // Draw the levels with peaks paintLevels(ev, painter, !m_levelsDisplayedInDBFS); + if (modelIsLinear()) + { + paintFaderTicks(painter); + } + // Draw the knob painter.drawPixmap((width() - m_knob.width()) / 2, calculateKnobPosYFromModel() - m_knob.height(), m_knob); } @@ -658,4 +670,22 @@ void Fader::paintLevels(QPaintEvent* ev, QPainter& painter, bool linear) painter.restore(); } +void Fader::paintFaderTicks(QPainter& painter) +{ + painter.save(); + + painter.setPen(QColor(255, 255, 255, 128)); + + for (float i = 6.f; i >= -120.f; i-= 6.f) + { + const auto scaledRatio = computeScaledRatio(i); + const auto maxHeight = height() - (height() - m_knob.height()) * scaledRatio - (m_knob.height() / 2); + + painter.drawLine(QPointF(0, maxHeight), QPointF(1, maxHeight)); + painter.drawLine(QPointF(width() - 1, maxHeight), QPointF(width(), maxHeight)); + } + + painter.restore(); +} + } // namespace lmms::gui