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.

filter.hpp 8.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. #pragma once
  2. #include <dsp/common.hpp>
  3. namespace rack {
  4. namespace dsp {
  5. /** The simplest possible analog filter using an Euler solver.
  6. https://en.wikipedia.org/wiki/RC_circuit
  7. Use two RC filters in series for a bandpass filter.
  8. */
  9. template <typename T = float>
  10. struct TRCFilter {
  11. T c = 0.f;
  12. T xstate[1];
  13. T ystate[1];
  14. TRCFilter() {
  15. reset();
  16. }
  17. void reset() {
  18. xstate[0] = 0.f;
  19. ystate[0] = 0.f;
  20. }
  21. /** Sets the cutoff angular frequency in radians.
  22. */
  23. void setCutoff(T r) {
  24. c = 2.f / r;
  25. }
  26. /** Sets the cutoff frequency.
  27. `f` is the ratio between the cutoff frequency and sample rate, i.e. f = f_c / f_s
  28. */
  29. void setCutoffFreq(T f) {
  30. setCutoff(2.f * M_PI * f);
  31. }
  32. void process(T x) {
  33. T y = (x + xstate[0] - ystate[0] * (1 - c)) / (1 + c);
  34. xstate[0] = x;
  35. ystate[0] = y;
  36. }
  37. T lowpass() {
  38. return ystate[0];
  39. }
  40. T highpass() {
  41. return xstate[0] - ystate[0];
  42. }
  43. };
  44. typedef TRCFilter<> RCFilter;
  45. /** Applies exponential smoothing to a signal with the ODE
  46. \f$ \frac{dy}{dt} = x \lambda \f$.
  47. */
  48. template <typename T = float>
  49. struct TExponentialFilter {
  50. T out = 0.f;
  51. T lambda = 0.f;
  52. void reset() {
  53. out = 0.f;
  54. }
  55. void setLambda(T lambda) {
  56. this->lambda = lambda;
  57. }
  58. void setTau(T tau) {
  59. this->lambda = 1 / tau;
  60. }
  61. T process(T deltaTime, T in) {
  62. T y = out + (in - out) * lambda * deltaTime;
  63. // If no change was made between the old and new output, assume T granularity is too small and snap output to input
  64. out = simd::ifelse(out == y, in, y);
  65. return out;
  66. }
  67. DEPRECATED T process(T in) {
  68. return process(1.f, in);
  69. }
  70. };
  71. typedef TExponentialFilter<> ExponentialFilter;
  72. /** Like ExponentialFilter but jumps immediately to higher values.
  73. */
  74. template <typename T = float>
  75. struct TPeakFilter {
  76. T out = 0.f;
  77. T lambda = 0.f;
  78. void reset() {
  79. out = 0.f;
  80. }
  81. void setLambda(T lambda) {
  82. this->lambda = lambda;
  83. }
  84. void setTau(T tau) {
  85. this->lambda = 1 / tau;
  86. }
  87. T process(T deltaTime, T in) {
  88. T y = out + (in - out) * lambda * deltaTime;
  89. out = simd::fmax(y, in);
  90. return out;
  91. }
  92. /** Use the return value of process() instead. */
  93. DEPRECATED T peak() {
  94. return out;
  95. }
  96. /** Use setLambda() instead. */
  97. DEPRECATED void setRate(T r) {
  98. lambda = 1.f - r;
  99. }
  100. DEPRECATED T process(T x) {
  101. return process(1.f, x);
  102. }
  103. };
  104. typedef TPeakFilter<> PeakFilter;
  105. template <typename T = float>
  106. struct TSlewLimiter {
  107. T out = 0.f;
  108. T rise = 0.f;
  109. T fall = 0.f;
  110. void reset() {
  111. out = 0.f;
  112. }
  113. void setRiseFall(T rise, T fall) {
  114. this->rise = rise;
  115. this->fall = fall;
  116. }
  117. T process(T deltaTime, T in) {
  118. out = simd::clamp(in, out - fall * deltaTime, out + rise * deltaTime);
  119. return out;
  120. }
  121. DEPRECATED T process(T in) {
  122. return process(1.f, in);
  123. }
  124. };
  125. typedef TSlewLimiter<> SlewLimiter;
  126. template <typename T = float>
  127. struct TExponentialSlewLimiter {
  128. T out = 0.f;
  129. T riseLambda = 0.f;
  130. T fallLambda = 0.f;
  131. void reset() {
  132. out = 0.f;
  133. }
  134. void setRiseFall(T riseLambda, T fallLambda) {
  135. this->riseLambda = riseLambda;
  136. this->fallLambda = fallLambda;
  137. }
  138. T process(T deltaTime, T in) {
  139. T lambda = simd::ifelse(in > out, riseLambda, fallLambda);
  140. T y = out + (in - out) * lambda * deltaTime;
  141. // If the change from the old out to the new out is too small for floats, set `in` directly.
  142. out = simd::ifelse(out == y, in, y);
  143. return out;
  144. }
  145. DEPRECATED T process(T in) {
  146. return process(1.f, in);
  147. }
  148. };
  149. typedef TExponentialSlewLimiter<> ExponentialSlewLimiter;
  150. template <typename T = float>
  151. struct TBiquadFilter {
  152. /** input state */
  153. T x[2];
  154. /** output state */
  155. T y[2];
  156. /** transfer function numerator coefficients: b_0, b_1, b_2 */
  157. float b[3];
  158. /** transfer function denominator coefficients: a_1, a_2
  159. a_0 is fixed to 1.
  160. */
  161. float a[2];
  162. enum Type {
  163. LOWPASS_1POLE,
  164. HIGHPASS_1POLE,
  165. LOWPASS,
  166. HIGHPASS,
  167. LOWSHELF,
  168. HIGHSHELF,
  169. BANDPASS,
  170. PEAK,
  171. NOTCH,
  172. NUM_TYPES
  173. };
  174. TBiquadFilter() {
  175. reset();
  176. setParameters(LOWPASS, 0.f, 0.f, 1.f);
  177. }
  178. void reset() {
  179. std::memset(x, 0, sizeof(x));
  180. std::memset(y, 0, sizeof(y));
  181. }
  182. T process(T in) {
  183. // Advance IIR
  184. T out = b[0] * in + b[1] * x[0] + b[2] * x[1]
  185. - a[0] * y[0] - a[1] * y[1];
  186. // Push input
  187. x[1] = x[0];
  188. x[0] = in;
  189. // Push output
  190. y[1] = y[0];
  191. y[0] = out;
  192. return out;
  193. }
  194. /** Calculates and sets the biquad transfer function coefficients.
  195. f: normalized frequency (cutoff frequency / sample rate), must be less than 0.5
  196. Q: quality factor
  197. V: gain
  198. */
  199. void setParameters(Type type, float f, float Q, float V) {
  200. float K = std::tan(M_PI * f);
  201. switch (type) {
  202. case LOWPASS_1POLE: {
  203. a[0] = -std::exp(-2.f * M_PI * f);
  204. a[1] = 0.f;
  205. b[0] = 1.f + a[0];
  206. b[1] = 0.f;
  207. b[2] = 0.f;
  208. } break;
  209. case HIGHPASS_1POLE: {
  210. a[0] = std::exp(-2.f * M_PI * (0.5f - f));
  211. a[1] = 0.f;
  212. b[0] = 1.f - a[0];
  213. b[1] = 0.f;
  214. b[2] = 0.f;
  215. } break;
  216. case LOWPASS: {
  217. float norm = 1.f / (1.f + K / Q + K * K);
  218. b[0] = K * K * norm;
  219. b[1] = 2.f * b[0];
  220. b[2] = b[0];
  221. a[0] = 2.f * (K * K - 1.f) * norm;
  222. a[1] = (1.f - K / Q + K * K) * norm;
  223. } break;
  224. case HIGHPASS: {
  225. float norm = 1.f / (1.f + K / Q + K * K);
  226. b[0] = norm;
  227. b[1] = -2.f * b[0];
  228. b[2] = b[0];
  229. a[0] = 2.f * (K * K - 1.f) * norm;
  230. a[1] = (1.f - K / Q + K * K) * norm;
  231. } break;
  232. case LOWSHELF: {
  233. float sqrtV = std::sqrt(V);
  234. if (V >= 1.f) {
  235. float norm = 1.f / (1.f + M_SQRT2 * K + K * K);
  236. b[0] = (1.f + M_SQRT2 * sqrtV * K + V * K * K) * norm;
  237. b[1] = 2.f * (V * K * K - 1.f) * norm;
  238. b[2] = (1.f - M_SQRT2 * sqrtV * K + V * K * K) * norm;
  239. a[0] = 2.f * (K * K - 1.f) * norm;
  240. a[1] = (1.f - M_SQRT2 * K + K * K) * norm;
  241. }
  242. else {
  243. float norm = 1.f / (1.f + M_SQRT2 / sqrtV * K + K * K / V);
  244. b[0] = (1.f + M_SQRT2 * K + K * K) * norm;
  245. b[1] = 2.f * (K * K - 1) * norm;
  246. b[2] = (1.f - M_SQRT2 * K + K * K) * norm;
  247. a[0] = 2.f * (K * K / V - 1.f) * norm;
  248. a[1] = (1.f - M_SQRT2 / sqrtV * K + K * K / V) * norm;
  249. }
  250. } break;
  251. case HIGHSHELF: {
  252. float sqrtV = std::sqrt(V);
  253. if (V >= 1.f) {
  254. float norm = 1.f / (1.f + M_SQRT2 * K + K * K);
  255. b[0] = (V + M_SQRT2 * sqrtV * K + K * K) * norm;
  256. b[1] = 2.f * (K * K - V) * norm;
  257. b[2] = (V - M_SQRT2 * sqrtV * K + K * K) * norm;
  258. a[0] = 2.f * (K * K - 1.f) * norm;
  259. a[1] = (1.f - M_SQRT2 * K + K * K) * norm;
  260. }
  261. else {
  262. float norm = 1.f / (1.f / V + M_SQRT2 / sqrtV * K + K * K);
  263. b[0] = (1.f + M_SQRT2 * K + K * K) * norm;
  264. b[1] = 2.f * (K * K - 1.f) * norm;
  265. b[2] = (1.f - M_SQRT2 * K + K * K) * norm;
  266. a[0] = 2.f * (K * K - 1.f / V) * norm;
  267. a[1] = (1.f / V - M_SQRT2 / sqrtV * K + K * K) * norm;
  268. }
  269. } break;
  270. case BANDPASS: {
  271. float norm = 1.f / (1.f + K / Q + K * K);
  272. b[0] = K / Q * norm;
  273. b[1] = 0.f;
  274. b[2] = -b[0];
  275. a[0] = 2.f * (K * K - 1.f) * norm;
  276. a[1] = (1.f - K / Q + K * K) * norm;
  277. } break;
  278. case PEAK: {
  279. if (V >= 1.f) {
  280. float norm = 1.f / (1.f + K / Q + K * K);
  281. b[0] = (1.f + K / Q * V + K * K) * norm;
  282. b[1] = 2.f * (K * K - 1.f) * norm;
  283. b[2] = (1.f - K / Q * V + K * K) * norm;
  284. a[0] = b[1];
  285. a[1] = (1.f - K / Q + K * K) * norm;
  286. }
  287. else {
  288. float norm = 1.f / (1.f + K / Q / V + K * K);
  289. b[0] = (1.f + K / Q + K * K) * norm;
  290. b[1] = 2.f * (K * K - 1.f) * norm;
  291. b[2] = (1.f - K / Q + K * K) * norm;
  292. a[0] = b[1];
  293. a[1] = (1.f - K / Q / V + K * K) * norm;
  294. }
  295. } break;
  296. case NOTCH: {
  297. float norm = 1.f / (1.f + K / Q + K * K);
  298. b[0] = (1.f + K * K) * norm;
  299. b[1] = 2.f * (K * K - 1.f) * norm;
  300. b[2] = b[0];
  301. a[0] = b[1];
  302. a[1] = (1.f - K / Q + K * K) * norm;
  303. } break;
  304. default: break;
  305. }
  306. }
  307. void copyParameters(const TBiquadFilter<T>& from) {
  308. b[0] = from.b[0];
  309. b[1] = from.b[1];
  310. b[2] = from.b[2];
  311. a[0] = from.a[0];
  312. a[1] = from.a[1];
  313. }
  314. /** Computes the gain of a particular frequency
  315. f: normalized frequency
  316. */
  317. float getFrequencyResponse(float f) {
  318. // Compute sum(a_k e^(-i k f))
  319. std::complex<float> bsum = b[0];
  320. std::complex<float> asum = 1.f;
  321. for (int i = 1; i < 3; i++) {
  322. float p = 2 * M_PI * -i * f;
  323. std::complex<float> e(std::cos(p), std::sin(p));
  324. bsum += b[i] * e;
  325. asum += a[i - 1] * e;
  326. }
  327. return std::abs(bsum / asum);
  328. }
  329. };
  330. typedef TBiquadFilter<> BiquadFilter;
  331. } // namespace dsp
  332. } // namespace rack