BiquadFilter.h 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. #ifndef BELL_BIQUADFILTER_H
  2. #define BELL_BIQUADFILTER_H
  3. #include <mutex>
  4. #include <cmath>
  5. #include "esp_platform.h"
  6. extern "C" int dsps_biquad_f32_ae32(const float* input, float* output, int len, float* coef, float* w);
  7. class BiquadFilter
  8. {
  9. private:
  10. std::mutex processMutex;
  11. float coeffs[5];
  12. float w[2] = {0, 0};
  13. public:
  14. BiquadFilter(){};
  15. // Generates coefficients for a high pass biquad filter
  16. void generateHighPassCoEffs(float f, float q){
  17. if (q <= 0.0001) {
  18. q = 0.0001;
  19. }
  20. float Fs = 1;
  21. float w0 = 2 * M_PI * f / Fs;
  22. float c = cosf(w0);
  23. float s = sinf(w0);
  24. float alpha = s / (2 * q);
  25. float b0 = (1 + c) / 2;
  26. float b1 = -(1 + c);
  27. float b2 = b0;
  28. float a0 = 1 + alpha;
  29. float a1 = -2 * c;
  30. float a2 = 1 - alpha;
  31. coeffs[0] = b0 / a0;
  32. coeffs[1] = b1 / a0;
  33. coeffs[2] = b2 / a0;
  34. coeffs[3] = a1 / a0;
  35. coeffs[4] = a2 / a0;
  36. }
  37. // Generates coefficients for a low pass biquad filter
  38. void generateLowPassCoEffs(float f, float q){
  39. if (q <= 0.0001) {
  40. q = 0.0001;
  41. }
  42. float Fs = 1;
  43. float w0 = 2 * M_PI * f / Fs;
  44. float c = cosf(w0);
  45. float s = sinf(w0);
  46. float alpha = s / (2 * q);
  47. float b0 = (1 - c) / 2;
  48. float b1 = 1 - c;
  49. float b2 = b0;
  50. float a0 = 1 + alpha;
  51. float a1 = -2 * c;
  52. float a2 = 1 - alpha;
  53. coeffs[0] = b0 / a0;
  54. coeffs[1] = b1 / a0;
  55. coeffs[2] = b2 / a0;
  56. coeffs[3] = a1 / a0;
  57. coeffs[4] = a2 / a0;
  58. }
  59. // Generates coefficients for a high shelf biquad filter
  60. void generateHighShelfCoEffs(float f, float gain, float q)
  61. {
  62. if (q <= 0.0001)
  63. {
  64. q = 0.0001;
  65. }
  66. float Fs = 1;
  67. float A = sqrtf(pow(10, (double)gain / 20.0));
  68. float w0 = 2 * M_PI * f / Fs;
  69. float c = cosf(w0);
  70. float s = sinf(w0);
  71. float alpha = s / (2 * q);
  72. float b0 = A * ((A + 1) + (A - 1) * c + 2 * sqrtf(A) * alpha);
  73. float b1 = -2 * A * ((A - 1) + (A + 1) * c);
  74. float b2 = A * ((A + 1) + (A - 1) * c - 2 * sqrtf(A) * alpha);
  75. float a0 = (A + 1) - (A - 1) * c + 2 * sqrtf(A) * alpha;
  76. float a1 = 2 * ((A - 1) - (A + 1) * c);
  77. float a2 = (A + 1) - (A - 1) * c - 2 * sqrtf(A) * alpha;
  78. std::lock_guard lock(processMutex);
  79. coeffs[0] = b0 / a0;
  80. coeffs[1] = b1 / a0;
  81. coeffs[2] = b2 / a0;
  82. coeffs[3] = a1 / a0;
  83. coeffs[4] = a2 / a0;
  84. }
  85. // Generates coefficients for a low shelf biquad filter
  86. void generateLowShelfCoEffs(float f, float gain, float q)
  87. {
  88. if (q <= 0.0001)
  89. {
  90. q = 0.0001;
  91. }
  92. float Fs = 1;
  93. float A = sqrtf(pow(10, (double)gain / 20.0));
  94. float w0 = 2 * M_PI * f / Fs;
  95. float c = cosf(w0);
  96. float s = sinf(w0);
  97. float alpha = s / (2 * q);
  98. float b0 = A * ((A + 1) - (A - 1) * c + 2 * sqrtf(A) * alpha);
  99. float b1 = 2 * A * ((A - 1) - (A + 1) * c);
  100. float b2 = A * ((A + 1) - (A - 1) * c - 2 * sqrtf(A) * alpha);
  101. float a0 = (A + 1) + (A - 1) * c + 2 * sqrtf(A) * alpha;
  102. float a1 = -2 * ((A - 1) + (A + 1) * c);
  103. float a2 = (A + 1) + (A - 1) * c - 2 * sqrtf(A) * alpha;
  104. std::lock_guard lock(processMutex);
  105. coeffs[0] = b0 / a0;
  106. coeffs[1] = b1 / a0;
  107. coeffs[2] = b2 / a0;
  108. coeffs[3] = a1 / a0;
  109. coeffs[4] = a2 / a0;
  110. }
  111. // Generates coefficients for a notch biquad filter
  112. void generateNotchCoEffs(float f, float gain, float q)
  113. {
  114. if (q <= 0.0001)
  115. {
  116. q = 0.0001;
  117. }
  118. float Fs = 1;
  119. float A = sqrtf(pow(10, (double)gain / 20.0));
  120. float w0 = 2 * M_PI * f / Fs;
  121. float c = cosf(w0);
  122. float s = sinf(w0);
  123. float alpha = s / (2 * q);
  124. float b0 = 1 + alpha * A;
  125. float b1 = -2 * c;
  126. float b2 = 1 - alpha * A;
  127. float a0 = 1 + alpha;
  128. float a1 = -2 * c;
  129. float a2 = 1 - alpha;
  130. std::scoped_lock lock(processMutex);
  131. coeffs[0] = b0 / a0;
  132. coeffs[1] = b1 / a0;
  133. coeffs[2] = b2 / a0;
  134. coeffs[3] = a1 / a0;
  135. coeffs[4] = a2 / a0;
  136. }
  137. // Generates coefficients for a peaking biquad filter
  138. void generatePeakCoEffs(float f, float gain, float q)
  139. {
  140. if (q <= 0.0001) {
  141. q = 0.0001;
  142. }
  143. float Fs = 1;
  144. float w0 = 2 * M_PI * f / Fs;
  145. float c = cosf(w0);
  146. float s = sinf(w0);
  147. float alpha = s / (2 * q);
  148. float b0 = alpha;
  149. float b1 = 0;
  150. float b2 = -alpha;
  151. float a0 = 1 + alpha;
  152. float a1 = -2 * c;
  153. float a2 = 1 - alpha;
  154. coeffs[0] = b0 / a0;
  155. coeffs[1] = b1 / a0;
  156. coeffs[2] = b2 / a0;
  157. coeffs[3] = a1 / a0;
  158. coeffs[4] = a2 / a0;
  159. }
  160. // Generates coefficients for a peaking EQ biquad filter
  161. void generatePeakingEqCoEffs(float f, float gain, float q)
  162. {
  163. // formular taken from: https://webaudio.github.io/Audio-EQ-Cookbook/audio-eq-cookbook.html
  164. if (q <= 0.0001) {
  165. q = 0.0001;
  166. }
  167. float Fs = 1;
  168. float w0 = 2 * M_PI * f / Fs;
  169. float c = cosf(w0);
  170. float s = sinf(w0);
  171. float alpha = s / (2 * q);
  172. float A = sqrtf(pow(10, (double)gain / 20.0));
  173. float b0 = 1 + (alpha*A);
  174. float b1 = (-2*c);
  175. float b2 = 1 - (alpha*A);
  176. float a0 = 1 + (alpha/A);
  177. float a1 = b1;
  178. float a2 = 1 - (alpha/A);
  179. coeffs[0] = b0 / a0;
  180. coeffs[1] = b1 / a0;
  181. coeffs[2] = b2 / a0;
  182. coeffs[3] = a1 / a0;
  183. coeffs[4] = a2 / a0;
  184. }
  185. // Generates coefficients for an all pass 180° biquad filter
  186. void generateAllPass180CoEffs(float f, float q)
  187. {
  188. if (q <= 0.0001) {
  189. q = 0.0001;
  190. }
  191. float Fs = 1;
  192. float w0 = 2 * M_PI * f / Fs;
  193. float c = cosf(w0);
  194. float s = sinf(w0);
  195. float alpha = s / (2 * q);
  196. float b0 = 1 - alpha;
  197. float b1 = -2 * c;
  198. float b2 = 1 + alpha;
  199. float a0 = 1 + alpha;
  200. float a1 = -2 * c;
  201. float a2 = 1 - alpha;
  202. coeffs[0] = b0 / a0;
  203. coeffs[1] = b1 / a0;
  204. coeffs[2] = b2 / a0;
  205. coeffs[3] = a1 / a0;
  206. coeffs[4] = a2 / a0;
  207. }
  208. // Generates coefficients for an all pass 360° biquad filter
  209. void generateAllPass360CoEffs(float f, float q)
  210. {
  211. if (q <= 0.0001) {
  212. q = 0.0001;
  213. }
  214. float Fs = 1;
  215. float w0 = 2 * M_PI * f / Fs;
  216. float c = cosf(w0);
  217. float s = sinf(w0);
  218. float alpha = s / (2 * q);
  219. float b0 = 1 - alpha;
  220. float b1 = -2 * c;
  221. float b2 = 1 + alpha;
  222. float a0 = 1 + alpha;
  223. float a1 = -2 * c;
  224. float a2 = 1 - alpha;
  225. coeffs[0] = b0 / a0;
  226. coeffs[1] = b1 / a0;
  227. coeffs[2] = b2 / a0;
  228. coeffs[3] = a1 / a0;
  229. coeffs[4] = a2 / a0;
  230. }
  231. void processSamples(float *input, int numSamples)
  232. {
  233. std::scoped_lock lock(processMutex);
  234. #ifdef ESP_PLATFORM
  235. dsps_biquad_f32_ae32(input, input, numSamples, coeffs, w);
  236. #else
  237. // Apply the set coefficients
  238. for (int i = 0; i < numSamples; i++)
  239. {
  240. float d0 = input[i] - coeffs[3] * w[0] - coeffs[4] * w[1];
  241. input[i] = coeffs[0] * d0 + coeffs[1] * w[0] + coeffs[2] * w[1];
  242. w[1] = w[0];
  243. w[0] = d0;
  244. }
  245. #endif
  246. }
  247. };
  248. #endif