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.

384 lines
8.1KB

  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. T process(T deltaTime, T in) {
  59. T y = out + (in - out) * lambda * deltaTime;
  60. // If no change was made between the old and new output, assume T granularity is too small and snap output to input
  61. out = simd::ifelse(out == y, in, y);
  62. return out;
  63. }
  64. DEPRECATED T process(T in) {
  65. return process(1.f, in);
  66. }
  67. };
  68. typedef TExponentialFilter<> ExponentialFilter;
  69. /** Like ExponentialFilter but jumps immediately to higher values.
  70. */
  71. template <typename T = float>
  72. struct TPeakFilter {
  73. T out = 0.f;
  74. T lambda = 0.f;
  75. void reset() {
  76. out = 0.f;
  77. }
  78. void setLambda(T lambda) {
  79. this->lambda = lambda;
  80. }
  81. T process(T deltaTime, T in) {
  82. T y = out + (in - out) * lambda * deltaTime;
  83. out = simd::fmax(y, in);
  84. return out;
  85. }
  86. /** Use the return value of process() instead. */
  87. DEPRECATED T peak() {
  88. return out;
  89. }
  90. /** Use setLambda() instead. */
  91. DEPRECATED void setRate(T r) {
  92. lambda = 1.f - r;
  93. }
  94. DEPRECATED T process(T x) {
  95. return process(1.f, x);
  96. }
  97. };
  98. typedef TPeakFilter<> PeakFilter;
  99. template <typename T = float>
  100. struct TSlewLimiter {
  101. T out = 0.f;
  102. T rise = 0.f;
  103. T fall = 0.f;
  104. void reset() {
  105. out = 0.f;
  106. }
  107. void setRiseFall(T rise, T fall) {
  108. this->rise = rise;
  109. this->fall = fall;
  110. }
  111. T process(T deltaTime, T in) {
  112. out = simd::clamp(in, out - fall * deltaTime, out + rise * deltaTime);
  113. return out;
  114. }
  115. DEPRECATED T process(T in) {
  116. return process(1.f, in);
  117. }
  118. };
  119. typedef TSlewLimiter<> SlewLimiter;
  120. template <typename T = float>
  121. struct TExponentialSlewLimiter {
  122. T out = 0.f;
  123. T riseLambda = 0.f;
  124. T fallLambda = 0.f;
  125. void reset() {
  126. out = 0.f;
  127. }
  128. void setRiseFall(T riseLambda, T fallLambda) {
  129. this->riseLambda = riseLambda;
  130. this->fallLambda = fallLambda;
  131. }
  132. T process(T deltaTime, T in) {
  133. T lambda = simd::ifelse(in > out, riseLambda, fallLambda);
  134. T y = out + (in - out) * lambda * deltaTime;
  135. // If the change from the old out to the new out is too small for floats, set `in` directly.
  136. out = simd::ifelse(out == y, in, y);
  137. return out;
  138. }
  139. DEPRECATED T process(T in) {
  140. return process(1.f, in);
  141. }
  142. };
  143. typedef TExponentialSlewLimiter<> ExponentialSlewLimiter;
  144. template <typename T = float>
  145. struct TBiquadFilter {
  146. /** input state */
  147. T x[2];
  148. /** output state */
  149. T y[2];
  150. /** transfer function denominator coefficients: a_1, a_2
  151. a_0 is fixed to 1.
  152. */
  153. float a[2];
  154. /** transfer function numerator coefficients: b_0, b_1, b_2 */
  155. float b[3];
  156. enum Type {
  157. LOWPASS_1POLE,
  158. HIGHPASS_1POLE,
  159. LOWPASS,
  160. HIGHPASS,
  161. LOWSHELF,
  162. HIGHSHELF,
  163. BANDPASS,
  164. PEAK,
  165. NOTCH,
  166. NUM_TYPES
  167. };
  168. Type type = LOWPASS;
  169. TBiquadFilter() {
  170. reset();
  171. setParameters(0.f, 0.f, 1.f);
  172. }
  173. void reset() {
  174. std::memset(x, 0, sizeof(x));
  175. std::memset(y, 0, sizeof(y));
  176. }
  177. T process(T in) {
  178. // Advance IIR
  179. T out =
  180. b[0] * in
  181. + b[1] * x[0]
  182. + b[2] * x[1]
  183. - a[0] * y[0]
  184. - a[1] * y[1];
  185. // Push input
  186. x[1] = x[0];
  187. x[0] = in;
  188. // Push output
  189. y[1] = y[0];
  190. y[0] = out;
  191. return out;
  192. }
  193. /** Calculates and sets the biquad transfer function coefficients.
  194. f: normalized frequency (cutoff frequency / sample rate), must be less than 0.5
  195. Q: quality factor
  196. V: gain
  197. */
  198. void setParameters(float f, float Q, float V) {
  199. float K = std::tan(M_PI * f);
  200. switch (type) {
  201. case LOWPASS_1POLE: {
  202. a[0] = -std::exp(-2.f * M_PI * f);
  203. a[1] = 0.f;
  204. b[0] = 1.f + a[0];
  205. b[1] = 0.f;
  206. b[2] = 0.f;
  207. } break;
  208. case HIGHPASS_1POLE: {
  209. a[0] = std::exp(-2.f * M_PI * (0.5f - f));
  210. a[1] = 0.f;
  211. b[0] = 1.f - a[0];
  212. b[1] = 0.f;
  213. b[2] = 0.f;
  214. } break;
  215. case LOWPASS: {
  216. float norm = 1.f / (1.f + K / Q + K * K);
  217. b[0] = K * K * norm;
  218. b[1] = 2.f * b[0];
  219. b[2] = b[0];
  220. a[0] = 2.f * (K * K - 1.f) * norm;
  221. a[1] = (1.f - K / Q + K * K) * norm;
  222. } break;
  223. case HIGHPASS: {
  224. float norm = 1.f / (1.f + K / Q + K * K);
  225. b[0] = norm;
  226. b[1] = -2.f * b[0];
  227. b[2] = b[0];
  228. a[0] = 2.f * (K * K - 1.f) * norm;
  229. a[1] = (1.f - K / Q + K * K) * norm;
  230. } break;
  231. case LOWSHELF: {
  232. float sqrtV = std::sqrt(V);
  233. if (V >= 1.f) {
  234. float norm = 1.f / (1.f + M_SQRT2 * K + K * K);
  235. b[0] = (1.f + M_SQRT2 * sqrtV * K + V * K * K) * norm;
  236. b[1] = 2.f * (V * K * K - 1.f) * norm;
  237. b[2] = (1.f - M_SQRT2 * sqrtV * K + V * K * K) * norm;
  238. a[0] = 2.f * (K * K - 1.f) * norm;
  239. a[1] = (1.f - M_SQRT2 * K + K * K) * norm;
  240. }
  241. else {
  242. float norm = 1.f / (1.f + M_SQRT2 / sqrtV * K + K * K / V);
  243. b[0] = (1.f + M_SQRT2 * K + K * K) * norm;
  244. b[1] = 2.f * (K * K - 1) * norm;
  245. b[2] = (1.f - M_SQRT2 * K + K * K) * norm;
  246. a[0] = 2.f * (K * K / V - 1.f) * norm;
  247. a[1] = (1.f - M_SQRT2 / sqrtV * K + K * K / V) * norm;
  248. }
  249. } break;
  250. case HIGHSHELF: {
  251. float sqrtV = std::sqrt(V);
  252. if (V >= 1.f) {
  253. float norm = 1.f / (1.f + M_SQRT2 * K + K * K);
  254. b[0] = (V + M_SQRT2 * sqrtV * K + K * K) * norm;
  255. b[1] = 2.f * (K * K - V) * norm;
  256. b[2] = (V - M_SQRT2 * sqrtV * K + K * K) * norm;
  257. a[0] = 2.f * (K * K - 1.f) * norm;
  258. a[1] = (1.f - M_SQRT2 * K + K * K) * norm;
  259. }
  260. else {
  261. float norm = 1.f / (1.f / V + M_SQRT2 / sqrtV * K + K * K);
  262. b[0] = (1.f + M_SQRT2 * K + K * K) * norm;
  263. b[1] = 2.f * (K * K - 1.f) * norm;
  264. b[2] = (1.f - M_SQRT2 * K + K * K) * norm;
  265. a[0] = 2.f * (K * K - 1.f / V) * norm;
  266. a[1] = (1.f / V - M_SQRT2 / sqrtV * K + K * K) * norm;
  267. }
  268. } break;
  269. case BANDPASS: {
  270. float norm = 1.f / (1.f + K / Q + K * K);
  271. b[0] = K / Q * norm;
  272. b[1] = 0.f;
  273. b[2] = -b[0];
  274. a[0] = 2.f * (K * K - 1.f) * norm;
  275. a[1] = (1.f - K / Q + K * K) * norm;
  276. } break;
  277. case PEAK: {
  278. if (V >= 1.f) {
  279. float norm = 1.f / (1.f + K / Q + K * K);
  280. b[0] = (1.f + K / Q * V + K * K) * norm;
  281. b[1] = 2.f * (K * K - 1.f) * norm;
  282. b[2] = (1.f - K / Q * V + K * K) * norm;
  283. a[0] = b[1];
  284. a[1] = (1.f - K / Q + K * K) * norm;
  285. }
  286. else {
  287. float norm = 1.f / (1.f + K / Q / V + K * K);
  288. b[0] = (1.f + K / Q + K * K) * norm;
  289. b[1] = 2.f * (K * K - 1.f) * norm;
  290. b[2] = (1.f - K / Q + K * K) * norm;
  291. a[0] = b[1];
  292. a[1] = (1.f - K / Q / V + K * K) * norm;
  293. }
  294. } break;
  295. case NOTCH: {
  296. float norm = 1.f / (1.f + K / Q + K * K);
  297. b[0] = (1.f + K * K) * norm;
  298. b[1] = 2.f * (K * K - 1.f) * norm;
  299. b[2] = b[0];
  300. a[0] = b[1];
  301. a[1] = (1.f - K / Q + K * K) * norm;
  302. } break;
  303. default: break;
  304. }
  305. }
  306. /** Computes the gain of a particular frequency
  307. f: normalized frequency
  308. */
  309. float getFrequencyResponse(float f) {
  310. float br = b[0];
  311. float bi = 0.f;
  312. float ar = 1.f;
  313. float ai = 0.f;
  314. for (int i = 1; i < 3; i++) {
  315. float er = std::cos(2 * M_PI * -i * f);
  316. float ei = std::sin(2 * M_PI * -i * f);
  317. br += b[i] * er;
  318. bi += b[i] * ei;
  319. ar += a[i - 1] * er;
  320. ai += a[i - 1] * ei;
  321. }
  322. // Compute |b / a|
  323. float cr = (br * ar + bi * ai) / (ar * ar + ai * ai);
  324. float ci = (bi * ar - br * ai) / (ar * ar + ai * ai);
  325. return std::hypot(cr, ci);
  326. }
  327. };
  328. typedef TBiquadFilter<> BiquadFilter;
  329. } // namespace dsp
  330. } // namespace rack