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.

441 lines
10KB

  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. /** Sets \f$ \lambda = 1 / \tau \f$. */
  59. void setTau(T tau) {
  60. this->lambda = 1 / tau;
  61. }
  62. T process(T deltaTime, T in) {
  63. T y = out + (in - out) * lambda * deltaTime;
  64. // If no change was made between the old and new output, assume T granularity is too small and snap output to input
  65. out = simd::ifelse(out == y, in, y);
  66. return out;
  67. }
  68. DEPRECATED T process(T in) {
  69. return process(1.f, in);
  70. }
  71. };
  72. typedef TExponentialFilter<> ExponentialFilter;
  73. /** Like ExponentialFilter but jumps immediately to higher values.
  74. */
  75. template <typename T = float>
  76. struct TPeakFilter {
  77. T out = 0.f;
  78. T lambda = 0.f;
  79. void reset() {
  80. out = 0.f;
  81. }
  82. void setLambda(T lambda) {
  83. this->lambda = lambda;
  84. }
  85. void setTau(T tau) {
  86. this->lambda = 1 / tau;
  87. }
  88. T process(T deltaTime, T in) {
  89. T y = out + (in - out) * lambda * deltaTime;
  90. out = simd::fmax(y, in);
  91. return out;
  92. }
  93. /** Use the return value of process() instead. */
  94. DEPRECATED T peak() {
  95. return out;
  96. }
  97. /** Use setLambda() instead. */
  98. DEPRECATED void setRate(T r) {
  99. lambda = 1.f - r;
  100. }
  101. DEPRECATED T process(T x) {
  102. return process(1.f, x);
  103. }
  104. };
  105. typedef TPeakFilter<> PeakFilter;
  106. /** Limits the derivative of the output by a rise and fall speed, in units/s. */
  107. template <typename T = float>
  108. struct TSlewLimiter {
  109. T out = 0.f;
  110. T rise = 0.f;
  111. T fall = 0.f;
  112. void reset() {
  113. out = 0.f;
  114. }
  115. void setRiseFall(T rise, T fall) {
  116. this->rise = rise;
  117. this->fall = fall;
  118. }
  119. T process(T deltaTime, T in) {
  120. out = simd::clamp(in, out - fall * deltaTime, out + rise * deltaTime);
  121. return out;
  122. }
  123. DEPRECATED T process(T in) {
  124. return process(1.f, in);
  125. }
  126. };
  127. typedef TSlewLimiter<> SlewLimiter;
  128. /** Behaves like ExponentialFilter but with different lambas when the RHS of the ODE is positive or negative. */
  129. template <typename T = float>
  130. struct TExponentialSlewLimiter {
  131. T out = 0.f;
  132. T riseLambda = 0.f;
  133. T fallLambda = 0.f;
  134. void reset() {
  135. out = 0.f;
  136. }
  137. void setRiseFall(T riseLambda, T fallLambda) {
  138. this->riseLambda = riseLambda;
  139. this->fallLambda = fallLambda;
  140. }
  141. void setRiseFallTau(T riseTau, T fallTau) {
  142. this->riseLambda = 1 / riseTau;
  143. this->fallLambda = 1 / fallTau;
  144. }
  145. T process(T deltaTime, T in) {
  146. T lambda = simd::ifelse(in > out, riseLambda, fallLambda);
  147. T y = out + (in - out) * lambda * deltaTime;
  148. // If the change from the old out to the new out is too small for floats, set `in` directly.
  149. out = simd::ifelse(out == y, in, y);
  150. return out;
  151. }
  152. DEPRECATED T process(T in) {
  153. return process(1.f, in);
  154. }
  155. };
  156. typedef TExponentialSlewLimiter<> ExponentialSlewLimiter;
  157. /** Digital IIR filter processor.
  158. https://en.wikipedia.org/wiki/Infinite_impulse_response
  159. */
  160. template <int B_ORDER, int A_ORDER, typename T = float>
  161. struct IIRFilter {
  162. /** transfer function numerator coefficients: b_0, b_1, etc.
  163. */
  164. T b[B_ORDER] = {};
  165. /** transfer function denominator coefficients: a_1, a_2, etc.
  166. a_0 is fixed to 1 and omitted from the `a` array, so its indices are shifted down by 1.
  167. */
  168. T a[A_ORDER - 1] = {};
  169. /** input state
  170. x[0] = x_{n-1}
  171. x[1] = x_{n-2}
  172. etc.
  173. */
  174. T x[B_ORDER - 1];
  175. /** output state */
  176. T y[A_ORDER - 1];
  177. IIRFilter() {
  178. reset();
  179. }
  180. void reset() {
  181. for (int i = 1; i < B_ORDER; i++) {
  182. x[i - 1] = 0.f;
  183. }
  184. for (int i = 1; i < A_ORDER; i++) {
  185. y[i - 1] = 0.f;
  186. }
  187. }
  188. void setCoefficients(const T* b, const T* a) {
  189. for (int i = 0; i < B_ORDER; i++) {
  190. this->b[i] = b[i];
  191. }
  192. for (int i = 1; i < A_ORDER; i++) {
  193. this->a[i - 1] = a[i - 1];
  194. }
  195. }
  196. T process(T in) {
  197. T out = 0.f;
  198. // Add x state
  199. if (0 < B_ORDER) {
  200. out = b[0] * in;
  201. }
  202. for (int i = 1; i < B_ORDER; i++) {
  203. out += b[i] * x[i - 1];
  204. }
  205. // Subtract y state
  206. for (int i = 1; i < A_ORDER; i++) {
  207. out -= a[i - 1] * y[i - 1];
  208. }
  209. // Shift x state
  210. for (int i = B_ORDER - 1; i >= 2; i--) {
  211. x[i - 1] = x[i - 2];
  212. }
  213. x[0] = in;
  214. // Shift y state
  215. for (int i = A_ORDER - 1; i >= 2; i--) {
  216. y[i - 1] = y[i - 2];
  217. }
  218. y[0] = out;
  219. return out;
  220. }
  221. /** Computes the complex transfer function $H(s)$ at a particular frequency
  222. s: normalized angular frequency equal to $2 \pi f / f_{sr}$ ($\pi$ is the Nyquist frequency)
  223. */
  224. std::complex<T> getTransferFunction(T s) {
  225. // Compute sum(a_k z^-k) / sum(b_k z^-k) where z = e^(i s)
  226. std::complex<T> bSum(b[0], 0);
  227. std::complex<T> aSum(1, 0);
  228. for (int i = 1; i < std::max(B_ORDER, A_ORDER); i++) {
  229. T p = -i * s;
  230. std::complex<T> z(simd::cos(p), simd::sin(p));
  231. if (i < B_ORDER)
  232. bSum += b[i] * z;
  233. if (i < A_ORDER)
  234. aSum += a[i - 1] * z;
  235. }
  236. return bSum / aSum;
  237. }
  238. T getFrequencyResponse(T f) {
  239. // T hReal, hImag;
  240. // getTransferFunction(2 * M_PI * f, &hReal, &hImag);
  241. // return simd::hypot(hReal, hImag);
  242. return simd::abs(getTransferFunction(2 * M_PI * f));
  243. }
  244. T getFrequencyPhase(T f) {
  245. return simd::arg(getTransferFunction(2 * M_PI * f));
  246. }
  247. };
  248. template <typename T = float>
  249. struct TBiquadFilter : IIRFilter<3, 3, T> {
  250. enum Type {
  251. LOWPASS_1POLE,
  252. HIGHPASS_1POLE,
  253. LOWPASS,
  254. HIGHPASS,
  255. LOWSHELF,
  256. HIGHSHELF,
  257. BANDPASS,
  258. PEAK,
  259. NOTCH,
  260. NUM_TYPES
  261. };
  262. TBiquadFilter() {
  263. setParameters(LOWPASS, 0.f, 0.f, 1.f);
  264. }
  265. /** Calculates and sets the biquad transfer function coefficients.
  266. f: normalized frequency (cutoff frequency / sample rate), must be less than 0.5
  267. Q: quality factor
  268. V: gain
  269. */
  270. void setParameters(Type type, float f, float Q, float V) {
  271. float K = std::tan(M_PI * f);
  272. switch (type) {
  273. case LOWPASS_1POLE: {
  274. this->a[0] = -std::exp(-2.f * M_PI * f);
  275. this->a[1] = 0.f;
  276. this->b[0] = 1.f + this->a[0];
  277. this->b[1] = 0.f;
  278. this->b[2] = 0.f;
  279. } break;
  280. case HIGHPASS_1POLE: {
  281. this->a[0] = std::exp(-2.f * M_PI * (0.5f - f));
  282. this->a[1] = 0.f;
  283. this->b[0] = 1.f - this->a[0];
  284. this->b[1] = 0.f;
  285. this->b[2] = 0.f;
  286. } break;
  287. case LOWPASS: {
  288. float norm = 1.f / (1.f + K / Q + K * K);
  289. this->b[0] = K * K * norm;
  290. this->b[1] = 2.f * this->b[0];
  291. this->b[2] = this->b[0];
  292. this->a[0] = 2.f * (K * K - 1.f) * norm;
  293. this->a[1] = (1.f - K / Q + K * K) * norm;
  294. } break;
  295. case HIGHPASS: {
  296. float norm = 1.f / (1.f + K / Q + K * K);
  297. this->b[0] = norm;
  298. this->b[1] = -2.f * this->b[0];
  299. this->b[2] = this->b[0];
  300. this->a[0] = 2.f * (K * K - 1.f) * norm;
  301. this->a[1] = (1.f - K / Q + K * K) * norm;
  302. } break;
  303. case LOWSHELF: {
  304. float sqrtV = std::sqrt(V);
  305. if (V >= 1.f) {
  306. float norm = 1.f / (1.f + M_SQRT2 * K + K * K);
  307. this->b[0] = (1.f + M_SQRT2 * sqrtV * K + V * K * K) * norm;
  308. this->b[1] = 2.f * (V * K * K - 1.f) * norm;
  309. this->b[2] = (1.f - M_SQRT2 * sqrtV * K + V * K * K) * norm;
  310. this->a[0] = 2.f * (K * K - 1.f) * norm;
  311. this->a[1] = (1.f - M_SQRT2 * K + K * K) * norm;
  312. }
  313. else {
  314. float norm = 1.f / (1.f + M_SQRT2 / sqrtV * K + K * K / V);
  315. this->b[0] = (1.f + M_SQRT2 * K + K * K) * norm;
  316. this->b[1] = 2.f * (K * K - 1) * norm;
  317. this->b[2] = (1.f - M_SQRT2 * K + K * K) * norm;
  318. this->a[0] = 2.f * (K * K / V - 1.f) * norm;
  319. this->a[1] = (1.f - M_SQRT2 / sqrtV * K + K * K / V) * norm;
  320. }
  321. } break;
  322. case HIGHSHELF: {
  323. float sqrtV = std::sqrt(V);
  324. if (V >= 1.f) {
  325. float norm = 1.f / (1.f + M_SQRT2 * K + K * K);
  326. this->b[0] = (V + M_SQRT2 * sqrtV * K + K * K) * norm;
  327. this->b[1] = 2.f * (K * K - V) * norm;
  328. this->b[2] = (V - M_SQRT2 * sqrtV * K + K * K) * norm;
  329. this->a[0] = 2.f * (K * K - 1.f) * norm;
  330. this->a[1] = (1.f - M_SQRT2 * K + K * K) * norm;
  331. }
  332. else {
  333. float norm = 1.f / (1.f / V + M_SQRT2 / sqrtV * K + K * K);
  334. this->b[0] = (1.f + M_SQRT2 * K + K * K) * norm;
  335. this->b[1] = 2.f * (K * K - 1.f) * norm;
  336. this->b[2] = (1.f - M_SQRT2 * K + K * K) * norm;
  337. this->a[0] = 2.f * (K * K - 1.f / V) * norm;
  338. this->a[1] = (1.f / V - M_SQRT2 / sqrtV * K + K * K) * norm;
  339. }
  340. } break;
  341. case BANDPASS: {
  342. float norm = 1.f / (1.f + K / Q + K * K);
  343. this->b[0] = K / Q * norm;
  344. this->b[1] = 0.f;
  345. this->b[2] = -this->b[0];
  346. this->a[0] = 2.f * (K * K - 1.f) * norm;
  347. this->a[1] = (1.f - K / Q + K * K) * norm;
  348. } break;
  349. case PEAK: {
  350. if (V >= 1.f) {
  351. float norm = 1.f / (1.f + K / Q + K * K);
  352. this->b[0] = (1.f + K / Q * V + K * K) * norm;
  353. this->b[1] = 2.f * (K * K - 1.f) * norm;
  354. this->b[2] = (1.f - K / Q * V + K * K) * norm;
  355. this->a[0] = this->b[1];
  356. this->a[1] = (1.f - K / Q + K * K) * norm;
  357. }
  358. else {
  359. float norm = 1.f / (1.f + K / Q / V + K * K);
  360. this->b[0] = (1.f + K / Q + K * K) * norm;
  361. this->b[1] = 2.f * (K * K - 1.f) * norm;
  362. this->b[2] = (1.f - K / Q + K * K) * norm;
  363. this->a[0] = this->b[1];
  364. this->a[1] = (1.f - K / Q / V + K * K) * norm;
  365. }
  366. } break;
  367. case NOTCH: {
  368. float norm = 1.f / (1.f + K / Q + K * K);
  369. this->b[0] = (1.f + K * K) * norm;
  370. this->b[1] = 2.f * (K * K - 1.f) * norm;
  371. this->b[2] = this->b[0];
  372. this->a[0] = this->b[1];
  373. this->a[1] = (1.f - K / Q + K * K) * norm;
  374. } break;
  375. default: break;
  376. }
  377. }
  378. };
  379. typedef TBiquadFilter<> BiquadFilter;
  380. } // namespace dsp
  381. } // namespace rack