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.

381 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 numerator coefficients: b_0, b_1, b_2 */
  151. float b[3];
  152. /** transfer function denominator coefficients: a_1, a_2
  153. a_0 is fixed to 1.
  154. */
  155. float a[2];
  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. TBiquadFilter() {
  169. reset();
  170. setParameters(LOWPASS, 0.f, 0.f, 1.f);
  171. }
  172. void reset() {
  173. std::memset(x, 0, sizeof(x));
  174. std::memset(y, 0, sizeof(y));
  175. }
  176. T process(T in) {
  177. // Advance IIR
  178. T out = b[0] * in + b[1] * x[0] + b[2] * x[1]
  179. - a[0] * y[0] - a[1] * y[1];
  180. // Push input
  181. x[1] = x[0];
  182. x[0] = in;
  183. // Push output
  184. y[1] = y[0];
  185. y[0] = out;
  186. return out;
  187. }
  188. /** Calculates and sets the biquad transfer function coefficients.
  189. f: normalized frequency (cutoff frequency / sample rate), must be less than 0.5
  190. Q: quality factor
  191. V: gain
  192. */
  193. void setParameters(Type type, float f, float Q, float V) {
  194. float K = std::tan(M_PI * f);
  195. switch (type) {
  196. case LOWPASS_1POLE: {
  197. a[0] = -std::exp(-2.f * M_PI * f);
  198. a[1] = 0.f;
  199. b[0] = 1.f + a[0];
  200. b[1] = 0.f;
  201. b[2] = 0.f;
  202. } break;
  203. case HIGHPASS_1POLE: {
  204. a[0] = std::exp(-2.f * M_PI * (0.5f - f));
  205. a[1] = 0.f;
  206. b[0] = 1.f - a[0];
  207. b[1] = 0.f;
  208. b[2] = 0.f;
  209. } break;
  210. case LOWPASS: {
  211. float norm = 1.f / (1.f + K / Q + K * K);
  212. b[0] = K * K * norm;
  213. b[1] = 2.f * b[0];
  214. b[2] = b[0];
  215. a[0] = 2.f * (K * K - 1.f) * norm;
  216. a[1] = (1.f - K / Q + K * K) * norm;
  217. } break;
  218. case HIGHPASS: {
  219. float norm = 1.f / (1.f + K / Q + K * K);
  220. b[0] = norm;
  221. b[1] = -2.f * b[0];
  222. b[2] = b[0];
  223. a[0] = 2.f * (K * K - 1.f) * norm;
  224. a[1] = (1.f - K / Q + K * K) * norm;
  225. } break;
  226. case LOWSHELF: {
  227. float sqrtV = std::sqrt(V);
  228. if (V >= 1.f) {
  229. float norm = 1.f / (1.f + M_SQRT2 * K + K * K);
  230. b[0] = (1.f + M_SQRT2 * sqrtV * K + V * K * K) * norm;
  231. b[1] = 2.f * (V * K * K - 1.f) * norm;
  232. b[2] = (1.f - M_SQRT2 * sqrtV * K + V * K * K) * norm;
  233. a[0] = 2.f * (K * K - 1.f) * norm;
  234. a[1] = (1.f - M_SQRT2 * K + K * K) * norm;
  235. }
  236. else {
  237. float norm = 1.f / (1.f + M_SQRT2 / sqrtV * K + K * K / V);
  238. b[0] = (1.f + M_SQRT2 * K + K * K) * norm;
  239. b[1] = 2.f * (K * K - 1) * norm;
  240. b[2] = (1.f - M_SQRT2 * K + K * K) * norm;
  241. a[0] = 2.f * (K * K / V - 1.f) * norm;
  242. a[1] = (1.f - M_SQRT2 / sqrtV * K + K * K / V) * norm;
  243. }
  244. } break;
  245. case HIGHSHELF: {
  246. float sqrtV = std::sqrt(V);
  247. if (V >= 1.f) {
  248. float norm = 1.f / (1.f + M_SQRT2 * K + K * K);
  249. b[0] = (V + M_SQRT2 * sqrtV * K + K * K) * norm;
  250. b[1] = 2.f * (K * K - V) * norm;
  251. b[2] = (V - M_SQRT2 * sqrtV * K + K * K) * norm;
  252. a[0] = 2.f * (K * K - 1.f) * norm;
  253. a[1] = (1.f - M_SQRT2 * K + K * K) * norm;
  254. }
  255. else {
  256. float norm = 1.f / (1.f / V + M_SQRT2 / sqrtV * K + K * K);
  257. b[0] = (1.f + M_SQRT2 * K + K * K) * norm;
  258. b[1] = 2.f * (K * K - 1.f) * norm;
  259. b[2] = (1.f - M_SQRT2 * K + K * K) * norm;
  260. a[0] = 2.f * (K * K - 1.f / V) * norm;
  261. a[1] = (1.f / V - M_SQRT2 / sqrtV * K + K * K) * norm;
  262. }
  263. } break;
  264. case BANDPASS: {
  265. float norm = 1.f / (1.f + K / Q + K * K);
  266. b[0] = K / Q * norm;
  267. b[1] = 0.f;
  268. b[2] = -b[0];
  269. a[0] = 2.f * (K * K - 1.f) * norm;
  270. a[1] = (1.f - K / Q + K * K) * norm;
  271. } break;
  272. case PEAK: {
  273. if (V >= 1.f) {
  274. float norm = 1.f / (1.f + K / Q + K * K);
  275. b[0] = (1.f + K / Q * V + K * K) * norm;
  276. b[1] = 2.f * (K * K - 1.f) * norm;
  277. b[2] = (1.f - K / Q * V + K * K) * norm;
  278. a[0] = b[1];
  279. a[1] = (1.f - K / Q + K * K) * norm;
  280. }
  281. else {
  282. float norm = 1.f / (1.f + K / Q / V + K * K);
  283. b[0] = (1.f + K / Q + K * K) * norm;
  284. b[1] = 2.f * (K * K - 1.f) * norm;
  285. b[2] = (1.f - K / Q + K * K) * norm;
  286. a[0] = b[1];
  287. a[1] = (1.f - K / Q / V + K * K) * norm;
  288. }
  289. } break;
  290. case NOTCH: {
  291. float norm = 1.f / (1.f + K / Q + K * K);
  292. b[0] = (1.f + K * K) * norm;
  293. b[1] = 2.f * (K * K - 1.f) * norm;
  294. b[2] = b[0];
  295. a[0] = b[1];
  296. a[1] = (1.f - K / Q + K * K) * norm;
  297. } break;
  298. default: break;
  299. }
  300. }
  301. void copyParameters(const TBiquadFilter<T>& from) {
  302. b[0] = from.b[0];
  303. b[1] = from.b[1];
  304. b[2] = from.b[2];
  305. a[0] = from.a[0];
  306. a[1] = from.a[1];
  307. }
  308. /** Computes the gain of a particular frequency
  309. f: normalized frequency
  310. */
  311. float getFrequencyResponse(float f) {
  312. // Compute sum(a_k e^(-i k f))
  313. std::complex<float> bsum = b[0];
  314. std::complex<float> asum = 1.f;
  315. for (int i = 1; i < 3; i++) {
  316. float p = 2 * M_PI * -i * f;
  317. std::complex<float> e(std::cos(p), std::sin(p));
  318. bsum += b[i] * e;
  319. asum += a[i - 1] * e;
  320. }
  321. return std::abs(bsum / asum);
  322. }
  323. };
  324. typedef TBiquadFilter<> BiquadFilter;
  325. } // namespace dsp
  326. } // namespace rack