1
0

Biquad.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. #include "Biquad.h"
  2. #include <assert.h>
  3. #include <math.h>
  4. Biquad::Biquad()
  5. : sampleRate(44100)
  6. , _f0(1000)
  7. {
  8. _z_eq_b[0] = 1;
  9. _z_eq_b[1] = 0;
  10. _z_eq_b[2] = 0;
  11. _z_eq_a[0] = 1;
  12. _z_eq_a[1] = 0;
  13. _z_eq_a[2] = 0;
  14. clear_buffers();
  15. _s_eq_a[0] = 1;
  16. _s_eq_a[1] = 2;
  17. _s_eq_a[2] = 1;
  18. _s_eq_b[0] = _s_eq_a[0];
  19. _s_eq_b[1] = _s_eq_a[1];
  20. _s_eq_b[2] = _s_eq_a[2];
  21. }
  22. #define M_PI 3.14159265358979323846
  23. // warp to the z-plane
  24. void Biquad::transform_s_to_z()
  25. {
  26. // s to z bilinear transform
  27. const double inv_k = tan(_f0 * M_PI / sampleRate);
  28. const double k = 1 / inv_k;
  29. const double kk = k*k;
  30. const double b1k = _s_eq_b[1] * k;
  31. const double b2kk = _s_eq_b[2] * kk;
  32. const double b2kk_plus_b0 = b2kk + _s_eq_b[0];
  33. const double b0z = b2kk_plus_b0 + b1k;
  34. const double b2z = b2kk_plus_b0 - b1k;
  35. const double b1z = 2 * (_s_eq_b[0] - b2kk);
  36. const double a1k = _s_eq_a[1] * k;
  37. const double a2kk = _s_eq_a[2] * kk;
  38. const double a2kk_plus_a0 = a2kk + _s_eq_a[0];
  39. const double a0z = a2kk_plus_a0 + a1k;
  40. const double a2z = a2kk_plus_a0 - a1k;
  41. const double a1z = 2 * (_s_eq_a[0] - a2kk);
  42. // IIR coefficients
  43. const double mult = 1 / a0z;
  44. _z_eq_b[0] = float(b0z * mult);
  45. _z_eq_b[1] = float(b1z * mult);
  46. _z_eq_b[2] = float(b2z * mult);
  47. _z_eq_a[0] = 1;
  48. _z_eq_a[1] = float(a1z * mult);
  49. _z_eq_a[2] = float(a2z * mult);
  50. }
  51. void Biquad::process_block(float *dest_ptr, const float *src_ptr, long nbr_spl)
  52. {
  53. assert(nbr_spl >= 0);
  54. if (nbr_spl == 0)
  55. {
  56. return;
  57. }
  58. // If we're not on a pair boudary, we process a single sample.
  59. if (_mem_pos != 0)
  60. {
  61. *dest_ptr++ = (float)process_sample(*src_ptr++);
  62. nbr_spl--;
  63. }
  64. if (nbr_spl == 0)
  65. {
  66. return;
  67. }
  68. long half_nbr_spl = nbr_spl >> 1;
  69. long index = 0;
  70. if (half_nbr_spl > 0)
  71. {
  72. double mem_x[2];
  73. double mem_y[2];
  74. mem_x[0] = xn[0];
  75. mem_x[1] = xn[1];
  76. mem_y[0] = yn[0];
  77. mem_y[1] = yn[1];
  78. do
  79. {
  80. float x = src_ptr[index];
  81. mem_y[1] = _z_eq_b[0] * x
  82. + (_z_eq_b[1] * mem_x[0]
  83. + _z_eq_b[2] * mem_x[1])
  84. - (_z_eq_a[1] * mem_y[0]
  85. + _z_eq_a[2] * mem_y[1]);
  86. mem_x[1] = x;
  87. dest_ptr[index] = (float)mem_y[1];
  88. x = src_ptr[index + 1];
  89. mem_y[0] = _z_eq_b[0] * x
  90. + (_z_eq_b[1] * mem_x[1]
  91. + _z_eq_b[2] * mem_x[0])
  92. - (_z_eq_a[1] * mem_y[1]
  93. + _z_eq_a[2] * mem_y[0]);
  94. mem_x[0] = x;
  95. dest_ptr[index + 1] = (float)mem_y[0];
  96. index += 2;
  97. -- half_nbr_spl;
  98. }
  99. while (half_nbr_spl > 0);
  100. xn[0] = mem_x[0];
  101. xn[1] = mem_x[1];
  102. yn[0] = mem_y[0];
  103. yn[1] = mem_y[1];
  104. }
  105. // If number of samples was odd, there is one more to process.
  106. if ((nbr_spl & 1) > 0)
  107. {
  108. dest_ptr[index] = (float)process_sample(src_ptr[index]);
  109. }
  110. }
  111. void Biquad::clear_buffers()
  112. {
  113. xn[0] = 0;
  114. xn[1] = 0;
  115. yn[0] = 0;
  116. yn[1] = 0;
  117. _mem_pos = 0;
  118. }
  119. double Biquad::process_sample(double x)
  120. {
  121. const int alt_pos = 1 - _mem_pos;
  122. const double y = _z_eq_b[0] * x
  123. + (_z_eq_b[1] * xn[_mem_pos]
  124. + _z_eq_b[2] * xn[alt_pos])
  125. - (_z_eq_a[1] * yn[_mem_pos]
  126. + _z_eq_a[2] * yn[alt_pos]);
  127. xn[alt_pos] = x;
  128. yn[alt_pos] = y;
  129. _mem_pos = alt_pos;
  130. return (y);
  131. }
  132. void Biquad::copy_filter(const Biquad &other)
  133. {
  134. _z_eq_b[0] = other._z_eq_b[0];
  135. _z_eq_b[1] = other._z_eq_b[1];
  136. _z_eq_b[2] = other._z_eq_b[2];
  137. _z_eq_a[1] = other._z_eq_a[1];
  138. _z_eq_a[2] = other._z_eq_a[2];
  139. sampleRate = other.sampleRate;
  140. _f0 = other._f0;
  141. set_s_eq(other._s_eq_b, other._s_eq_a);
  142. }
  143. void Biquad::SetSampleRate(double fs)
  144. {
  145. assert(fs > 0);
  146. sampleRate = fs;
  147. transform_s_to_z();
  148. }
  149. void Biquad::set_freq(double f0)
  150. {
  151. assert(f0 > 0);
  152. _f0 = f0;
  153. }
  154. void Biquad::set_s_eq(const double b[3], const double a[3])
  155. {
  156. assert(a != 0);
  157. assert(a[2] != 0);
  158. assert(b != 0);
  159. _s_eq_b[0] = float(b[0]);
  160. _s_eq_b[1] = float(b[1]);
  161. _s_eq_b[2] = float(b[2]);
  162. _s_eq_a[0] = float(a[0]);
  163. _s_eq_a[1] = float(a[1]);
  164. _s_eq_a[2] = float(a[2]);
  165. }