diff --git a/include/BiQuad.h b/include/BiQuad.h index 5e8aaf7..ac200ab 100644 --- a/include/BiQuad.h +++ b/include/BiQuad.h @@ -74,6 +74,46 @@ public: */ void setNotch( StkFloat frequency, StkFloat radius ); + //! Set the filter coefficients for a low-pass at \e frequency (in Hz) with factor \e Q. + /*! + This method determines the filter coefficients corresponding to + a low-pass filter with cutoff placed at \e frequency and + Q-factor set by \e Q. Both \e frequency and \e Q must be positive. + */ + void setLowPass( StkFloat frequency, StkFloat Q ); + + //! Set the filter coefficients for a high-pass at \e frequency (in Hz) with factor \e Q. + /*! + This method determines the filter coefficients corresponding to + a high-pass filter with cutoff placed at \e frequency and + Q-factor set by \e Q. Both \e frequency and \e Q must be positive. + */ + void setHighPass( StkFloat frequency, StkFloat Q ); + + //! Set the filter coefficients for a band-pass at \e frequency (in Hz) with factor \e Q. + /*! + This method determines the filter coefficients corresponding to + a band-pass filter with center placed at \e frequency and + Q-factor set by \e Q. Both \e frequency and \e Q must be positive. + */ + void setBandPass( StkFloat frequency, StkFloat Q ); + + //! Set the filter coefficients for a band-reject at \e frequency (in Hz) with factor \e Q. + /*! + This method determines the filter coefficients corresponding to + a band-reject filter with center placed at \e frequency and + Q-factor set by \e Q. Both \e frequency and \e Q must be positive. + */ + void setBandReject( StkFloat frequency, StkFloat Q ); + + //! Set the filter coefficients for an all-pass at \e frequency (in Hz) with factor \e Q. + /*! + This method determines the filter coefficients corresponding to + an all-pass filter with center placed at \e frequency and + Q-factor set by \e Q. Both \e frequency and \e Q must be positive. + */ + void setAllPass( StkFloat frequency, StkFloat Q ); + //! Sets the filter zeroes for equal resonance gain. /*! When using the filter as a resonator, zeroes places at z = 1, z @@ -114,6 +154,14 @@ public: protected: virtual void sampleRateChanged( StkFloat newRate, StkFloat oldRate ); + + // Helper function to update the three intermediate values for the predefined filter types + // along with the feedback filter coefficients. Performs the debug check for frequency and Q-factor arguments. + void setCommonFilterValues( StkFloat frequency, StkFloat Q ); + + StkFloat K_; + StkFloat kSqr_; + StkFloat denom_; }; inline StkFloat BiQuad :: tick( StkFloat input ) diff --git a/src/BiQuad.cpp b/src/BiQuad.cpp index 024a65f..c841d6f 100644 --- a/src/BiQuad.cpp +++ b/src/BiQuad.cpp @@ -24,6 +24,10 @@ BiQuad :: BiQuad() : Filter() inputs_.resize( 3, 1, 0.0 ); outputs_.resize( 3, 1, 0.0 ); + K_ = 0.0; + kSqr_ = 0.0; + denom_ = 1.0; + Stk::addSampleRateAlert( this ); } @@ -73,6 +77,11 @@ void BiQuad :: setResonance( StkFloat frequency, StkFloat radius, bool normalize b_[1] = 0.0; b_[2] = -b_[0]; } + else { + b_[0] = 1.0; + b_[1] = 0.0; + b_[2] = 0.0; + } } void BiQuad :: setNotch( StkFloat frequency, StkFloat radius ) @@ -93,6 +102,51 @@ void BiQuad :: setNotch( StkFloat frequency, StkFloat radius ) b_[1] = (StkFloat) -2.0 * radius * cos( TWO_PI * (double) frequency / Stk::sampleRate() ); } +void BiQuad :: setLowPass( StkFloat frequency, StkFloat Q ) +{ + setCommonFilterValues(frequency, Q); + + b_[0] = kSqr_ * Q * denom_; + b_[1] = 2 * b_[0]; + b_[2] = b_[0]; +} + +void BiQuad :: setHighPass( StkFloat frequency, StkFloat Q ) +{ + setCommonFilterValues(frequency, Q); + + b_[0] = Q * denom_; + b_[1] = -2 * b_[0]; + b_[2] = b_[0]; +} + +void BiQuad :: setBandPass( StkFloat frequency, StkFloat Q ) +{ + setCommonFilterValues(frequency, Q); + + b_[0] = K_ * denom_; + b_[1] = 0.0; + b_[2] = -b_[0]; +} + +void BiQuad :: setBandReject( StkFloat frequency, StkFloat Q ) +{ + setCommonFilterValues(frequency, Q); + + b_[0] = Q * (kSqr_ + 1) * denom_; + b_[1] = 2 * Q * (kSqr_ - 1) * denom_; + b_[2] = b_[0]; +} + +void BiQuad :: setAllPass( StkFloat frequency, StkFloat Q ) +{ + setCommonFilterValues(frequency, Q); + + b_[0] = a_[2]; + b_[1] = a_[1]; + b_[2] = 1; +} + void BiQuad :: setEqualGainZeroes( void ) { b_[0] = 1.0; @@ -100,4 +154,25 @@ void BiQuad :: setEqualGainZeroes( void ) b_[2] = -1.0; } +void BiQuad :: setCommonFilterValues( StkFloat frequency, StkFloat Q) +{ +#if defined(_STK_DEBUG_) + if ( frequency < 0.0 ) { + oStream_ << "BiQuad::updateKValues: frequency argument (" << frequency << ") is negative!"; + handleError( StkError::WARNING ); return; + } + if ( Q < 0.0 ) { + oStream_ << "BiQuad::updateKValues: Q argument (" << Q << ") is negative!"; + handleError( StkError::WARNING ); return; + } +#endif + + K_ = tan(PI * frequency / Stk::sampleRate()); + kSqr_ = K_ * K_; + denom_ = 1 / (kSqr_ * Q + K_ + Q); + + a_[1] = 2 * Q * (kSqr_ - 1) * denom_; + a_[2] = (kSqr_ * Q - K_ + Q) * denom_; +} + } // stk namespace