From 5c5ec5dfe78b23752a619bac3af9aa884c43b8db Mon Sep 17 00:00:00 2001 From: Rossmaxx Date: Tue, 16 Jul 2024 11:50:16 +0530 Subject: [PATCH 01/17] simplified fraction and absfraction functions --- include/lmms_math.h | 84 ++++++++------------------------------------- 1 file changed, 14 insertions(+), 70 deletions(-) diff --git a/include/lmms_math.h b/include/lmms_math.h index bf5e53a2b53..bdc237adbee 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -36,21 +36,20 @@ namespace lmms { - -#ifdef __INTEL_COMPILER - -static inline float absFraction( const float _x ) -{ - return( _x - floorf( _x ) ); -} - -static inline float fraction( const float _x ) +/*! + * @brief Returns the fractional part of a float, a value between -1.0f and 1.0f. + * + * fraction( 2.3) => 0.3 + * fraction(-2.3) => -0.3 + * + * Note that if the return value is used as a phase of an oscillator, that the oscillator must support + * negative phases. + */ +static inline float fraction(const float x) { - return( _x - floorf( _x ) - ( _x >= 0.0f ? 0.0 : 1.0 ) ); + return x - std::floor(x); } -#else - /*! * @brief Returns the wrapped fractional part of a float, a value between 0.0f and 1.0f. * @@ -61,68 +60,13 @@ static inline float fraction( const float _x ) * If the result is interpreted as a phase of an oscillator, it makes that negative phases are * converted to positive phases. */ -static inline float absFraction( const float _x ) -{ - return( _x - ( _x >= 0.0f ? static_cast( _x ) : - static_cast( _x ) - 1 ) ); -} - -/*! - * @brief Returns the fractional part of a float, a value between -1.0f and 1.0f. - * - * fraction( 2.3) => 0.3 - * fraction(-2.3) => -0.3 - * - * Note that if the return value is used as a phase of an oscillator, that the oscillator must support - * negative phases. - */ -static inline float fraction( const float _x ) +static inline float absFraction(const float x) { - return( _x - static_cast( _x ) ); + float dec = fraction(x); + return (dec >= 0 ? dec : dec + 1.0f); } -#if 0 -// SSE3-version -static inline float absFraction( float _x ) -{ - unsigned int tmp; - asm( - "fld %%st\n\t" - "fisttp %1\n\t" - "fild %1\n\t" - "ftst\n\t" - "sahf\n\t" - "jae 1f\n\t" - "fld1\n\t" - "fsubrp %%st, %%st(1)\n\t" - "1:\n\t" - "fsubrp %%st, %%st(1)" - : "+t"( _x ), "=m"( tmp ) - : - : "st(1)", "cc" ); - return( _x ); -} - -static inline float absFraction( float _x ) -{ - unsigned int tmp; - asm( - "fld %%st\n\t" - "fisttp %1\n\t" - "fild %1\n\t" - "fsubrp %%st, %%st(1)" - : "+t"( _x ), "=m"( tmp ) - : - : "st(1)" ); - return( _x ); -} -#endif - -#endif // __INTEL_COMPILER - - - constexpr int FAST_RAND_MAX = 32767; static inline int fast_rand() { From 1dded27d6104a7e540076918f8d6f2e7737ffd15 Mon Sep 17 00:00:00 2001 From: Rossmaxx Date: Tue, 16 Jul 2024 11:50:47 +0530 Subject: [PATCH 02/17] removed unused fastSqrt() function --- include/lmms_math.h | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/include/lmms_math.h b/include/lmms_math.h index bdc237adbee..c112719deef 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -244,19 +244,6 @@ static inline float sqrt_neg( float val ) } -// fast approximation of square root -static inline float fastSqrt( float n ) -{ - union - { - int32_t i; - float f; - } u; - u.f = n; - u.i = ( u.i + ( 127 << 23 ) ) >> 1; - return u.f; -} - //! returns value furthest from zero template static inline T absMax( T a, T b ) From e30614c72d2cecc3bf428944532de84cd08eaf18 Mon Sep 17 00:00:00 2001 From: Rossmaxx Date: Tue, 16 Jul 2024 11:54:22 +0530 Subject: [PATCH 03/17] unused absMin() and absMax() --- include/lmms_math.h | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/include/lmms_math.h b/include/lmms_math.h index c112719deef..46884977e47 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -244,20 +244,6 @@ static inline float sqrt_neg( float val ) } -//! returns value furthest from zero -template -static inline T absMax( T a, T b ) -{ - return std::abs(a) > std::abs(b) ? a : b; -} - -//! returns value nearest to zero -template -static inline T absMin( T a, T b ) -{ - return std::abs(a) < std::abs(b) ? a : b; -} - //! Returns the linear interpolation of the two values template constexpr T lerp(T a, T b, F t) From d8453319c5c3b4051f2c8f0f4c536d9ed0fa74ad Mon Sep 17 00:00:00 2001 From: Rossmaxx Date: Tue, 16 Jul 2024 12:11:53 +0530 Subject: [PATCH 04/17] simplified numDigitsAsInt() function --- include/lmms_math.h | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/include/lmms_math.h b/include/lmms_math.h index 46884977e47..6d43bd4532b 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -255,23 +255,13 @@ constexpr T lerp(T a, T b, F t) // @note Once we upgrade to C++20, we could probably use std::formatted_size static inline int numDigitsAsInt(float f) { - // use rounding: - // LcdSpinBox sometimes uses roundf(), sometimes cast rounding - // we use rounding to be on the "safe side" - const float rounded = roundf(f); - int asInt = static_cast(rounded); + int asInt = std::abs(static_cast(std::round(f))); int digits = 1; // always at least 1 - if(asInt < 0) - { - ++digits; - asInt = -asInt; - } - // "asInt" is positive from now - int32_t power = 1; - for(int32_t i = 1; i<10; ++i) + int power = 1; + for (int i = 1; i < 10; ++i) { power *= 10; - if(static_cast(asInt) >= power) { ++digits; } // 2 digits for >=10, 3 for >=100 + if (asInt >= power) { ++digits; } // 2 digits for >=10, 3 for >=100 else { break; } } return digits; From b1bc1731c4e0736f9b1513d5a7003ca929c8b6c6 Mon Sep 17 00:00:00 2001 From: Rossmaxx Date: Tue, 16 Jul 2024 12:19:38 +0530 Subject: [PATCH 05/17] removed fastPow() --- include/lmms_math.h | 12 ------------ plugins/Kicker/KickerOsc.h | 4 ++-- plugins/Monstro/Monstro.cpp | 2 +- 3 files changed, 3 insertions(+), 15 deletions(-) diff --git a/include/lmms_math.h b/include/lmms_math.h index 6d43bd4532b..a41a807bdfc 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -125,18 +125,6 @@ static inline double fastFma( double a, double b, double c ) #endif } -// source: http://martin.ankerl.com/2007/10/04/optimized-pow-approximation-for-java-and-c-c/ -static inline double fastPow( double a, double b ) -{ - union - { - double d; - int32_t x[2]; - } u = { a }; - u.x[1] = static_cast( b * ( u.x[1] - 1072632447 ) + 1072632447 ); - u.x[0] = 0; - return u.d; -} // sinc function static inline double sinc( double _x ) diff --git a/plugins/Kicker/KickerOsc.h b/plugins/Kicker/KickerOsc.h index 420373512af..a11b0fc5521 100644 --- a/plugins/Kicker/KickerOsc.h +++ b/plugins/Kicker/KickerOsc.h @@ -64,7 +64,7 @@ class KickerOsc { for( fpp_t frame = 0; frame < frames; ++frame ) { - const double gain = ( 1 - fastPow( ( m_counter < m_length ) ? m_counter / m_length : 1, m_env ) ); + const double gain = 1 - std::pow((m_counter < m_length) ? m_counter / m_length : 1, m_env); const sample_t s = ( Oscillator::sinSample( m_phase ) * ( 1 - m_noise ) ) + ( Oscillator::noiseSample( 0 ) * gain * gain * m_noise ); buf[frame][0] = s * gain; buf[frame][1] = s * gain; @@ -80,7 +80,7 @@ class KickerOsc m_FX.nextSample( buf[frame][0], buf[frame][1] ); m_phase += m_freq / sampleRate; - const double change = ( m_counter < m_length ) ? ( ( m_startFreq - m_endFreq ) * ( 1 - fastPow( m_counter / m_length, m_slope ) ) ) : 0; + const double change = (m_counter < m_length) ? ((m_startFreq - m_endFreq) * (1 - std::pow(m_counter / m_length, m_slope))) : 0; m_freq = m_endFreq + change; ++m_counter; } diff --git a/plugins/Monstro/Monstro.cpp b/plugins/Monstro/Monstro.cpp index 7063be0e265..609ba6a6429 100644 --- a/plugins/Monstro/Monstro.cpp +++ b/plugins/Monstro/Monstro.cpp @@ -858,7 +858,7 @@ inline sample_t MonstroSynth::calcSlope( int slope, sample_t s ) { if( m_parent->m_slope[slope] == 1.0f ) return s; if( s == 0.0f ) return s; - return fastPow( s, m_parent->m_slope[slope] ); + return std::pow(s, m_parent->m_slope[slope]); } From 0853f5a21e0591c5df7d41f67daed798ab8010cc Mon Sep 17 00:00:00 2001 From: Rossmaxx Date: Tue, 16 Jul 2024 12:35:01 +0530 Subject: [PATCH 06/17] move roundAt to math header --- include/lmms_math.h | 9 +++++++++ src/core/AutomatableModel.cpp | 15 +-------------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/include/lmms_math.h b/include/lmms_math.h index a41a807bdfc..76a5488dc37 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -125,6 +125,15 @@ static inline double fastFma( double a, double b, double c ) #endif } +// function to round 'value' depending on step size +template +static void roundAt(T& value, const T& where, const T& step_size) +{ + if (std::abs(value - where) < typeInfo::minEps() * std::abs(step_size)) + { + value = where; + } +} // sinc function static inline double sinc( double _x ) diff --git a/src/core/AutomatableModel.cpp b/src/core/AutomatableModel.cpp index abda0b43ed3..def44edf1fe 100644 --- a/src/core/AutomatableModel.cpp +++ b/src/core/AutomatableModel.cpp @@ -350,24 +350,11 @@ float AutomatableModel::inverseScaledValue( float value ) const -//! @todo: this should be moved into a maths header -template -void roundAt( T& value, const T& where, const T& step_size ) -{ - if (std::abs(value - where) - < typeInfo::minEps() * std::abs(step_size)) - { - value = where; - } -} - - - template void AutomatableModel::roundAt( T& value, const T& where ) const { - lmms::roundAt(value, where, m_step); + roundAt(value, where, m_step); } From 41b1e864abd504cdd62535106ca944469b8cddf2 Mon Sep 17 00:00:00 2001 From: Rossmaxx Date: Tue, 16 Jul 2024 14:18:49 +0530 Subject: [PATCH 07/17] use lmms namespace for roundAt --- src/core/AutomatableModel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/AutomatableModel.cpp b/src/core/AutomatableModel.cpp index def44edf1fe..7ea456a8b45 100644 --- a/src/core/AutomatableModel.cpp +++ b/src/core/AutomatableModel.cpp @@ -354,7 +354,7 @@ float AutomatableModel::inverseScaledValue( float value ) const template void AutomatableModel::roundAt( T& value, const T& where ) const { - roundAt(value, where, m_step); + lmms::roundAt(value, where, m_step); } From 6e7be745aa59372af38b6b6efb9beb3d42c4263d Mon Sep 17 00:00:00 2001 From: Rossmaxx Date: Tue, 16 Jul 2024 14:20:57 +0530 Subject: [PATCH 08/17] fixed compilation --- include/lmms_math.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/lmms_math.h b/include/lmms_math.h index 76a5488dc37..c9668b10530 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -30,6 +30,7 @@ #include #include +#include "lmms_basics.h" #include "lmms_constants.h" #include "lmmsconfig.h" #include From 2ab7411d41db1e7fa5346934af2caed02561cf73 Mon Sep 17 00:00:00 2001 From: Rossmaxx Date: Tue, 16 Jul 2024 16:27:06 +0530 Subject: [PATCH 09/17] patch up calculation flaw --- include/lmms_math.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/lmms_math.h b/include/lmms_math.h index c9668b10530..57fba1724df 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -253,7 +253,8 @@ constexpr T lerp(T a, T b, F t) // @note Once we upgrade to C++20, we could probably use std::formatted_size static inline int numDigitsAsInt(float f) { - int asInt = std::abs(static_cast(std::round(f))); + int asInt = static_cast(std::round(f)); + if (asInt < 0) { asInt = std::abs(asInt) + 1} int digits = 1; // always at least 1 int power = 1; for (int i = 1; i < 10; ++i) From e4614c3faeb6b69b06c2b2947c6d106ac4caeb88 Mon Sep 17 00:00:00 2001 From: Rossmaxx Date: Tue, 16 Jul 2024 16:27:06 +0530 Subject: [PATCH 10/17] patch up calculation flaw --- include/lmms_math.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/lmms_math.h b/include/lmms_math.h index 57fba1724df..1916a10d38d 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -254,7 +254,7 @@ constexpr T lerp(T a, T b, F t) static inline int numDigitsAsInt(float f) { int asInt = static_cast(std::round(f)); - if (asInt < 0) { asInt = std::abs(asInt) + 1} + if (asInt < 0) { asInt = std::abs(asInt) + 1} // there's a rounding error with negative values int digits = 1; // always at least 1 int power = 1; for (int i = 1; i < 10; ++i) From 311941ce20a4e2560f72480e53b1806e0bcb398b Mon Sep 17 00:00:00 2001 From: Rossmaxx <74815851+Rossmaxx@users.noreply.github.com> Date: Tue, 16 Jul 2024 17:07:04 +0530 Subject: [PATCH 11/17] Stupid semicolon miss --- include/lmms_math.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/lmms_math.h b/include/lmms_math.h index 1916a10d38d..bd088ae7165 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -254,7 +254,7 @@ constexpr T lerp(T a, T b, F t) static inline int numDigitsAsInt(float f) { int asInt = static_cast(std::round(f)); - if (asInt < 0) { asInt = std::abs(asInt) + 1} // there's a rounding error with negative values + if (asInt < 0) { asInt = std::abs(asInt) + 1; } // there's a rounding error with negative values int digits = 1; // always at least 1 int power = 1; for (int i = 1; i < 10; ++i) From aa1408f75eff940f3723f14a08bd915cc991b7c4 Mon Sep 17 00:00:00 2001 From: Rossmaxx <74815851+Rossmaxx@users.noreply.github.com> Date: Tue, 16 Jul 2024 17:31:14 +0530 Subject: [PATCH 12/17] Fixed tests failing. --- include/lmms_math.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/lmms_math.h b/include/lmms_math.h index bd088ae7165..75773b7506c 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -254,8 +254,11 @@ constexpr T lerp(T a, T b, F t) static inline int numDigitsAsInt(float f) { int asInt = static_cast(std::round(f)); - if (asInt < 0) { asInt = std::abs(asInt) + 1; } // there's a rounding error with negative values int digits = 1; // always at least 1 + if (asInt < 0) { + ++digits + asInt = -1 * asInt; + } int power = 1; for (int i = 1; i < 10; ++i) { From bb82c0df104d74e99988459f9e92a3bf9b55ede6 Mon Sep 17 00:00:00 2001 From: Rossmaxx <74815851+Rossmaxx@users.noreply.github.com> Date: Tue, 16 Jul 2024 17:33:45 +0530 Subject: [PATCH 13/17] Negate diff --- include/lmms_math.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/lmms_math.h b/include/lmms_math.h index 75773b7506c..9121b2fdee9 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -255,9 +255,10 @@ static inline int numDigitsAsInt(float f) { int asInt = static_cast(std::round(f)); int digits = 1; // always at least 1 - if (asInt < 0) { + if (asInt < 0) + { ++digits - asInt = -1 * asInt; + asInt = -asInt; } int power = 1; for (int i = 1; i < 10; ++i) From 9287e4e5edfaac284fdb5a7baad48abeca9f4aac Mon Sep 17 00:00:00 2001 From: Rossmaxx <74815851+Rossmaxx@users.noreply.github.com> Date: Tue, 16 Jul 2024 17:35:23 +0530 Subject: [PATCH 14/17] Another semicolon --- include/lmms_math.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/lmms_math.h b/include/lmms_math.h index 9121b2fdee9..dac9c0ce87c 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -257,7 +257,7 @@ static inline int numDigitsAsInt(float f) int digits = 1; // always at least 1 if (asInt < 0) { - ++digits + ++digits; asInt = -asInt; } int power = 1; From cb069f9f456612a6798a150e4a5628044aa94d0a Mon Sep 17 00:00:00 2001 From: Rossmaxx <74815851+Rossmaxx@users.noreply.github.com> Date: Wed, 17 Jul 2024 16:11:54 +0530 Subject: [PATCH 15/17] Code review from saker Co-authored-by: saker --- include/lmms_math.h | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/include/lmms_math.h b/include/lmms_math.h index dac9c0ce87c..680c7b4e366 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -46,9 +46,9 @@ namespace lmms * Note that if the return value is used as a phase of an oscillator, that the oscillator must support * negative phases. */ -static inline float fraction(const float x) +static inline float fraction(float x) { - return x - std::floor(x); + return x - static_cast(x); } /*! @@ -63,8 +63,7 @@ static inline float fraction(const float x) */ static inline float absFraction(const float x) { - float dec = fraction(x); - return (dec >= 0 ? dec : dec + 1.0f); + return x - std::floor(x); } @@ -126,11 +125,11 @@ static inline double fastFma( double a, double b, double c ) #endif } -// function to round 'value' depending on step size +//! Round `value` to `where` depending on step size template -static void roundAt(T& value, const T& where, const T& step_size) +static void roundAt(T& value, const T& where, const T& stepSize) { - if (std::abs(value - where) < typeInfo::minEps() * std::abs(step_size)) + if (std::abs(value - where) < typeInfo::minEps() * std::abs(stepSize)) { value = where; } From cb3be41cd847094ed52b28da62e3ef2a9f98b954 Mon Sep 17 00:00:00 2001 From: Rossmaxx Date: Fri, 19 Jul 2024 15:31:31 +0530 Subject: [PATCH 16/17] it's const --- include/lmms_math.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/lmms_math.h b/include/lmms_math.h index 680c7b4e366..2edea761d4c 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -46,7 +46,7 @@ namespace lmms * Note that if the return value is used as a phase of an oscillator, that the oscillator must support * negative phases. */ -static inline float fraction(float x) +static inline float fraction(const float x) { return x - static_cast(x); } From 7ebb8c24c76cac15fef9218009d27c92a58c18ef Mon Sep 17 00:00:00 2001 From: Rossmaxx Date: Fri, 19 Jul 2024 15:38:24 +0530 Subject: [PATCH 17/17] use std::trunc() --- include/lmms_math.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/lmms_math.h b/include/lmms_math.h index 2edea761d4c..499205342bf 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -48,7 +48,7 @@ namespace lmms */ static inline float fraction(const float x) { - return x - static_cast(x); + return x - std::trunc(x); } /*!