From d166212d49832a6be2463173bf6679b7efcb39e7 Mon Sep 17 00:00:00 2001 From: Vesa Date: Wed, 25 Jun 2014 20:43:34 +0300 Subject: [PATCH 1/4] basic_filters: optimize RC highpass & bandpass filters For both RC12 and RC24 filter types: handle lowpass separately, because we can then calculate highpass & bandpass with less operations. This shouldn't affect the performance of lowpass, but probably will make highpass and bandpass a bit faster. --- include/basic_filters.h | 397 ++++++++++++++++++++-------------------- 1 file changed, 201 insertions(+), 196 deletions(-) diff --git a/include/basic_filters.h b/include/basic_filters.h index e41046e61..923716a35 100644 --- a/include/basic_filters.h +++ b/include/basic_filters.h @@ -1,11 +1,11 @@ /* * basic_filters.h - simple but powerful filter-class with most used filters * - * original file by ??? + * original file by ??? * modified and enhanced by Tobias Doerffel * * Copyright (c) 2004-2009 Tobias Doerffel - * + * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * * This program is free software; you can redistribute it and/or @@ -127,16 +127,16 @@ public: // reset in/out history for simple filters m_ou1[_chnl] = m_ou2[_chnl] = m_in1[_chnl] = m_in2[_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] = m_oldy2[_chnl] = m_oldy3[_chnl] = 0.0f; - + // reset in/out history for RC-filters m_rclp0[_chnl] = m_rcbp0[_chnl] = m_rchp0[_chnl] = m_rclast0[_chnl] = 0.0f; m_rclp1[_chnl] = m_rcbp1[_chnl] = m_rchp1[_chnl] = m_rclast1[_chnl] = 0.0f; - + for(int i=0; i<6; i++) m_vflp[i][_chnl] = m_vfbp[i][_chnl] = m_vfhp[i][_chnl] = m_vflast[i][_chnl] = 0.0f; } @@ -186,130 +186,135 @@ public: // (C) 1998 ... 2009 S.Fendt. Released under the GPL v2.0 or any later version. case Lowpass_RC12: - case Bandpass_RC12: - case Highpass_RC12: { - sample_t lp, hp, bp; - - sample_t in; - - // 4-times oversampled... (even the moog-filter would benefit from this) + sample_t lp, bp, hp, in; for( int n = 4; n != 0; --n ) { in = _in0 + m_rcbp0[_chnl] * m_rcq; - in = (in > +1.f) ? +1.f : in; - in = (in < -1.f) ? -1.f : in; + in = qBound( -1.0f, in, 1.0f ); lp = in * m_rcb + m_rclp0[_chnl] * m_rca; - lp = (lp > +1.f) ? +1.f : lp; - lp = (lp < -1.f) ? -1.f : lp; + lp = qBound( -1.0f, lp, 1.0f ); hp = m_rcc * ( m_rchp0[_chnl] + in - m_rclast0[_chnl] ); - hp = (hp > +1.f) ? +1.f : hp; - hp = (hp < -1.f) ? -1.f : hp; + hp = qBound( -1.0f, hp, 1.0f ); bp = hp * m_rcb + m_rcbp0[_chnl] * m_rca; - bp = (bp > +1.f) ? +1.f : bp; - bp = (bp < -1.f) ? -1.f : bp; + bp = qBound( -1.0f, bp, 1.0f ); m_rclast0[_chnl] = in; m_rclp0[_chnl] = lp; m_rchp0[_chnl] = hp; m_rcbp0[_chnl] = bp; } + return lp; + break; + } + case Highpass_RC12: + case Bandpass_RC12: + { + sample_t hp, bp, in; + for( int n = 4; n != 0; --n ) + { + in = _in0 + m_rcbp0[_chnl] * m_rcq; + in = qBound( -1.0f, in, 1.0f ); - if( m_type == Lowpass_RC12 ) - out = lp; - else if( m_type == Bandpass_RC12 ) - out = bp; - else - out = hp; - - return( out ); + hp = m_rcc * ( m_rchp0[_chnl] + in - m_rclast0[_chnl] ); + hp = qBound( -1.0f, hp, 1.0f ); + + bp = hp * m_rcb + m_rcbp0[_chnl] * m_rca; + bp = qBound( -1.0f, bp, 1.0f ); + + m_rclast0[_chnl] = in; + m_rchp0[_chnl] = hp; + m_rcbp0[_chnl] = bp; + } + return m_type == Highpass_RC12 ? hp : bp; break; } case Lowpass_RC24: - case Bandpass_RC24: - case Highpass_RC24: { - sample_t lp, hp, bp; - - sample_t in; - + sample_t lp, bp, hp, in; for( int n = 4; n != 0; --n ) { // first stage is as for the 12dB case... in = _in0 + m_rcbp0[_chnl] * m_rcq; - in = (in > +1.f) ? +1.f : in; - in = (in < -1.f) ? -1.f : in; + in = qBound( -1.0f, in, 1.0f ); lp = in * m_rcb + m_rclp0[_chnl] * m_rca; - lp = (lp > +1.f) ? +1.f : lp; - lp = (lp < -1.f) ? -1.f : lp; + lp = qBound( -1.0f, lp, 1.0f ); hp = m_rcc * ( m_rchp0[_chnl] + in - m_rclast0[_chnl] ); - hp = (hp > +1.f) ? +1.f : hp; - hp = (hp < -1.f) ? -1.f : hp; + hp = qBound( -1.0f, hp, 1.0f ); bp = hp * m_rcb + m_rcbp0[_chnl] * m_rca; - bp = (bp > +1.f) ? +1.f : bp; - bp = (bp < -1.f) ? -1.f : bp; + bp = qBound( -1.0f, bp, 1.0f ); m_rclast0[_chnl] = in; m_rclp0[_chnl] = lp; + m_rcbp0[_chnl] = bp; + m_rchp0[_chnl] = hp; + + // second stage gets the output of the first stage as input... + in = lp + m_rcbp1[_chnl] * m_rcq; + in = qBound( -1.0f, in, 1.0f ); + + lp = in * m_rcb + m_rclp1[_chnl] * m_rca; + lp = qBound( -1.0f, lp, 1.0f ); + + hp = m_rcc * ( m_rchp1[_chnl] + in - m_rclast1[_chnl] ); + hp = qBound( -1.0f, hp, 1.0f ); + + bp = hp * m_rcb + m_rcbp1[_chnl] * m_rca; + bp = qBound( -1.0f, bp, 1.0f ); + + m_rclast1[_chnl] = in; + m_rclp1[_chnl] = lp; + m_rcbp1[_chnl] = bp; + m_rchp1[_chnl] = hp; + } + return lp; + break; + } + case Highpass_RC24: + case Bandpass_RC24: + { + sample_t hp, bp, in; + for( int n = 4; n != 0; --n ) + { + // first stage is as for the 12dB case... + in = _in0 + m_rcbp0[_chnl] * m_rcq; + in = qBound( -1.0f, in, 1.0f ); + + hp = m_rcc * ( m_rchp0[_chnl] + in - m_rclast0[_chnl] ); + hp = qBound( -1.0f, hp, 1.0f ); + + bp = hp * m_rcb + m_rcbp0[_chnl] * m_rca; + bp = qBound( -1.0f, bp, 1.0f ); + + m_rclast0[_chnl] = in; m_rchp0[_chnl] = hp; m_rcbp0[_chnl] = bp; // second stage gets the output of the first stage as input... - if( m_type == Lowpass_RC24 ) - { - in = lp + m_rcbp1[_chnl] * m_rcq; - } - else if( m_type == Bandpass_RC24 ) - { - in = bp + m_rcbp1[_chnl] * m_rcq; - } - else - { - in = hp + m_rcbp1[_chnl] * m_rcq; - } - in = (in > +1.f) ? +1.f : in; - in = (in < -1.f) ? -1.f : in; + in = m_type == Highpass_RC24 + ? hp + m_rcbp1[_chnl] * m_rcq + : bp + m_rcbp1[_chnl] * m_rcq; - lp = in * m_rcb + m_rclp1[_chnl] * m_rca; - lp = (lp > +1.f) ? +1.f : lp; - lp = (lp < -1.f) ? -1.f : lp; + in = qBound( -1.0f, in, 1.0f ); hp = m_rcc * ( m_rchp1[_chnl] + in - m_rclast1[_chnl] ); - hp = (hp > +1.f) ? +1.f : hp; - hp = (hp < -1.f) ? -1.f : hp; + hp = qBound( -1.0f, hp, 1.0f ); bp = hp * m_rcb + m_rcbp1[_chnl] * m_rca; - bp = (bp > +1.f) ? +1.f : bp; - bp = (bp < -1.f) ? -1.f : bp; + bp = qBound( -1.0f, bp, 1.0f ); m_rclast1[_chnl] = in; - m_rclp1[_chnl] = lp; m_rchp1[_chnl] = hp; m_rcbp1[_chnl] = bp; } - - // output is second stage-lowpass... - if( m_type == Lowpass_RC24 ) - { - out = lp; - } - else if( m_type == Bandpass_RC24 ) - { - out = bp; - } - else - { - out = hp; - } - - return out; + return m_type == Highpass_RC24 ? hp : bp; break; } @@ -317,146 +322,146 @@ public: { sample_t lp, hp, bp, in; - out = 0; - for(int o=0; o<4; o++) - { - // first formant - in = _in0 + m_vfbp[0][_chnl] * m_vfq; - in = (in > +1.f) ? +1.f : in; - in = (in < -1.f) ? -1.f : in; + out = 0; + for(int o=0; o<4; o++) + { + // first formant + in = _in0 + m_vfbp[0][_chnl] * m_vfq; + in = (in > +1.f) ? +1.f : in; + in = (in < -1.f) ? -1.f : in; - lp = in * m_vfb[0] + m_vflp[0][_chnl] * m_vfa[0]; - lp = (lp > +1.f) ? +1.f : lp; - lp = (lp < -1.f) ? -1.f : lp; + lp = in * m_vfb[0] + m_vflp[0][_chnl] * m_vfa[0]; + lp = (lp > +1.f) ? +1.f : lp; + lp = (lp < -1.f) ? -1.f : lp; - hp = m_vfc[0] * ( m_vfhp[0][_chnl] + in - m_vflast[0][_chnl] ); - hp = (hp > +1.f) ? +1.f : hp; - hp = (hp < -1.f) ? -1.f : hp; + hp = m_vfc[0] * ( m_vfhp[0][_chnl] + in - m_vflast[0][_chnl] ); + hp = (hp > +1.f) ? +1.f : hp; + hp = (hp < -1.f) ? -1.f : hp; - bp = hp * m_vfb[0] + m_vfbp[0][_chnl] * m_vfa[0]; - bp = (bp > +1.f) ? +1.f : bp; - bp = (bp < -1.f) ? -1.f : bp; + bp = hp * m_vfb[0] + m_vfbp[0][_chnl] * m_vfa[0]; + bp = (bp > +1.f) ? +1.f : bp; + bp = (bp < -1.f) ? -1.f : bp; - m_vflast[0][_chnl] = in; - m_vflp[0][_chnl] = lp; - m_vfhp[0][_chnl] = hp; - m_vfbp[0][_chnl] = bp; + m_vflast[0][_chnl] = in; + m_vflp[0][_chnl] = lp; + m_vfhp[0][_chnl] = hp; + m_vfbp[0][_chnl] = bp; - in = bp + m_vfbp[2][_chnl] * m_vfq; - in = (in > +1.f) ? +1.f : in; - in = (in < -1.f) ? -1.f : in; + in = bp + m_vfbp[2][_chnl] * m_vfq; + in = (in > +1.f) ? +1.f : in; + in = (in < -1.f) ? -1.f : in; - lp = in * m_vfb[0] + m_vflp[2][_chnl] * m_vfa[0]; - lp = (lp > +1.f) ? +1.f : lp; - lp = (lp < -1.f) ? -1.f : lp; + lp = in * m_vfb[0] + m_vflp[2][_chnl] * m_vfa[0]; + lp = (lp > +1.f) ? +1.f : lp; + lp = (lp < -1.f) ? -1.f : lp; - hp = m_vfc[0] * ( m_vfhp[2][_chnl] + in - m_vflast[2][_chnl] ); - hp = (hp > +1.f) ? +1.f : hp; - hp = (hp < -1.f) ? -1.f : hp; + hp = m_vfc[0] * ( m_vfhp[2][_chnl] + in - m_vflast[2][_chnl] ); + hp = (hp > +1.f) ? +1.f : hp; + hp = (hp < -1.f) ? -1.f : hp; - bp = hp * m_vfb[0] + m_vfbp[2][_chnl] * m_vfa[0]; - bp = (bp > +1.f) ? +1.f : bp; - bp = (bp < -1.f) ? -1.f : bp; + bp = hp * m_vfb[0] + m_vfbp[2][_chnl] * m_vfa[0]; + bp = (bp > +1.f) ? +1.f : bp; + bp = (bp < -1.f) ? -1.f : bp; - m_vflast[2][_chnl] = in; - m_vflp[2][_chnl] = lp; - m_vfhp[2][_chnl] = hp; - m_vfbp[2][_chnl] = bp; - - in = bp + m_vfbp[4][_chnl] * m_vfq; - in = (in > +1.f) ? +1.f : in; - in = (in < -1.f) ? -1.f : in; + m_vflast[2][_chnl] = in; + m_vflp[2][_chnl] = lp; + m_vfhp[2][_chnl] = hp; + m_vfbp[2][_chnl] = bp; - lp = in * m_vfb[0] + m_vflp[4][_chnl] * m_vfa[0]; - lp = (lp > +1.f) ? +1.f : lp; - lp = (lp < -1.f) ? -1.f : lp; + in = bp + m_vfbp[4][_chnl] * m_vfq; + in = (in > +1.f) ? +1.f : in; + in = (in < -1.f) ? -1.f : in; - hp = m_vfc[0] * ( m_vfhp[4][_chnl] + in - m_vflast[4][_chnl] ); - hp = (hp > +1.f) ? +1.f : hp; - hp = (hp < -1.f) ? -1.f : hp; + lp = in * m_vfb[0] + m_vflp[4][_chnl] * m_vfa[0]; + lp = (lp > +1.f) ? +1.f : lp; + lp = (lp < -1.f) ? -1.f : lp; - bp = hp * m_vfb[0] + m_vfbp[4][_chnl] * m_vfa[0]; - bp = (bp > +1.f) ? +1.f : bp; - bp = (bp < -1.f) ? -1.f : bp; + hp = m_vfc[0] * ( m_vfhp[4][_chnl] + in - m_vflast[4][_chnl] ); + hp = (hp > +1.f) ? +1.f : hp; + hp = (hp < -1.f) ? -1.f : hp; - m_vflast[4][_chnl] = in; - m_vflp[4][_chnl] = lp; - m_vfhp[4][_chnl] = hp; - m_vfbp[4][_chnl] = bp; + bp = hp * m_vfb[0] + m_vfbp[4][_chnl] * m_vfa[0]; + bp = (bp > +1.f) ? +1.f : bp; + bp = (bp < -1.f) ? -1.f : bp; - out += bp; + m_vflast[4][_chnl] = in; + m_vflp[4][_chnl] = lp; + m_vfhp[4][_chnl] = hp; + m_vfbp[4][_chnl] = bp; - // second formant - in = _in0 + m_vfbp[0][_chnl] * m_vfq; - in = (in > +1.f) ? +1.f : in; - in = (in < -1.f) ? -1.f : in; + out += bp; - lp = in * m_vfb[1] + m_vflp[1][_chnl] * m_vfa[1]; - lp = (lp > +1.f) ? +1.f : lp; - lp = (lp < -1.f) ? -1.f : lp; + // second formant + in = _in0 + m_vfbp[0][_chnl] * m_vfq; + in = (in > +1.f) ? +1.f : in; + in = (in < -1.f) ? -1.f : in; - hp = m_vfc[1] * ( m_vfhp[1][_chnl] + in - m_vflast[1][_chnl] ); - hp = (hp > +1.f) ? +1.f : hp; - hp = (hp < -1.f) ? -1.f : hp; + lp = in * m_vfb[1] + m_vflp[1][_chnl] * m_vfa[1]; + lp = (lp > +1.f) ? +1.f : lp; + lp = (lp < -1.f) ? -1.f : lp; - bp = hp * m_vfb[1] + m_vfbp[1][_chnl] * m_vfa[1]; - bp = (bp > +1.f) ? +1.f : bp; - bp = (bp < -1.f) ? -1.f : bp; + hp = m_vfc[1] * ( m_vfhp[1][_chnl] + in - m_vflast[1][_chnl] ); + hp = (hp > +1.f) ? +1.f : hp; + hp = (hp < -1.f) ? -1.f : hp; - m_vflast[1][_chnl] = in; - m_vflp[1][_chnl] = lp; - m_vfhp[1][_chnl] = hp; - m_vfbp[1][_chnl] = bp; + bp = hp * m_vfb[1] + m_vfbp[1][_chnl] * m_vfa[1]; + bp = (bp > +1.f) ? +1.f : bp; + bp = (bp < -1.f) ? -1.f : bp; - in = bp + m_vfbp[3][_chnl] * m_vfq; - in = (in > +1.f) ? +1.f : in; - in = (in < -1.f) ? -1.f : in; + m_vflast[1][_chnl] = in; + m_vflp[1][_chnl] = lp; + m_vfhp[1][_chnl] = hp; + m_vfbp[1][_chnl] = bp; - lp = in * m_vfb[1] + m_vflp[3][_chnl] * m_vfa[1]; - lp = (lp > +1.f) ? +1.f : lp; - lp = (lp < -1.f) ? -1.f : lp; + in = bp + m_vfbp[3][_chnl] * m_vfq; + in = (in > +1.f) ? +1.f : in; + in = (in < -1.f) ? -1.f : in; - hp = m_vfc[1] * ( m_vfhp[3][_chnl] + in - m_vflast[3][_chnl] ); - hp = (hp > +1.f) ? +1.f : hp; - hp = (hp < -1.f) ? -1.f : hp; + lp = in * m_vfb[1] + m_vflp[3][_chnl] * m_vfa[1]; + lp = (lp > +1.f) ? +1.f : lp; + lp = (lp < -1.f) ? -1.f : lp; - bp = hp * m_vfb[1] + m_vfbp[3][_chnl] * m_vfa[1]; - bp = (bp > +1.f) ? +1.f : bp; - bp = (bp < -1.f) ? -1.f : bp; + hp = m_vfc[1] * ( m_vfhp[3][_chnl] + in - m_vflast[3][_chnl] ); + hp = (hp > +1.f) ? +1.f : hp; + hp = (hp < -1.f) ? -1.f : hp; - m_vflast[3][_chnl] = in; - m_vflp[3][_chnl] = lp; - m_vfhp[3][_chnl] = hp; - m_vfbp[3][_chnl] = bp; + bp = hp * m_vfb[1] + m_vfbp[3][_chnl] * m_vfa[1]; + bp = (bp > +1.f) ? +1.f : bp; + bp = (bp < -1.f) ? -1.f : bp; - in = bp + m_vfbp[5][_chnl] * m_vfq; - in = (in > +1.f) ? +1.f : in; - in = (in < -1.f) ? -1.f : in; + m_vflast[3][_chnl] = in; + m_vflp[3][_chnl] = lp; + m_vfhp[3][_chnl] = hp; + m_vfbp[3][_chnl] = bp; - lp = in * m_vfb[1] + m_vflp[5][_chnl] * m_vfa[1]; - lp = (lp > +1.f) ? +1.f : lp; - lp = (lp < -1.f) ? -1.f : lp; + in = bp + m_vfbp[5][_chnl] * m_vfq; + in = (in > +1.f) ? +1.f : in; + in = (in < -1.f) ? -1.f : in; - hp = m_vfc[1] * ( m_vfhp[5][_chnl] + in - m_vflast[5][_chnl] ); - hp = (hp > +1.f) ? +1.f : hp; - hp = (hp < -1.f) ? -1.f : hp; + lp = in * m_vfb[1] + m_vflp[5][_chnl] * m_vfa[1]; + lp = (lp > +1.f) ? +1.f : lp; + lp = (lp < -1.f) ? -1.f : lp; - bp = hp * m_vfb[1] + m_vfbp[5][_chnl] * m_vfa[1]; - bp = (bp > +1.f) ? +1.f : bp; - bp = (bp < -1.f) ? -1.f : bp; + hp = m_vfc[1] * ( m_vfhp[5][_chnl] + in - m_vflast[5][_chnl] ); + hp = (hp > +1.f) ? +1.f : hp; + hp = (hp < -1.f) ? -1.f : hp; - m_vflast[5][_chnl] = in; - m_vflp[5][_chnl] = lp; - m_vfhp[5][_chnl] = hp; - m_vfbp[5][_chnl] = bp; + bp = hp * m_vfb[1] + m_vfbp[5][_chnl] * m_vfa[1]; + bp = (bp > +1.f) ? +1.f : bp; + bp = (bp < -1.f) ? -1.f : bp; + + m_vflast[5][_chnl] = in; + m_vflp[5][_chnl] = lp; + m_vfhp[5][_chnl] = hp; + m_vfbp[5][_chnl] = bp; + + out += bp; + } - out += bp; - } - return( out/2.0f ); break; } - + default: // filter out = m_b0a0*_in0 + @@ -504,11 +509,11 @@ public: { _freq = 50.f; } - + m_rca = 1.0f - (1.0f/(m_sampleRate*4)) / ( (1.0f/(_freq*2.0f*M_PI)) + (1.0f/(m_sampleRate*4)) ); m_rcb = 1.0f - m_rca; m_rcc = (1.0f/(_freq*2.0f*M_PI)) / ( (1.0f/(_freq*2.0f*M_PI)) + (1.0f/(m_sampleRate*4)) ); - + // Stretch Q/resonance, as self-oscillation reliably starts at a q of ~2.5 - ~2.6 m_rcq = _q/4.f; } @@ -529,11 +534,11 @@ public: const float fract = ( _freq/14000.f * 4.f ) - (float)vowel; - // interpolate between formant frequencies - const float f0 = _f[vowel+0][0] * ( 1.0f - fract ) + + // interpolate between formant frequencies + const float f0 = _f[vowel+0][0] * ( 1.0f - fract ) + _f[vowel+1][0] * ( fract ); - const float f1 = _f[vowel+0][1] * ( 1.0f - fract ) + + const float f1 = _f[vowel+0][1] * ( 1.0f - fract ) + _f[vowel+1][1] * ( fract ); m_vfa[0] = 1.0f - (1.0f/(m_sampleRate*4)) / @@ -552,7 +557,7 @@ public: ( (1.0f/(f1*2.0f*M_PI)) + (1.0f/(m_sampleRate*4)) ); } - + if( m_type == Moog ) { // [ 0 - 0.5 ] @@ -647,7 +652,7 @@ private: // coeffs for formant-filters float m_vfa[4], m_vfb[4], m_vfc[4], m_vfq; - + typedef sample_t frame[CHANNELS]; // in/out history @@ -655,14 +660,14 @@ private: // in/out history for moog-filter frame m_y1, m_y2, m_y3, m_y4, m_oldx, m_oldy1, m_oldy2, m_oldy3; - + // in/out history for RC-type-filters frame m_rcbp0, m_rclp0, m_rchp0, m_rclast0; frame m_rcbp1, m_rclp1, m_rchp1, m_rclast1; // in/out history for Formant-filters frame m_vfbp[6], m_vflp[6], m_vfhp[6], m_vflast[6]; - + FilterTypes m_type; bool m_doubleFilter; From d6809b45c1aa97580c84c5b935d5e7325b384d14 Mon Sep 17 00:00:00 2001 From: Vesa Date: Thu, 26 Jun 2014 12:41:35 +0300 Subject: [PATCH 2/4] basic_filters: further optimization Use qBound in formant, and return early from calcFilterCoeffs so we don't do needless calculations --- include/basic_filters.h | 93 ++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 58 deletions(-) diff --git a/include/basic_filters.h b/include/basic_filters.h index 923716a35..e27766c3c 100644 --- a/include/basic_filters.h +++ b/include/basic_filters.h @@ -26,8 +26,8 @@ */ -#ifndef _BASIC_FILTERS_H -#define _BASIC_FILTERS_H +#ifndef BASIC_FILTERS_H +#define BASIC_FILTERS_H #ifndef __USE_XOPEN #define __USE_XOPEN @@ -327,20 +327,16 @@ public: { // first formant in = _in0 + m_vfbp[0][_chnl] * m_vfq; - in = (in > +1.f) ? +1.f : in; - in = (in < -1.f) ? -1.f : in; + in = qBound( -1.0f, in, 1.0f ); lp = in * m_vfb[0] + m_vflp[0][_chnl] * m_vfa[0]; - lp = (lp > +1.f) ? +1.f : lp; - lp = (lp < -1.f) ? -1.f : lp; + lp = qBound( -1.0f, lp, 1.0f ); hp = m_vfc[0] * ( m_vfhp[0][_chnl] + in - m_vflast[0][_chnl] ); - hp = (hp > +1.f) ? +1.f : hp; - hp = (hp < -1.f) ? -1.f : hp; + hp = qBound( -1.0f, hp, 1.0f ); bp = hp * m_vfb[0] + m_vfbp[0][_chnl] * m_vfa[0]; - bp = (bp > +1.f) ? +1.f : bp; - bp = (bp < -1.f) ? -1.f : bp; + bp = qBound( -1.0f, bp, 1.0f ); m_vflast[0][_chnl] = in; m_vflp[0][_chnl] = lp; @@ -348,20 +344,16 @@ public: m_vfbp[0][_chnl] = bp; in = bp + m_vfbp[2][_chnl] * m_vfq; - in = (in > +1.f) ? +1.f : in; - in = (in < -1.f) ? -1.f : in; + in = qBound( -1.0f, in, 1.0f ); lp = in * m_vfb[0] + m_vflp[2][_chnl] * m_vfa[0]; - lp = (lp > +1.f) ? +1.f : lp; - lp = (lp < -1.f) ? -1.f : lp; + lp = qBound( -1.0f, lp, 1.0f ); hp = m_vfc[0] * ( m_vfhp[2][_chnl] + in - m_vflast[2][_chnl] ); - hp = (hp > +1.f) ? +1.f : hp; - hp = (hp < -1.f) ? -1.f : hp; + hp = qBound( -1.0f, hp, 1.0f ); bp = hp * m_vfb[0] + m_vfbp[2][_chnl] * m_vfa[0]; - bp = (bp > +1.f) ? +1.f : bp; - bp = (bp < -1.f) ? -1.f : bp; + bp = qBound( -1.0f, bp, 1.0f ); m_vflast[2][_chnl] = in; m_vflp[2][_chnl] = lp; @@ -369,20 +361,16 @@ public: m_vfbp[2][_chnl] = bp; in = bp + m_vfbp[4][_chnl] * m_vfq; - in = (in > +1.f) ? +1.f : in; - in = (in < -1.f) ? -1.f : in; + in = qBound( -1.0f, in, 1.0f ); lp = in * m_vfb[0] + m_vflp[4][_chnl] * m_vfa[0]; - lp = (lp > +1.f) ? +1.f : lp; - lp = (lp < -1.f) ? -1.f : lp; + lp = qBound( -1.0f, lp, 1.0f ); hp = m_vfc[0] * ( m_vfhp[4][_chnl] + in - m_vflast[4][_chnl] ); - hp = (hp > +1.f) ? +1.f : hp; - hp = (hp < -1.f) ? -1.f : hp; + hp = qBound( -1.0f, hp, 1.0f ); bp = hp * m_vfb[0] + m_vfbp[4][_chnl] * m_vfa[0]; - bp = (bp > +1.f) ? +1.f : bp; - bp = (bp < -1.f) ? -1.f : bp; + bp = qBound( -1.0f, bp, 1.0f ); m_vflast[4][_chnl] = in; m_vflp[4][_chnl] = lp; @@ -393,20 +381,16 @@ public: // second formant in = _in0 + m_vfbp[0][_chnl] * m_vfq; - in = (in > +1.f) ? +1.f : in; - in = (in < -1.f) ? -1.f : in; + in = qBound( -1.0f, in, 1.0f ); lp = in * m_vfb[1] + m_vflp[1][_chnl] * m_vfa[1]; - lp = (lp > +1.f) ? +1.f : lp; - lp = (lp < -1.f) ? -1.f : lp; + lp = qBound( -1.0f, lp, 1.0f ); hp = m_vfc[1] * ( m_vfhp[1][_chnl] + in - m_vflast[1][_chnl] ); - hp = (hp > +1.f) ? +1.f : hp; - hp = (hp < -1.f) ? -1.f : hp; + hp = qBound( -1.0f, hp, 1.0f ); bp = hp * m_vfb[1] + m_vfbp[1][_chnl] * m_vfa[1]; - bp = (bp > +1.f) ? +1.f : bp; - bp = (bp < -1.f) ? -1.f : bp; + bp = qBound( -1.0f, bp, 1.0f ); m_vflast[1][_chnl] = in; m_vflp[1][_chnl] = lp; @@ -414,20 +398,16 @@ public: m_vfbp[1][_chnl] = bp; in = bp + m_vfbp[3][_chnl] * m_vfq; - in = (in > +1.f) ? +1.f : in; - in = (in < -1.f) ? -1.f : in; + in = qBound( -1.0f, in, 1.0f ); lp = in * m_vfb[1] + m_vflp[3][_chnl] * m_vfa[1]; - lp = (lp > +1.f) ? +1.f : lp; - lp = (lp < -1.f) ? -1.f : lp; + lp = qBound( -1.0f, lp, 1.0f ); hp = m_vfc[1] * ( m_vfhp[3][_chnl] + in - m_vflast[3][_chnl] ); - hp = (hp > +1.f) ? +1.f : hp; - hp = (hp < -1.f) ? -1.f : hp; + hp = qBound( -1.0f, hp, 1.0f ); bp = hp * m_vfb[1] + m_vfbp[3][_chnl] * m_vfa[1]; - bp = (bp > +1.f) ? +1.f : bp; - bp = (bp < -1.f) ? -1.f : bp; + bp = qBound( -1.0f, bp, 1.0f ); m_vflast[3][_chnl] = in; m_vflp[3][_chnl] = lp; @@ -435,20 +415,16 @@ public: m_vfbp[3][_chnl] = bp; in = bp + m_vfbp[5][_chnl] * m_vfq; - in = (in > +1.f) ? +1.f : in; - in = (in < -1.f) ? -1.f : in; + in = qBound( -1.0f, in, 1.0f ); lp = in * m_vfb[1] + m_vflp[5][_chnl] * m_vfa[1]; - lp = (lp > +1.f) ? +1.f : lp; - lp = (lp < -1.f) ? -1.f : lp; + lp = qBound( -1.0f, lp, 1.0f ); hp = m_vfc[1] * ( m_vfhp[5][_chnl] + in - m_vflast[5][_chnl] ); - hp = (hp > +1.f) ? +1.f : hp; - hp = (hp < -1.f) ? -1.f : hp; + hp = qBound( -1.0f, hp, 1.0f ); bp = hp * m_vfb[1] + m_vfbp[5][_chnl] * m_vfa[1]; - bp = (bp > +1.f) ? +1.f : bp; - bp = (bp < -1.f) ? -1.f : bp; + bp = qBound( -1.0f, bp, 1.0f ); m_vflast[5][_chnl] = in; m_vflp[5][_chnl] = lp; @@ -493,9 +469,6 @@ public: /*, const bool _q_is_bandwidth = false*/ ) { // temp coef vars - _freq = qBound(minFreq(), _freq, 20000.0f); // limit freq and q for not getting - // bad noise out of the filter... - _q = qMax( _q, minQ() ); if( m_type == Lowpass_RC12 || @@ -505,10 +478,7 @@ public: m_type == Bandpass_RC24 || m_type == Highpass_RC24 ) { - if( _freq < 50.f ) - { - _freq = 50.f; - } + _freq = qBound( 50.0f, _freq, 20000.0f ); m_rca = 1.0f - (1.0f/(m_sampleRate*4)) / ( (1.0f/(_freq*2.0f*M_PI)) + (1.0f/(m_sampleRate*4)) ); m_rcb = 1.0f - m_rca; @@ -516,12 +486,15 @@ public: // Stretch Q/resonance, as self-oscillation reliably starts at a q of ~2.5 - ~2.6 m_rcq = _q/4.f; + return; } if( m_type == Formantfilter ) { + _freq = qBound( minFreq(), _freq, 20000.0f ); // limit freq and q for not getting bad noise out of the filter... + // formats for a, e, i, o, u, a - const float _f[5][2] = { { 1000, 1400 }, { 500, 2300 }, + static const float _f[5][2] = { { 1000, 1400 }, { 500, 2300 }, { 320, 3200 }, { 500, 1000 }, { 320, 800 } }; @@ -556,10 +529,13 @@ public: m_vfc[1] = (1.0f/(f1*2.0f*M_PI)) / ( (1.0f/(f1*2.0f*M_PI)) + (1.0f/(m_sampleRate*4)) ); + return; } if( m_type == Moog ) { + _freq = qBound( minFreq(), _freq, 20000.0f ); + // [ 0 - 0.5 ] const float f = _freq / m_sampleRate; // (Empirical tunning) @@ -577,6 +553,7 @@ public: } // other filters + _freq = qBound( minFreq(), _freq, 20000.0f ); const float omega = F_2PI * _freq / m_sampleRate; const float tsin = sinf( omega ); const float tcos = cosf( omega ); From ba700399da875640dd23a710eae5aaf178c7ed8a Mon Sep 17 00:00:00 2001 From: Vesa Date: Thu, 26 Jun 2014 13:15:20 +0300 Subject: [PATCH 3/4] basic_filters - even more optimization Use more efficient interpolation, optimize some calculations --- include/basic_filters.h | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/include/basic_filters.h b/include/basic_filters.h index e27766c3c..f026226a1 100644 --- a/include/basic_filters.h +++ b/include/basic_filters.h @@ -39,6 +39,7 @@ #include "Mixer.h" #include "templates.h" #include "lmms_constants.h" +#include "interpolation.h" //#include //#include @@ -498,21 +499,19 @@ public: { 320, 3200 }, { 500, 1000 }, { 320, 800 } }; + static const float freqRatio = 4.0f / 14000.0f; // Stretch Q/resonance m_vfq = _q/4.f; // frequency in lmms ranges from 1Hz to 14000Hz - const int vowel = (int)( floor( _freq/14000.f * 4.f ) ); - const float fract = ( _freq/14000.f * 4.f ) - - (float)vowel; + const float vowelf = _freq * freqRatio; + const int vowel = static_cast( vowelf ); + const float fract = vowelf - vowel; // interpolate between formant frequencies - const float f0 = _f[vowel+0][0] * ( 1.0f - fract ) + - _f[vowel+1][0] * ( fract ); - - const float f1 = _f[vowel+0][1] * ( 1.0f - fract ) + - _f[vowel+1][1] * ( fract ); + const float f0 = linearInterpolate( _f[vowel+0][0], _f[vowel+1][0], fract ); + const float f1 = linearInterpolate( _f[vowel+0][1], _f[vowel+1][1], fract ); m_vfa[0] = 1.0f - (1.0f/(m_sampleRate*4)) / ( (1.0f/(f0*2.0f*M_PI)) + From 27383f91b7a5fc12ef1f8abbbbc7abe2ed113626 Mon Sep 17 00:00:00 2001 From: Vesa Date: Thu, 26 Jun 2014 13:18:00 +0300 Subject: [PATCH 4/4] basic_filters: replace div with mul --- include/basic_filters.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/basic_filters.h b/include/basic_filters.h index f026226a1..84484aeae 100644 --- a/include/basic_filters.h +++ b/include/basic_filters.h @@ -486,7 +486,7 @@ public: m_rcc = (1.0f/(_freq*2.0f*M_PI)) / ( (1.0f/(_freq*2.0f*M_PI)) + (1.0f/(m_sampleRate*4)) ); // Stretch Q/resonance, as self-oscillation reliably starts at a q of ~2.5 - ~2.6 - m_rcq = _q/4.f; + m_rcq = _q * 0.25f; return; } @@ -502,7 +502,7 @@ public: static const float freqRatio = 4.0f / 14000.0f; // Stretch Q/resonance - m_vfq = _q/4.f; + m_vfq = _q * 0.25f; // frequency in lmms ranges from 1Hz to 14000Hz const float vowelf = _freq * freqRatio;