Merge pull request #1372 from diizy/multitap

Separate BiQuad, OnePole filters as their own classes in BasicFilters.h
This commit is contained in:
Vesa V
2014-11-30 14:35:24 +02:00
3 changed files with 125 additions and 74 deletions

View File

@@ -47,8 +47,85 @@
//#include <iostream>
//#include <cstdlib>
template<ch_cnt_t CHANNELS> class BasicFilters;
template<ch_cnt_t CHANNELS>
class BiQuad
{
MM_OPERATORS
public:
BiQuad()
{
clearHistory();
}
virtual ~BiQuad() {}
inline void setCoeffs( float a1, float a2, float b0, float b1, float b2 )
{
m_a1 = a1;
m_a2 = a2;
m_b0 = b0;
m_b1 = b1;
m_b2 = b2;
}
inline void clearHistory()
{
for( int i = 0; i < CHANNELS; ++i )
{
m_z1[i] = 0.0f;
m_z2[i] = 0.0f;
}
}
inline float update( float in, ch_cnt_t ch )
{
// biquad filter in transposed form
const float out = m_z1[ch] + m_b0 * in;
m_z1[ch] = m_b1 * in + m_z2[ch] - m_a1 * out;
m_z2[ch] = m_b2 * in - m_a2 * out;
return out;
}
private:
float m_a1, m_a2, m_b0, m_b1, m_b2;
float m_z1 [CHANNELS], m_z2 [CHANNELS];
friend class BasicFilters<CHANNELS>;
};
typedef BiQuad<2> StereoBiQuad;
template<ch_cnt_t CHANNELS/* = DEFAULT_CHANNELS*/>
template<ch_cnt_t CHANNELS>
class OnePole
{
MM_OPERATORS
public:
OnePole()
{
m_a0 = 1.0;
m_b1 = 0.0;
for( int i = 0; i < CHANNELS; ++i )
{
m_z1[i] = 0.0;
}
}
virtual ~OnePole() {}
inline void setCoeffs( float a0, float b1 )
{
m_a0 = a0;
m_b1 = b1;
}
inline float update( float s, ch_cnt_t ch )
{
if( s < 1.0e-10f && m_z1[ch] < 1.0e-10f ) return 0.0f;
return m_z1[ch] = s * m_a0 + m_z1[ch] * m_b1;
}
private:
float m_a0, m_b1;
float m_z1 [CHANNELS];
};
typedef OnePole<2> StereoOnePole;
template<ch_cnt_t CHANNELS>
class BasicFilters
{
MM_OPERATORS
@@ -130,12 +207,12 @@ public:
inline void clearHistory()
{
// reset in/out history for biquads
m_biQuad.clearHistory();
// reset in/out history
for( ch_cnt_t _chnl = 0; _chnl < CHANNELS; ++_chnl )
{
// reset in/out history for simple filters
m_z1[_chnl] = m_z2[_chnl] = 0.0f;
// reset in/out history for moog-filter
m_y1[_chnl] = m_y2[_chnl] = m_y3[_chnl] = m_y4[_chnl] =
m_oldx[_chnl] = m_oldy1[_chnl] =
@@ -534,10 +611,7 @@ public:
}
default:
// biquad filter in transposed form
out = m_z1[_chnl] + m_b0a0 * _in0;
m_z1[_chnl] = m_b1a0 * _in0 + m_z2[_chnl] - m_a1a0 * out;
m_z2[_chnl] = m_b2a0 * _in0 - m_a2a0 * out;
out = m_biQuad.update( _in0, _chnl );
break;
}
@@ -665,59 +739,61 @@ public:
const float a0 = 1.0f / ( 1.0f + alpha );
m_a1a0 = -2.0f * tcos * a0;
m_a2a0 = ( 1.0f - alpha ) * a0;
const float a1 = -2.0f * tcos * a0;
const float a2 = ( 1.0f - alpha ) * a0;
switch( m_type )
{
case LowPass:
m_b1a0 = ( 1.0f - tcos ) * a0;
m_b0a0 = m_b1a0 * 0.5f;
m_b2a0 = m_b0a0;//((1.0f-tcos)/2.0f)*a0;
{
const float b1 = ( 1.0f - tcos ) * a0;
const float b0 = b1 * 0.5f;
m_biQuad.setCoeffs( a1, a2, b0, b1, b0 );
break;
}
case HiPass:
m_b1a0 = ( -1.0f - tcos ) * a0;
m_b0a0 = m_b1a0 * -0.5f;
m_b2a0 = m_b0a0;//((1.0f+tcos)/2.0f)*a0;
{
const float b1 = ( -1.0f - tcos ) * a0;
const float b0 = b1 * -0.5f;
m_biQuad.setCoeffs( a1, a2, b0, b1, b0 );
break;
}
case BandPass_CSG:
m_b1a0 = 0.0f;
m_b0a0 = tsin * a0;
m_b2a0 = -m_b0a0;
{
const float b0 = tsin * a0;
m_biQuad.setCoeffs( a1, a2, b0, 0.0f, -b0 );
break;
}
case BandPass_CZPG:
m_b1a0 = 0.0f;
m_b0a0 = alpha * a0;
m_b2a0 = -m_b0a0;
{
const float b0 = alpha * a0;
m_biQuad.setCoeffs( a1, a2, b0, 0.0f, -b0 );
break;
}
case Notch:
m_b1a0 = m_a1a0;
m_b0a0 = a0;
m_b2a0 = a0;
{
m_biQuad.setCoeffs( a1, a2, a0, a1, a0 );
break;
}
case AllPass:
m_b1a0 = m_a1a0;
m_b0a0 = m_a2a0;
m_b2a0 = 1.0f;//(1.0f+alpha)*a0;
{
m_biQuad.setCoeffs( a1, a2, a2, a1, 1.0f );
break;
}
default:
break;
}
if( m_doubleFilter )
{
m_subFilter->m_b0a0 = m_b0a0;
m_subFilter->m_b1a0 = m_b1a0;
m_subFilter->m_b2a0 = m_b2a0;
m_subFilter->m_a1a0 = m_a1a0;
m_subFilter->m_a2a0 = m_a2a0;
m_subFilter->m_biQuad.setCoeffs( m_biQuad.m_a1, m_biQuad.m_a2, m_biQuad.m_b0, m_biQuad.m_b1, m_biQuad.m_b2 );
}
}
private:
// filter coeffs
float m_b0a0, m_b1a0, m_b2a0, m_a1a0, m_a2a0;
// biquad filter
BiQuad<CHANNELS> m_biQuad;
// coeffs for moog-filter
float m_r, m_p, m_k;
@@ -733,9 +809,6 @@ private:
typedef sample_t frame[CHANNELS];
// in/out history
frame m_z1, m_z2;
// in/out history for moog-filter
frame m_y1, m_y2, m_y3, m_y4, m_oldx, m_oldy1, m_oldy2, m_oldy3;
// additional one for Tripole filter

View File

@@ -53,7 +53,7 @@ MultitapEchoEffect::MultitapEchoEffect( Model* parent, const Descriptor::SubPlug
m_sampleRate( Engine::mixer()->processingSampleRate() ),
m_sampleRatio( 1.0f / m_sampleRate )
{
m_work = new sampleFrame[ Engine::mixer()->framesPerPeriod() ];
m_work = MM_ALLOC( sampleFrame, Engine::mixer()->framesPerPeriod() );
m_buffer.reset();
updateFilters( 0, 19 );
}
@@ -61,16 +61,15 @@ MultitapEchoEffect::MultitapEchoEffect( Model* parent, const Descriptor::SubPlug
MultitapEchoEffect::~MultitapEchoEffect()
{
delete m_work;
MM_FREE( m_work );
}
void MultitapEchoEffect::updateFilters( int begin, int end )
{
for( int i = begin; i <= end; ++i )
{
m_filter[i][0].setFc( m_lpFreq[i] * m_sampleRatio );
m_filter[i][1].setFc( m_lpFreq[i] * m_sampleRatio );
{
setFilterFreq( m_lpFreq[i] * m_sampleRatio, m_filter[i] );
}
}
@@ -79,8 +78,8 @@ void MultitapEchoEffect::runFilter( sampleFrame * dst, sampleFrame * src, Stereo
{
for( int f = 0; f < frames; ++f )
{
dst[f][0] = filter[0].update( src[f][0] );
dst[f][1] = filter[1].update( src[f][1] );
dst[f][0] = filter.update( src[f][0], 0 );
dst[f][1] = filter.update( src[f][1], 1 );
}
}
@@ -119,7 +118,7 @@ bool MultitapEchoEffect::processAudioBuffer( sampleFrame * buf, const fpp_t fram
else
{
float offset = stepLength;
for( int i = 0; i < steps; ++i ) // add all steps swapped
for( int i = 0; i < steps; ++i ) // add all steps
{
runFilter( m_work, buf, m_filter[i], frames );
m_buffer.writeAddingMultiplied( m_work, offset, frames, m_amp[i] );

View File

@@ -31,34 +31,7 @@
#include "ValueBuffer.h"
#include "RingBuffer.h"
#include "lmms_math.h"
class OnePole
{
public:
OnePole()
{
m_a0 = 1.0;
m_b1 = 0.0;
m_z1 = 0.0;
}
virtual ~OnePole() {}
inline void setFc( float fc )
{
m_b1 = expf( -2.0f * F_PI * fc );
m_a0 = 1.0f - m_b1;
}
inline float update( float s )
{
return m_z1 = s * m_a0 + m_z1 * m_b1;
}
private:
float m_a0, m_b1, m_z1;
};
typedef OnePole StereoOnePole [2];
#include "BasicFilters.h"
class MultitapEchoEffect : public Effect
{
@@ -76,6 +49,12 @@ private:
void updateFilters( int begin, int end );
void runFilter( sampleFrame * dst, sampleFrame * src, StereoOnePole & filter, const fpp_t frames );
inline void setFilterFreq( float fc, StereoOnePole & f )
{
const float b1 = expf( -2.0f * F_PI * fc );
f.setCoeffs( 1.0f - b1, b1 );
}
MultitapEchoControls m_controls;
float m_amp [20];