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.

Biquad.h 6.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /*******************************************************************************
  2. "A Collection of Useful C++ Classes for Digital Signal Processing"
  3. By Vinnie Falco
  4. Official project location:
  5. https://github.com/vinniefalco/DSPFilters
  6. See Documentation.cpp for contact information, notes, and bibliography.
  7. --------------------------------------------------------------------------------
  8. License: MIT License (http://www.opensource.org/licenses/mit-license.php)
  9. Copyright (c) 2009 by Vinnie Falco
  10. Permission is hereby granted, free of charge, to any person obtaining a copy
  11. of this software and associated documentation files (the "Software"), to deal
  12. in the Software without restriction, including without limitation the rights
  13. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  14. copies of the Software, and to permit persons to whom the Software is
  15. furnished to do so, subject to the following conditions:
  16. The above copyright notice and this permission notice shall be included in
  17. all copies or substantial portions of the Software.
  18. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. THE SOFTWARE.
  25. *******************************************************************************/
  26. #ifndef DSPFILTERS_BIQUAD_H
  27. #define DSPFILTERS_BIQUAD_H
  28. #include "Common.h"
  29. #include "MathSupplement.h"
  30. #include "Types.h"
  31. namespace Dsp
  32. {
  33. struct BiquadPoleState;
  34. /*
  35. * Holds coefficients for a second order Infinite Impulse Response
  36. * digital filter. This is the building block for all IIR filters.
  37. *
  38. */
  39. // Factored interface to prevent outsiders from fiddling
  40. class BiquadBase
  41. {
  42. public:
  43. template <class StateType>
  44. struct State : StateType, private DenormalPrevention
  45. {
  46. template <typename Sample>
  47. Sample process(const Sample in, const BiquadBase& b) { return Sample(StateType::process1(in, b, ac())); }
  48. };
  49. // Calculate filter response at the given normalized frequency.
  50. complex_t response(double normalizedFrequency) const;
  51. std::vector<PoleZeroPair> getPoleZeros() const;
  52. double getA0() const { return m_a0; }
  53. double getA1() const { return m_a1 * m_a0; }
  54. double getA2() const { return m_a2 * m_a0; }
  55. double getB0() const { return m_b0 * m_a0; }
  56. double getB1() const { return m_b1 * m_a0; }
  57. double getB2() const { return m_b2 * m_a0; }
  58. // Process a block of samples in the given form
  59. template <class StateType, typename Sample>
  60. void process(int nSamples, Sample* dest, StateType& state) const
  61. {
  62. while (--nSamples >= 0)
  63. {
  64. *dest = state.process(*dest, *this);
  65. ++dest;
  66. }
  67. }
  68. protected:
  69. //
  70. // These are protected so you can't mess with RBJ biquads
  71. //
  72. void setCoefficients(double a0, double a1, double a2, double b0, double b1, double b2);
  73. void setOnePole(complex_t pole, complex_t zero);
  74. void setTwoPole(complex_t pole1, complex_t zero1, complex_t pole2, complex_t zero2);
  75. void setPoleZeroPair(const PoleZeroPair& pair)
  76. {
  77. if (pair.isSinglePole()) { setOnePole(pair.poles.first, pair.zeros.first); }
  78. else { setTwoPole(pair.poles.first, pair.zeros.first, pair.poles.second, pair.zeros.second); }
  79. }
  80. void setPoleZeroForm(const BiquadPoleState& bps);
  81. void setIdentity();
  82. void applyScale(double scale);
  83. public:
  84. double m_a0 = 0;
  85. double m_a1 = 0;
  86. double m_a2 = 0;
  87. double m_b1 = 0;
  88. double m_b2 = 0;
  89. double m_b0 = 0;
  90. };
  91. //------------------------------------------------------------------------------
  92. // Expresses a biquad as a pair of pole/zeros, with gain
  93. // values so that the coefficients can be reconstructed precisely.
  94. struct BiquadPoleState : PoleZeroPair
  95. {
  96. BiquadPoleState() { }
  97. explicit BiquadPoleState(const BiquadBase& s);
  98. double gain = 0;
  99. };
  100. // More permissive interface for fooling around
  101. class Biquad : public BiquadBase
  102. {
  103. public:
  104. Biquad();
  105. explicit Biquad(const BiquadPoleState& bps);
  106. // Process a block of samples, interpolating from the old section's coefficients
  107. // to this section's coefficients, over nSamples. This implements smooth
  108. // parameter changes.
  109. template <class StateType, typename Sample>
  110. void smoothProcess1(int nSamples, Sample* dest, StateType& state, Biquad sectionPrev) const
  111. {
  112. double t = 1. / nSamples;
  113. double da1 = (m_a1 - sectionPrev.m_a1) * t;
  114. double da2 = (m_a2 - sectionPrev.m_a2) * t;
  115. double db0 = (m_b0 - sectionPrev.m_b0) * t;
  116. double db1 = (m_b1 - sectionPrev.m_b1) * t;
  117. double db2 = (m_b2 - sectionPrev.m_b2) * t;
  118. while (--nSamples >= 0)
  119. {
  120. sectionPrev.m_a1 += da1;
  121. sectionPrev.m_a2 += da2;
  122. sectionPrev.m_b0 += db0;
  123. sectionPrev.m_b1 += db1;
  124. sectionPrev.m_b2 += db2;
  125. *dest = state.process(*dest, sectionPrev);
  126. ++dest;
  127. }
  128. }
  129. // Process a block of samples, interpolating from the old section's pole/zeros
  130. // to this section's pole/zeros, over nSamples. The interpolation is done
  131. // in the z-plane using polar coordinates.
  132. template <class StateType, typename Sample>
  133. void smoothProcess2(int nSamples,
  134. Sample* dest,
  135. StateType& state,
  136. BiquadPoleState zPrev) const
  137. {
  138. BiquadPoleState z(*this);
  139. double t = 1. / nSamples;
  140. complex_t dp0 = (z.poles.first - zPrev.poles.first) * t;
  141. complex_t dp1 = (z.poles.second - zPrev.poles.second) * t;
  142. complex_t dz0 = (z.zeros.first - zPrev.zeros.first) * t;
  143. complex_t dz1 = (z.zeros.second - zPrev.zeros.second) * t;
  144. double dg = (z.gain - zPrev.gain) * t;
  145. while (--nSamples >= 0)
  146. {
  147. zPrev.poles.first += dp0;
  148. zPrev.poles.second += dp1;
  149. zPrev.zeros.first += dz0;
  150. zPrev.zeros.second += dz1;
  151. zPrev.gain += dg;
  152. *dest = state.process(*dest, Biquad(zPrev));
  153. ++dest;
  154. }
  155. }
  156. // Export these as public
  157. void setOnePole(complex_t pole, complex_t zero) { BiquadBase::setOnePole(pole, zero); }
  158. void setTwoPole(complex_t pole1, complex_t zero1, complex_t pole2, complex_t zero2) { BiquadBase::setTwoPole(pole1, zero1, pole2, zero2); }
  159. void setPoleZeroPair(const PoleZeroPair& pair) { BiquadBase::setPoleZeroPair(pair); }
  160. void applyScale(double scale) { BiquadBase::applyScale(scale); }
  161. };
  162. } // namespace Dsp
  163. #endif