Merge pull request #564 from diizy/master
Optimize linear interpolation function
This commit is contained in:
@@ -232,23 +232,13 @@ public:
|
||||
|
||||
inline sample_t userWaveSample( const float _sample ) const
|
||||
{
|
||||
// Precise implementation
|
||||
// const float frame = fraction( _sample ) * m_frames;
|
||||
// const f_cnt_t f1 = static_cast<f_cnt_t>( frame );
|
||||
// const f_cnt_t f2 = ( f1 + 1 ) % m_frames;
|
||||
// sample_t waveSample = linearInterpolate( m_data[f1][0],
|
||||
// m_data[f2][0],
|
||||
// fraction( frame ) );
|
||||
// return waveSample;
|
||||
|
||||
// Fast implementation
|
||||
const float frame = _sample * m_frames;
|
||||
f_cnt_t f1 = static_cast<f_cnt_t>( frame ) % m_frames;
|
||||
if( f1 < 0 )
|
||||
{
|
||||
f1 += m_frames;
|
||||
}
|
||||
return m_data[f1][0];
|
||||
return linearInterpolate( m_data[f1][0], m_data[ (f1 + 1) % m_frames ][0], fraction( frame ) );
|
||||
}
|
||||
|
||||
static QString tryToMakeRelative( const QString & _file );
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _INTERPOLATION_H
|
||||
#define _INTERPOLATION_H
|
||||
#ifndef INTERPOLATION_H
|
||||
#define INTERPOLATION_H
|
||||
|
||||
#ifndef __USE_XOPEN
|
||||
#define __USE_XOPEN
|
||||
@@ -80,14 +80,21 @@ 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( v0*f + v1*( 1.0f-f ) );
|
||||
return( v1 - f * (v1-v0) );
|
||||
// return( v0*f + v1*( 1.0f-f ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline float linearInterpolate( float v0, float v1, float x )
|
||||
{
|
||||
return( v0*( 1.0f-x ) + v1*x );
|
||||
// take advantage of fma function if present in hardware
|
||||
|
||||
#ifdef FP_FAST_FMAF
|
||||
return fmaf( x, v1-v0, v0 );
|
||||
#else
|
||||
return x * (v1-v0) + v0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "templates.h"
|
||||
#include "tooltip.h"
|
||||
#include "song.h"
|
||||
#include "interpolation.h"
|
||||
|
||||
#include "embed.cpp"
|
||||
|
||||
@@ -108,9 +109,9 @@ sample_t bSynth::nextStringSample()
|
||||
}
|
||||
|
||||
// Nachkommaanteil
|
||||
float frac = sample_realindex - static_cast<int>(sample_realindex);
|
||||
const float frac = fraction( sample_realindex );
|
||||
|
||||
sample = sample_shape[a]*(1-frac) + sample_shape[b]*(frac);
|
||||
sample = linearInterpolate( sample_shape[a], sample_shape[b], frac );
|
||||
|
||||
} else {
|
||||
// No interpolation
|
||||
|
||||
@@ -25,7 +25,9 @@
|
||||
|
||||
|
||||
#include "dynamics_processor.h"
|
||||
#include <math.h>
|
||||
#include "lmms_math.h"
|
||||
#include "interpolation.h"
|
||||
|
||||
#include "embed.cpp"
|
||||
|
||||
#ifdef LMMS_BUILD_WIN32
|
||||
@@ -107,8 +109,7 @@ bool dynProcEffect::processAudioBuffer( sampleFrame * _buf,
|
||||
|
||||
// variables for effect
|
||||
int i = 0;
|
||||
float lookup;
|
||||
float frac;
|
||||
|
||||
float sm_peak[2] = { 0.0f, 0.0f };
|
||||
float gain;
|
||||
|
||||
@@ -182,22 +183,20 @@ bool dynProcEffect::processAudioBuffer( sampleFrame * _buf,
|
||||
|
||||
for ( i=0; i <= 1; i++ )
|
||||
{
|
||||
if( sm_peak[i] != 0 )
|
||||
const int lookup = static_cast<int>( sm_peak[i] * 200.0f );
|
||||
const float frac = fraction( sm_peak[i] * 200.0f );
|
||||
|
||||
if( sm_peak[i] > 0 )
|
||||
{
|
||||
lookup = sm_peak[i] * 200.0f;
|
||||
|
||||
if ( lookup < 1 )
|
||||
{
|
||||
frac = lookup - truncf(lookup);
|
||||
gain = frac * m_dpControls.m_wavegraphModel.samples()[0];
|
||||
}
|
||||
else
|
||||
if ( lookup < 200 )
|
||||
{
|
||||
frac = lookup - truncf(lookup);
|
||||
gain =
|
||||
(( (1.0f-frac) * m_dpControls.m_wavegraphModel.samples()[ (int)truncf(lookup) - 1 ] ) +
|
||||
( frac * m_dpControls.m_wavegraphModel.samples()[ (int)truncf(lookup) ] ));
|
||||
gain = linearInterpolate( m_dpControls.m_wavegraphModel.samples()[ lookup - 1 ],
|
||||
m_dpControls.m_wavegraphModel.samples()[ lookup ], frac );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -206,8 +205,6 @@ bool dynProcEffect::processAudioBuffer( sampleFrame * _buf,
|
||||
|
||||
s[i] *= ( gain / sm_peak[i] );
|
||||
}
|
||||
else { s[i] = 0.0f; }
|
||||
|
||||
}
|
||||
|
||||
// apply output gain
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "tooltip.h"
|
||||
#include "song.h"
|
||||
#include "lmms_math.h"
|
||||
#include "interpolation.h"
|
||||
|
||||
#include "embed.cpp"
|
||||
|
||||
@@ -103,10 +104,10 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf )
|
||||
{
|
||||
// macros for modulating with env/lfos
|
||||
#define modulatefreq( car, mod ) \
|
||||
if( mod##_e1 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast<float>( fastPow( 2.0, m_env1_buf[f] * mod##_e1 * 2 ) ), MAX_FREQ ); \
|
||||
if( mod##_e2 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast<float>( fastPow( 2.0, m_env2_buf[f] * mod##_e2 * 2 ) ), MAX_FREQ ); \
|
||||
if( mod##_l1 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast<float>( fastPow( 2.0, m_lfo1_buf[f] * mod##_l1 ) ), MAX_FREQ ); \
|
||||
if( mod##_l2 != 0.0 ) car = qBound( MIN_FREQ, car * static_cast<float>( fastPow( 2.0, m_lfo2_buf[f] * mod##_l2 ) ), MAX_FREQ );
|
||||
if( mod##_e1 != 0.0 ) car = qBound( MIN_FREQ, car * powf( 2.0, m_env1_buf[f] * mod##_e1 * 2 ), MAX_FREQ ); \
|
||||
if( mod##_e2 != 0.0 ) car = qBound( MIN_FREQ, car * powf( 2.0, m_env2_buf[f] * mod##_e2 * 2 ), MAX_FREQ ); \
|
||||
if( mod##_l1 != 0.0 ) car = qBound( MIN_FREQ, car * powf( 2.0, m_lfo1_buf[f] * mod##_l1 ), MAX_FREQ ); \
|
||||
if( mod##_l2 != 0.0 ) car = qBound( MIN_FREQ, car * powf( 2.0, m_lfo2_buf[f] * mod##_l2 ), MAX_FREQ );
|
||||
|
||||
#define modulateabs( car, mod ) \
|
||||
if( mod##_e1 != 0.0 ) car = qBound( 0.0f, car + mod##_e1 * m_env1_buf[f], 1.0f ); \
|
||||
@@ -251,14 +252,14 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf )
|
||||
for( f_cnt_t f = 0; f < _frames; f++ )
|
||||
{
|
||||
|
||||
/*
|
||||
// debug code
|
||||
|
||||
/* // debug code
|
||||
if( f % 10 == 0 ) {
|
||||
qDebug( "env1 %f -- env1 phase %f", m_env1_buf[f], m_env1_phase );
|
||||
qDebug( "env1 pre %f att %f dec %f rel %f ", m_parent->m_env1_pre, m_parent->m_env1_att,
|
||||
m_parent->m_env1_dec, m_parent->m_env1_rel );
|
||||
}
|
||||
*/
|
||||
}*/
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// //
|
||||
@@ -378,8 +379,8 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf )
|
||||
// o2 modulation?
|
||||
if( omod == MOD_FM )
|
||||
{
|
||||
o3l_f = qBound( MIN_FREQ, o3l_f * powf( 4.0f, O2L ), MAX_FREQ );
|
||||
o3r_f = qBound( MIN_FREQ, o3r_f * powf( 4.0f, O2R ), MAX_FREQ );
|
||||
o3l_f = qBound( MIN_FREQ, o3l_f * powf( 2.0f, O2L * 2 ), MAX_FREQ );
|
||||
o3r_f = qBound( MIN_FREQ, o3r_f * powf( 2.0f, O2R * 2 ), MAX_FREQ );
|
||||
}
|
||||
|
||||
// check for sync
|
||||
@@ -417,8 +418,8 @@ void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf )
|
||||
float sub = o3sub;
|
||||
modulateabs( sub, o3s )
|
||||
|
||||
sample_t O3L = interpolate( O3AL, O3BL, sub );
|
||||
sample_t O3R = interpolate( O3AR, O3BR, sub );
|
||||
sample_t O3L = linearInterpolate( O3AL, O3BL, sub );
|
||||
sample_t O3R = linearInterpolate( O3AR, O3BR, sub );
|
||||
|
||||
// modulate volume
|
||||
O3L *= o3lv;
|
||||
|
||||
@@ -183,11 +183,10 @@ private:
|
||||
void renderModulators( fpp_t _frames );
|
||||
|
||||
// linear interpolation
|
||||
inline sample_t interpolate( sample_t s1, sample_t s2, float x )
|
||||
/* inline sample_t interpolate( sample_t s1, sample_t s2, float x )
|
||||
{
|
||||
return s1 + ( s2 - s1 ) * x;
|
||||
}
|
||||
|
||||
}*/ // using interpolation.h from now on
|
||||
|
||||
inline sample_t calcSlope( sample_t _s, float _slope )
|
||||
{
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "tooltip.h"
|
||||
#include "song.h"
|
||||
#include "lmms_math.h"
|
||||
#include "interpolation.h"
|
||||
|
||||
#include "embed.cpp"
|
||||
|
||||
@@ -132,10 +133,10 @@ void WatsynObject::renderOutput( fpp_t _frames )
|
||||
if( A1_rphase < 0 ) A1_rphase += WAVELEN;
|
||||
}
|
||||
// A1
|
||||
sample_t A1_L = interpolate( m_A1wave[ static_cast<int>( A1_lphase ) ],
|
||||
sample_t A1_L = linearInterpolate( m_A1wave[ static_cast<int>( A1_lphase ) ],
|
||||
m_A1wave[ static_cast<int>( A1_lphase + 1 ) % WAVELEN ],
|
||||
fraction( A1_lphase ) ) * m_parent->m_lvol[A1_OSC];
|
||||
sample_t A1_R = interpolate( m_A1wave[ static_cast<int>( A1_rphase ) ],
|
||||
sample_t A1_R = linearInterpolate( m_A1wave[ static_cast<int>( A1_rphase ) ],
|
||||
m_A1wave[ static_cast<int>( A1_rphase + 1 ) % WAVELEN ],
|
||||
fraction( A1_rphase ) ) * m_parent->m_rvol[A1_OSC];
|
||||
|
||||
@@ -168,10 +169,10 @@ void WatsynObject::renderOutput( fpp_t _frames )
|
||||
if( B1_rphase < 0 ) B1_rphase += WAVELEN;
|
||||
}
|
||||
// B1
|
||||
sample_t B1_L = interpolate( m_B1wave[ static_cast<int>( B1_lphase ) % WAVELEN ],
|
||||
sample_t B1_L = linearInterpolate( m_B1wave[ static_cast<int>( B1_lphase ) % WAVELEN ],
|
||||
m_B1wave[ static_cast<int>( B1_lphase + 1 ) % WAVELEN ],
|
||||
fraction( B1_lphase ) ) * m_parent->m_lvol[B1_OSC];
|
||||
sample_t B1_R = interpolate( m_B1wave[ static_cast<int>( B1_rphase ) % WAVELEN ],
|
||||
sample_t B1_R = linearInterpolate( m_B1wave[ static_cast<int>( B1_rphase ) % WAVELEN ],
|
||||
m_B1wave[ static_cast<int>( B1_rphase + 1 ) % WAVELEN ],
|
||||
fraction( B1_rphase ) ) * m_parent->m_rvol[B1_OSC];
|
||||
|
||||
|
||||
@@ -103,10 +103,10 @@ public:
|
||||
|
||||
private:
|
||||
// linear interpolation
|
||||
inline sample_t interpolate( sample_t s1, sample_t s2, float x )
|
||||
/* inline sample_t interpolate( sample_t s1, sample_t s2, float x )
|
||||
{
|
||||
return s1 + ( s2 - s1 ) * x;
|
||||
}
|
||||
}*/ // we use the one in interpolation.h now
|
||||
|
||||
int m_amod;
|
||||
int m_bmod;
|
||||
|
||||
@@ -25,8 +25,9 @@
|
||||
|
||||
|
||||
#include "waveshaper.h"
|
||||
#include <math.h>
|
||||
#include "lmms_math.h"
|
||||
#include "embed.cpp"
|
||||
#include "interpolation.h"
|
||||
|
||||
|
||||
extern "C"
|
||||
@@ -77,9 +78,6 @@ bool waveShaperEffect::processAudioBuffer( sampleFrame * _buf,
|
||||
|
||||
// variables for effect
|
||||
int i = 0;
|
||||
float lookup;
|
||||
float frac;
|
||||
float posneg;
|
||||
|
||||
double out_sum = 0.0;
|
||||
const float d = dryLevel();
|
||||
@@ -101,23 +99,20 @@ bool waveShaperEffect::processAudioBuffer( sampleFrame * _buf,
|
||||
|
||||
// start effect
|
||||
|
||||
for ( i=0; i <= 1; ++i )
|
||||
for( i=0; i <= 1; ++i )
|
||||
{
|
||||
lookup = fabsf( s[i] ) * 200.0f;
|
||||
posneg = s[i] < 0 ? -1.0f : 1.0f;
|
||||
const int lookup = static_cast<int>( fabsf( s[i] ) * 200.0f );
|
||||
const float frac = fraction( fabsf( s[i] ) * 200.0f );
|
||||
const float posneg = s[i] < 0 ? -1.0f : 1.0f;
|
||||
|
||||
if ( lookup < 1 )
|
||||
if( lookup < 1 )
|
||||
{
|
||||
frac = lookup - truncf(lookup);
|
||||
s[i] = frac * m_wsControls.m_wavegraphModel.samples()[0] * posneg;
|
||||
}
|
||||
else
|
||||
if ( lookup < 200 )
|
||||
{
|
||||
frac = lookup - truncf(lookup);
|
||||
s[i] =
|
||||
(( (1.0f-frac) * m_wsControls.m_wavegraphModel.samples()[ (int)truncf(lookup) - 1 ] ) +
|
||||
( frac * m_wsControls.m_wavegraphModel.samples()[ (int)truncf(lookup) ] ))
|
||||
else if( lookup < 200 )
|
||||
{
|
||||
s[i] = linearInterpolate( m_wsControls.m_wavegraphModel.samples()[ lookup - 1 ],
|
||||
m_wsControls.m_wavegraphModel.samples()[ lookup ], frac )
|
||||
* posneg;
|
||||
}
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user