diff --git a/include/BandLimitedWave.h b/include/BandLimitedWave.h index 9971cf200..f8467b1bb 100644 --- a/include/BandLimitedWave.h +++ b/include/BandLimitedWave.h @@ -128,58 +128,26 @@ public: const float ph = fraction( _ph ); const float lookupf = ph * static_cast( tlen ); const int lookup = static_cast( lookupf ); + const float ip = fraction( lookupf ); + const sample_t s1 = s_waveforms[ _wave ].sampleAt( t, lookup ); const sample_t s2 = s_waveforms[ _wave ].sampleAt( t, ( lookup + 1 ) % tlen ); - return linearInterpolate( s1, s2, fraction( lookupf ) ); + const sample_t s12 = linearInterpolate( s1, s2, ip ); + return s12; + /*if( _wavelen > 0.75 * tlen ) return s12; - /*const int tlen1 = 1 << t; - const int tlen2 = 1 << ( t - 1 ); + lookup = lookup >> 1; + tlen = tlen >> 1; + t -= 1; + const sample_t s3 = s_waveforms[ _wave ].sampleAt( t, lookup ); + const sample_t s4 = s_waveforms[ _wave ].sampleAt( t, ( lookup + 1 ) % tlen ); + const sample_t s34 = linearInterpolate( s3, s4, ip ); - const float ph = fraction( _ph ); - const float lookupf = ph * static_cast( tlen1 ); - const int lookup1 = static_cast( lookupf ); - const int lookup2 = static_cast( ph * static_cast( tlen2 ) ); - - const sample_t s1 = linearInterpolate( s_waveforms[ _wave ].sampleAt( t, lookup1 ), - s_waveforms[ _wave ].sampleAt( t, ( lookup1 + 1 ) % tlen1 ), - fraction( lookupf ) ); - const sample_t s2 = s_waveforms[ _wave ].sampleAt( t - 1, lookup2 ); - - const float ip = static_cast( tlen1 - _wavelen ) / static_cast( tlen2 ); + const float ip2 = ( ( _wavelen - tlen ) / tlen - 0.5 ) * 2.0; + + return linearInterpolate( s34, s12, ip2 );*/ - return linearInterpolate( s1, s2, ip );*/ - }; - - /*! \brief The same as oscillate but uses cosinus interpolation instead of linear. - */ - static inline sample_t oscillateCos( float _ph, float _wavelen, Waveforms _wave ) - { - int t = MAXLEN; - while( ( 1 << t ) > _wavelen ) { t--; } - t = qMax( 1, t ); - - const int tlen = 1 << t; - const float ph = fraction( _ph ); - const int lookup = static_cast( ph * tlen ); - const sample_t s1 = s_waveforms[ _wave ].sampleAt( t, lookup ); - const sample_t s2 = s_waveforms[ _wave ].sampleAt( t, ( lookup + 1 ) % tlen ); - - return cosinusInterpolate( s1, s2, ph ); - }; - - /*! \brief The same as oscillate but without any interpolation. - */ - static inline sample_t oscillateNoip( float _ph, float _wavelen, Waveforms _wave ) - { - int t = MAXLEN; - while( ( 1 << t ) > _wavelen ) { t--; } - t = qMax( 1, t ); - - const int tlen = 1 << t; - const float ph = fraction( _ph ); - const int lookup = static_cast( ph * tlen ); - return s_waveforms[ _wave ].sampleAt( t, lookup ); }; diff --git a/include/interpolation.h b/include/interpolation.h index 43c50e102..0ca1d4e06 100644 --- a/include/interpolation.h +++ b/include/interpolation.h @@ -79,13 +79,16 @@ inline float cubicInterpolate( float v0, float v1, float v2, float v3, float x ) inline float cosinusInterpolate( float v0, float v1, float x ) { - float f = cosf( x * ( F_PI_2 ) ); - return( v1 - f * (v1-v0) ); + const float f = ( 1.0f - cosf( x * F_PI ) ) * 0.5f; +#ifdef FP_FAST_FMAF + return fmaf( x, v1-v0, v0 ); +#else + return f * (v1-v0) + v0; +#endif // return( v0*f + v1*( 1.0f-f ) ); } - inline float linearInterpolate( float v0, float v1, float x ) { // take advantage of fma function if present in hardware diff --git a/include/lmms_math.h b/include/lmms_math.h index d7ca24561..36656101a 100644 --- a/include/lmms_math.h +++ b/include/lmms_math.h @@ -23,10 +23,11 @@ */ -#ifndef _LMMS_MATH_H -#define _LMMS_MATH_H +#ifndef LMMS_MATH_H +#define LMMS_MATH_H #include +#include "lmms_constants.h" #ifdef __INTEL_COMPILER @@ -123,7 +124,7 @@ static inline double fastPow( double a, double b ) // sinc function static inline double sinc( double _x ) { - return sin( F_PI * _x ) / ( F_PI * _x ); + return _x == 0.0 ? 1.0 : sin( F_PI * _x ) / ( F_PI * _x ); } diff --git a/src/core/BandLimitedWave.cpp b/src/core/BandLimitedWave.cpp index cfa0a3c7d..c820eea0e 100644 --- a/src/core/BandLimitedWave.cpp +++ b/src/core/BandLimitedWave.cpp @@ -37,7 +37,7 @@ void BandLimitedWave::generateWaves() for( i = 1; i <= MAXLEN; i++ ) { const int len = 1 << i; - const double om = 1.0 / len; + //const double om = 1.0 / len; double max = 0.0; for( int ph = 0; ph < len; ph++ ) @@ -48,11 +48,11 @@ void BandLimitedWave::generateWaves() do { hlen = static_cast( len ) / static_cast( harm ); - const double amp = -1.0 / static_cast( harm ) * ( hlen <= 4 ? 0.5 : 1.0 ) * ( hlen < 8 ? 0.75 : 1.0 ); - const double a2 = cos( om * harm * F_2PI ); - s += amp * a2 * sin( static_cast( ph * harm ) / static_cast( len ) * F_2PI ); + const double amp = -1.0 / static_cast( harm ); + //const double a2 = cos( om * harm * F_2PI ); + s += amp * /*a2 **/sin( static_cast( ph * harm ) / static_cast( len ) * F_2PI ); harm++; - } while( hlen >= 2.0 ); + } while( hlen >= 4.0 ); s_waveforms[ BandLimitedWave::BLSaw ].setSampleAt( i, ph, s ); max = qMax( max, qAbs( s ) ); } @@ -68,7 +68,7 @@ void BandLimitedWave::generateWaves() for( i = 1; i <= MAXLEN; i++ ) { const int len = 1 << i; - const double om = 1.0 / len; + //const double om = 1.0 / len; double max = 0.0; for( int ph = 0; ph < len; ph++ ) @@ -79,11 +79,11 @@ void BandLimitedWave::generateWaves() do { hlen = static_cast( len ) / static_cast( harm ); - const double amp = 1.0 / static_cast( harm ) * ( hlen <= 4 ? 0.5 : 1.0 ) * ( hlen < 8 ? 0.75 : 1.0 ); - const double a2 = cos( om * harm * F_2PI ); - s += amp * a2 * sin( static_cast( ph * harm ) / static_cast( len ) * F_2PI ); + const double amp = 1.0 / static_cast( harm ); + //const double a2 = cos( om * harm * F_2PI ); + s += amp * /*a2 **/ sin( static_cast( ph * harm ) / static_cast( len ) * F_2PI ); harm += 2; - } while( hlen >= 2.0 ); + } while( hlen >= 4.0 ); s_waveforms[ BandLimitedWave::BLSquare ].setSampleAt( i, ph, s ); max = qMax( max, qAbs( s ) ); } @@ -111,12 +111,12 @@ void BandLimitedWave::generateWaves() do { hlen = static_cast( len ) / static_cast( harm ); - const double amp = 1.0 / static_cast( harm * harm ) * ( hlen <= 4 ? 0.5 : 1.0 ) * ( hlen < 8 ? 0.75 : 1.0 ); + const double amp = 1.0 / static_cast( harm * harm ); //const double a2 = cos( om * harm * F_2PI ); s += amp * /*a2 **/ sin( ( static_cast( ph * harm ) / static_cast( len ) + ( ( harm + 1 ) % 4 == 0 ? 0.5 : 0.0 ) ) * F_2PI ); harm += 2; - } while( hlen >= 2.0 ); + } while( hlen >= 4.0 ); s_waveforms[ BandLimitedWave::BLTriangle ].setSampleAt( i, ph, s ); max = qMax( max, qAbs( s ) ); }