Merge pull request #564 from diizy/master

Optimize linear interpolation function
This commit is contained in:
Tobias Doerffel
2014-04-05 07:43:11 +02:00
9 changed files with 58 additions and 67 deletions

View File

@@ -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 );

View 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
}

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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 )
{

View File

@@ -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];

View File

@@ -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;

View File

@@ -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