From f7042977a99910fa9c2f79ed64c90a1e428e42f5 Mon Sep 17 00:00:00 2001 From: Vesa Date: Sat, 21 Jun 2014 10:56:28 +0300 Subject: [PATCH] Logscale: Fix negative ranges This fixes errors that happen on models that have both logarithmic scale and a range that goes to the negative. --- include/lmms_math.h | 16 ++++++++++++++-- src/gui/widgets/knob.cpp | 6 ++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/include/lmms_math.h b/include/lmms_math.h index 9c22014af..6f361c971 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -128,13 +128,24 @@ static inline double sinc( double _x ) } +//! @brief Exponential function that deals with negative bases +static inline float signedPowf( float v, float e ) +{ + return v < 0 + ? powf( -v, e ) * -1.0f + : powf( v, e ); +} + + //! @brief Scales @value from linear to logarithmic. //! Value should be within [0,1] static inline float logToLinearScale( float min, float max, float value ) { if( min < 0 ) { - return powf( value * ( 1.0f - min / max ) + min / max, F_E ) * ( max - min ) + min; + const float mmax = qMax( qAbs( min ), qAbs( max ) ); + const float val = value * ( max - min ) + min; + return signedPowf( val / mmax, F_E ) * mmax; } return powf( value, F_E ) * ( max - min ) + min; } @@ -147,7 +158,8 @@ static inline float linearToLogScale( float min, float max, float value ) const float val = ( value - min ) / ( max - min ); if( min < 0 ) { - return powf( val * ( 1.0f - min / max ) + min / max, EXP ) * ( max - min ) + min; + const float mmax = qMax( qAbs( min ), qAbs( max ) ); + return signedPowf( value / mmax, EXP ) * mmax; } return powf( val, EXP ) * ( max - min ) + min; } diff --git a/src/gui/widgets/knob.cpp b/src/gui/widgets/knob.cpp index 3d127d4d2..7bb226795 100644 --- a/src/gui/widgets/knob.cpp +++ b/src/gui/widgets/knob.cpp @@ -674,8 +674,10 @@ void knob::setPosition( const QPoint & _p ) if( model()->isScaleLogarithmic() ) // logarithmic code { - const float pos = ( oldValue - model()->minValue() ) / model()->range(); - const float ratio = 0.1f + pos * 15.f; + const float pos = model()->minValue() < 0 + ? oldValue / qMax( qAbs( model()->maxValue() ), qAbs( model()->minValue() ) ) + : ( oldValue - model()->minValue() ) / model()->range(); + const float ratio = 0.1f + qAbs( pos ) * 15.f; float newValue = value * ratio; if( qAbs( newValue ) >= step ) {