You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

205 lines
6.6KB

  1. #ifndef STK_IIR_H
  2. #define STK_IIR_H
  3. #include "Filter.h"
  4. namespace stk {
  5. /***************************************************/
  6. /*! \class Iir
  7. \brief STK general infinite impulse response filter class.
  8. This class provides a generic digital filter structure that can be
  9. used to implement IIR filters. For filters containing only
  10. feedforward terms, the Fir class is slightly more efficient.
  11. In particular, this class implements the standard difference
  12. equation:
  13. a[0]*y[n] = b[0]*x[n] + ... + b[nb]*x[n-nb] -
  14. a[1]*y[n-1] - ... - a[na]*y[n-na]
  15. If a[0] is not equal to 1, the filter coeffcients are normalized
  16. by a[0].
  17. The \e gain parameter is applied at the filter input and does not
  18. affect the coefficient values. The default gain value is 1.0.
  19. This structure results in one extra multiply per computed sample,
  20. but allows easy control of the overall filter gain.
  21. by Perry R. Cook and Gary P. Scavone, 1995--2017.
  22. */
  23. /***************************************************/
  24. class Iir : public Filter
  25. {
  26. public:
  27. //! Default constructor creates a zero-order pass-through "filter".
  28. Iir( void );
  29. //! Overloaded constructor which takes filter coefficients.
  30. /*!
  31. An StkError can be thrown if either of the coefficient vector
  32. sizes is zero, or if the a[0] coefficient is equal to zero.
  33. */
  34. Iir( std::vector<StkFloat> &bCoefficients, std::vector<StkFloat> &aCoefficients );
  35. //! Class destructor.
  36. ~Iir( void );
  37. //! Set filter coefficients.
  38. /*!
  39. An StkError can be thrown if either of the coefficient vector
  40. sizes is zero, or if the a[0] coefficient is equal to zero. If
  41. a[0] is not equal to 1, the filter coeffcients are normalized by
  42. a[0]. The internal state of the filter is not cleared unless the
  43. \e clearState flag is \c true.
  44. */
  45. void setCoefficients( std::vector<StkFloat> &bCoefficients, std::vector<StkFloat> &aCoefficients, bool clearState = false );
  46. //! Set numerator coefficients.
  47. /*!
  48. An StkError can be thrown if coefficient vector is empty. Any
  49. previously set denominator coefficients are left unaffected. Note
  50. that the default constructor sets the single denominator
  51. coefficient a[0] to 1.0. The internal state of the filter is not
  52. cleared unless the \e clearState flag is \c true.
  53. */
  54. void setNumerator( std::vector<StkFloat> &bCoefficients, bool clearState = false );
  55. //! Set denominator coefficients.
  56. /*!
  57. An StkError can be thrown if the coefficient vector is empty or
  58. if the a[0] coefficient is equal to zero. Previously set
  59. numerator coefficients are unaffected unless a[0] is not equal to
  60. 1, in which case all coeffcients are normalized by a[0]. Note
  61. that the default constructor sets the single numerator coefficient
  62. b[0] to 1.0. The internal state of the filter is not cleared
  63. unless the \e clearState flag is \c true.
  64. */
  65. void setDenominator( std::vector<StkFloat> &aCoefficients, bool clearState = false );
  66. //! Return the last computed output value.
  67. StkFloat lastOut( void ) const { return lastFrame_[0]; };
  68. //! Input one sample to the filter and return one output.
  69. StkFloat tick( StkFloat input );
  70. //! Take a channel of the StkFrames object as inputs to the filter and replace with corresponding outputs.
  71. /*!
  72. The StkFrames argument reference is returned. The \c channel
  73. argument must be less than the number of channels in the
  74. StkFrames argument (the first channel is specified by 0).
  75. However, range checking is only performed if _STK_DEBUG_ is
  76. defined during compilation, in which case an out-of-range value
  77. will trigger an StkError exception.
  78. */
  79. StkFrames& tick( StkFrames& frames, unsigned int channel = 0 );
  80. //! Take a channel of the \c iFrames object as inputs to the filter and write outputs to the \c oFrames object.
  81. /*!
  82. The \c iFrames object reference is returned. Each channel
  83. argument must be less than the number of channels in the
  84. corresponding StkFrames argument (the first channel is specified
  85. by 0). However, range checking is only performed if _STK_DEBUG_
  86. is defined during compilation, in which case an out-of-range value
  87. will trigger an StkError exception.
  88. */
  89. StkFrames& tick( StkFrames& iFrames, StkFrames &oFrames, unsigned int iChannel = 0, unsigned int oChannel = 0 );
  90. protected:
  91. };
  92. inline StkFloat Iir :: tick( StkFloat input )
  93. {
  94. size_t i;
  95. outputs_[0] = 0.0;
  96. inputs_[0] = gain_ * input;
  97. for ( i=b_.size()-1; i>0; i-- ) {
  98. outputs_[0] += b_[i] * inputs_[i];
  99. inputs_[i] = inputs_[i-1];
  100. }
  101. outputs_[0] += b_[0] * inputs_[0];
  102. for ( i=a_.size()-1; i>0; i-- ) {
  103. outputs_[0] += -a_[i] * outputs_[i];
  104. outputs_[i] = outputs_[i-1];
  105. }
  106. lastFrame_[0] = outputs_[0];
  107. return lastFrame_[0];
  108. }
  109. inline StkFrames& Iir :: tick( StkFrames& frames, unsigned int channel )
  110. {
  111. #if defined(_STK_DEBUG_)
  112. if ( channel >= frames.channels() ) {
  113. oStream_ << "Iir::tick(): channel and StkFrames arguments are incompatible!";
  114. handleError( StkError::FUNCTION_ARGUMENT );
  115. }
  116. #endif
  117. StkFloat *samples = &frames[channel];
  118. size_t i;
  119. unsigned int hop = frames.channels();
  120. for ( unsigned int j=0; j<frames.frames(); j++, samples += hop ) {
  121. outputs_[0] = 0.0;
  122. inputs_[0] = gain_ * *samples;
  123. for ( i=b_.size()-1; i>0; i-- ) {
  124. outputs_[0] += b_[i] * inputs_[i];
  125. inputs_[i] = inputs_[i-1];
  126. }
  127. outputs_[0] += b_[0] * inputs_[0];
  128. for ( i=a_.size()-1; i>0; i-- ) {
  129. outputs_[0] += -a_[i] * outputs_[i];
  130. outputs_[i] = outputs_[i-1];
  131. }
  132. *samples = outputs_[0];
  133. }
  134. lastFrame_[0] = *(samples-hop);
  135. return frames;
  136. }
  137. inline StkFrames& Iir :: tick( StkFrames& iFrames, StkFrames& oFrames, unsigned int iChannel, unsigned int oChannel )
  138. {
  139. #if defined(_STK_DEBUG_)
  140. if ( iChannel >= iFrames.channels() || oChannel >= oFrames.channels() ) {
  141. oStream_ << "Iir::tick(): channel and StkFrames arguments are incompatible!";
  142. handleError( StkError::FUNCTION_ARGUMENT );
  143. }
  144. #endif
  145. StkFloat *iSamples = &iFrames[iChannel];
  146. StkFloat *oSamples = &oFrames[oChannel];
  147. size_t i;
  148. unsigned int iHop = iFrames.channels(), oHop = oFrames.channels();
  149. for ( unsigned int j=0; j<iFrames.frames(); j++, iSamples += iHop, oSamples += oHop ) {
  150. outputs_[0] = 0.0;
  151. inputs_[0] = gain_ * *iSamples;
  152. for ( i=b_.size()-1; i>0; i-- ) {
  153. outputs_[0] += b_[i] * inputs_[i];
  154. inputs_[i] = inputs_[i-1];
  155. }
  156. outputs_[0] += b_[0] * inputs_[0];
  157. for ( i=a_.size()-1; i>0; i-- ) {
  158. outputs_[0] += -a_[i] * outputs_[i];
  159. outputs_[i] = outputs_[i-1];
  160. }
  161. *oSamples = outputs_[0];
  162. }
  163. lastFrame_[0] = *(oSamples-oHop);
  164. return iFrames;
  165. }
  166. } // stk namespace
  167. #endif