diff --git a/include/BasicFilters.h b/include/BasicFilters.h index 8842b0dc9..ba04b609c 100644 --- a/include/BasicFilters.h +++ b/include/BasicFilters.h @@ -47,8 +47,85 @@ //#include //#include +template class BasicFilters; +template +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; +}; +typedef BiQuad<2> StereoBiQuad; -template +template +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 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 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 diff --git a/plugins/MultitapEcho/MultitapEcho.cpp b/plugins/MultitapEcho/MultitapEcho.cpp index 8c060b2ea..e3da02075 100644 --- a/plugins/MultitapEcho/MultitapEcho.cpp +++ b/plugins/MultitapEcho/MultitapEcho.cpp @@ -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] ); diff --git a/plugins/MultitapEcho/MultitapEcho.h b/plugins/MultitapEcho/MultitapEcho.h index 50ac5a55f..d1c4cdfaa 100644 --- a/plugins/MultitapEcho/MultitapEcho.h +++ b/plugins/MultitapEcho/MultitapEcho.h @@ -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];