From b150ea2a0d8288506df7faee198ccbb5d5ed6148 Mon Sep 17 00:00:00 2001 From: Vesa Date: Sun, 13 Apr 2014 10:34:38 +0300 Subject: [PATCH 1/2] Add some fancy new interpolation algorithms --- include/interpolation.h | 46 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/include/interpolation.h b/include/interpolation.h index 0ca1d4e06..e58be7be3 100644 --- a/include/interpolation.h +++ b/include/interpolation.h @@ -101,4 +101,50 @@ inline float linearInterpolate( float v0, float v1, float x ) } +inline float optimalInterpolate( float v0, float v1, float x ) +{ + const float z = x - 0.5f; + const float even = v1 + v0; + const float odd = v1 - v0; + + const float c0 = even * 0.50037842517188658; + const float c1 = odd * 1.00621089801788210; + const float c2 = even * -0.004541102062639801; + const float c3 = odd * -1.57015627178718420; + + return ( ( c3*z + c2 ) * z + c1 ) * z + c0; +} + + +inline float optimal4pInterpolate( float v0, float v1, float v2, float v3, float x ) +{ + const float z = x - 0.5f; + const float even1 = v2 + v1; + const float odd1 = v2 - v1; + const float even2 = v3 + v0; + const float odd2 = v3 - v0; + + const float c0 = even1 * 0.45868970870461956 + even2 * 0.04131401926395584; + const float c1 = odd1 * 0.48068024766578432 + odd2 * 0.17577925564495955; + const float c2 = even1 * -0.246185007019907091 + even2 * 0.24614027139700284; + const float c3 = odd1 * -0.36030925263849456 + odd2 * 0.10174985775982505; + + return ( ( c3*z + c2 ) * z + c1 ) * z + c0; +} + + + +inline float lagrangeInterpolate( float v0, float v1, float v2, float v3, float x ) +{ + const float c0 = v1; + const float c1 = v2 - v0 * ( 1.0f / 3.0f ) - v1 * 0.5f - v3 * ( 1.0f / 6.0f ); + const float c2 = 0.5f * (v0 + v2) - v1; + const float c3 = ( 1.0f/6.0f ) * ( v3 - v0 ) + 0.5f * ( v1 - v2 ); + return ( ( c3*x + c2 ) * x + c1 ) * x + c0; +} + + + + + #endif From 26553cab17e0bfa408965f0bd9939dd805714974 Mon Sep 17 00:00:00 2001 From: Vesa Date: Sun, 13 Apr 2014 12:48:38 +0300 Subject: [PATCH 2/2] Updates to bandlimitedwave code (using new interpolation) and Monstro --- include/BandLimitedWave.h | 31 ++++++++++++++++++++++--------- plugins/monstro/Monstro.h | 2 +- src/core/BandLimitedWave.cpp | 6 +++--- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/include/BandLimitedWave.h b/include/BandLimitedWave.h index fdb33b23a..855ff4b90 100644 --- a/include/BandLimitedWave.h +++ b/include/BandLimitedWave.h @@ -114,33 +114,47 @@ public: static inline sample_t oscillate( float _ph, float _wavelen, Waveforms _wave ) { // high wavelen/ low freq - if( _wavelen > TLENS[ MAXTBL -1 ] ) + if( _wavelen > TLENS[ MAXTBL ] ) { const int t = MAXTBL; const int tlen = TLENS[t]; 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 int lm = lookup == 0 ? tlen - 1 : lookup - 1; + const sample_t s0 = s_waveforms[ _wave ].sampleAt( t, lm ); + const sample_t s3 = s_waveforms[ _wave ].sampleAt( t, ( lookup + 2 ) % tlen ); + const sample_t sr = optimal4pInterpolate( s0, s1, s2, s3, ip ); + + return sr; } // low wavelen/ high freq - if( _wavelen <= 2.0f ) + if( _wavelen < 3.0f ) { const int t = 0; const int tlen = TLENS[t]; 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 int lm = lookup == 0 ? tlen - 1 : lookup - 1; + const sample_t s0 = s_waveforms[ _wave ].sampleAt( t, lm ); + const sample_t s3 = s_waveforms[ _wave ].sampleAt( t, ( lookup + 2 ) % tlen ); + const sample_t sr = optimal4pInterpolate( s0, s1, s2, s3, ip ); + + return sr; } // get the next higher tlen - int t = 1; - while( TLENS[t] < _wavelen ) { t++; } + int t = MAXTBL - 1; + while( _wavelen < TLENS[t] ) { t--; } int tlen = TLENS[t]; const float ph = fraction( _ph ); @@ -150,12 +164,11 @@ public: const sample_t s1 = s_waveforms[ _wave ].sampleAt( t, lookup ); const sample_t s2 = s_waveforms[ _wave ].sampleAt( t, ( lookup + 1 ) % tlen ); - //const sample_t sr = linearInterpolate( s1, s2, ip ); - + const int lm = lookup == 0 ? tlen - 1 : lookup - 1; const sample_t s0 = s_waveforms[ _wave ].sampleAt( t, lm ); const sample_t s3 = s_waveforms[ _wave ].sampleAt( t, ( lookup + 2 ) % tlen ); - const sample_t sr = cubicInterpolate( s0, s1, s2, s3, ip ); + const sample_t sr = optimal4pInterpolate( s0, s1, s2, s3, ip ); return sr; diff --git a/plugins/monstro/Monstro.h b/plugins/monstro/Monstro.h index 4bf5fea0c..4e8a3ea96 100644 --- a/plugins/monstro/Monstro.h +++ b/plugins/monstro/Monstro.h @@ -172,7 +172,7 @@ const float MAX_FREQ = 48000.0f; // constants for amp delta capping - these will be divided by samplerate by the synth const float ADCAP1 = 44100 / 2; -const float ADCAP2 = 44100 / 3; +const float ADCAP2 = 44100 / 2.25; class MonstroInstrument; diff --git a/src/core/BandLimitedWave.cpp b/src/core/BandLimitedWave.cpp index 55214765f..cf2215c8e 100644 --- a/src/core/BandLimitedWave.cpp +++ b/src/core/BandLimitedWave.cpp @@ -55,7 +55,7 @@ void BandLimitedWave::generateWaves() //const double a2 = cos( om * harm * F_2PI ); s += amp * /*a2 **/sin( static_cast( ph * harm ) / static_cast( len ) * F_2PI ); harm++; - } while( hlen >= 4.0 ); + } while( hlen > 2.0 ); s_waveforms[ BandLimitedWave::BLSaw ].setSampleAt( i, ph, s ); max = qMax( max, qAbs( s ) ); } @@ -86,7 +86,7 @@ void BandLimitedWave::generateWaves() //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 >= 4.0 ); + } while( hlen > 2.0 ); s_waveforms[ BandLimitedWave::BLSquare ].setSampleAt( i, ph, s ); max = qMax( max, qAbs( s ) ); } @@ -119,7 +119,7 @@ void BandLimitedWave::generateWaves() 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 >= 4.0 ); + } while( hlen > 2.0 ); s_waveforms[ BandLimitedWave::BLTriangle ].setSampleAt( i, ph, s ); max = qMax( max, qAbs( s ) ); }