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.

434 lines
9.7KB

  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. /** Digital IIR filter processor.
  151. https://en.wikipedia.org/wiki/Infinite_impulse_response
  152. */
  153. template <int B_ORDER, int A_ORDER, typename T = float>
  154. struct IIRFilter {
  155. /** transfer function numerator coefficients: b_0, b_1, etc.
  156. */
  157. T b[B_ORDER] = {};
  158. /** transfer function denominator coefficients: a_1, a_2, etc.
  159. a_0 is fixed to 1 and omitted from the `a` array, so its indices are shifted down by 1.
  160. */
  161. T a[A_ORDER - 1] = {};
  162. /** input state
  163. x[0] = x_{n-1}
  164. x[1] = x_{n-2}
  165. etc.
  166. */
  167. T x[B_ORDER - 1];
  168. /** output state */
  169. T y[A_ORDER - 1];
  170. IIRFilter() {
  171. reset();
  172. }
  173. void reset() {
  174. for (int i = 1; i < B_ORDER; i++) {
  175. x[i - 1] = 0.f;
  176. }
  177. for (int i = 1; i < A_ORDER; i++) {
  178. y[i - 1] = 0.f;
  179. }
  180. }
  181. void setCoefficients(const T* b, const T* a) {
  182. for (int i = 0; i < B_ORDER; i++) {
  183. this->b[i] = b[i];
  184. }
  185. for (int i = 1; i < A_ORDER; i++) {
  186. this->a[i - 1] = a[i - 1];
  187. }
  188. }
  189. T process(T in) {
  190. T out = 0.f;
  191. // Add x state
  192. if (0 < B_ORDER) {
  193. out = b[0] * in;
  194. }
  195. for (int i = 1; i < B_ORDER; i++) {
  196. out += b[i] * x[i - 1];
  197. }
  198. // Subtract y state
  199. for (int i = 1; i < A_ORDER; i++) {
  200. out -= a[i - 1] * y[i - 1];
  201. }
  202. // Shift x state
  203. for (int i = B_ORDER - 1; i >= 2; i--) {
  204. x[i - 1] = x[i - 2];
  205. }
  206. x[0] = in;
  207. // Shift y state
  208. for (int i = A_ORDER - 1; i >= 2; i--) {
  209. y[i - 1] = y[i - 2];
  210. }
  211. y[0] = out;
  212. return out;
  213. }
  214. /** Computes the complex transfer function $H(s)$ at a particular frequency
  215. s: normalized angular frequency equal to $2 \pi f / f_{sr}$ ($\pi$ is the Nyquist frequency)
  216. */
  217. std::complex<T> getTransferFunction(T s) {
  218. // Compute sum(a_k z^-k) / sum(b_k z^-k) where z = e^(i s)
  219. std::complex<T> bSum(b[0], 0);
  220. std::complex<T> aSum(1, 0);
  221. for (int i = 1; i < std::max(B_ORDER, A_ORDER); i++) {
  222. T p = -i * s;
  223. std::complex<T> z(simd::cos(p), simd::sin(p));
  224. if (i < B_ORDER)
  225. bSum += b[i] * z;
  226. if (i < A_ORDER)
  227. aSum += a[i - 1] * z;
  228. }
  229. return bSum / aSum;
  230. }
  231. T getFrequencyResponse(T f) {
  232. // T hReal, hImag;
  233. // getTransferFunction(2 * M_PI * f, &hReal, &hImag);
  234. // return simd::hypot(hReal, hImag);
  235. return simd::abs(getTransferFunction(2 * M_PI * f));
  236. }
  237. T getFrequencyPhase(T f) {
  238. return simd::arg(getTransferFunction(2 * M_PI * f));
  239. }
  240. };
  241. template <typename T = float>
  242. struct TBiquadFilter : IIRFilter<3, 3, T> {
  243. enum Type {
  244. LOWPASS_1POLE,
  245. HIGHPASS_1POLE,
  246. LOWPASS,
  247. HIGHPASS,
  248. LOWSHELF,
  249. HIGHSHELF,
  250. BANDPASS,
  251. PEAK,
  252. NOTCH,
  253. NUM_TYPES
  254. };
  255. TBiquadFilter() {
  256. setParameters(LOWPASS, 0.f, 0.f, 1.f);
  257. }
  258. /** Calculates and sets the biquad transfer function coefficients.
  259. f: normalized frequency (cutoff frequency / sample rate), must be less than 0.5
  260. Q: quality factor
  261. V: gain
  262. */
  263. void setParameters(Type type, float f, float Q, float V) {
  264. float K = std::tan(M_PI * f);
  265. switch (type) {
  266. case LOWPASS_1POLE: {
  267. this->a[0] = -std::exp(-2.f * M_PI * f);
  268. this->a[1] = 0.f;
  269. this->b[0] = 1.f + this->a[0];
  270. this->b[1] = 0.f;
  271. this->b[2] = 0.f;
  272. } break;
  273. case HIGHPASS_1POLE: {
  274. this->a[0] = std::exp(-2.f * M_PI * (0.5f - 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 LOWPASS: {
  281. float norm = 1.f / (1.f + K / Q + K * K);
  282. this->b[0] = K * K * norm;
  283. this->b[1] = 2.f * this->b[0];
  284. this->b[2] = this->b[0];
  285. this->a[0] = 2.f * (K * K - 1.f) * norm;
  286. this->a[1] = (1.f - K / Q + K * K) * norm;
  287. } break;
  288. case HIGHPASS: {
  289. float norm = 1.f / (1.f + K / Q + K * K);
  290. this->b[0] = norm;
  291. this->b[1] = -2.f * this->b[0];
  292. this->b[2] = this->b[0];
  293. this->a[0] = 2.f * (K * K - 1.f) * norm;
  294. this->a[1] = (1.f - K / Q + K * K) * norm;
  295. } break;
  296. case LOWSHELF: {
  297. float sqrtV = std::sqrt(V);
  298. if (V >= 1.f) {
  299. float norm = 1.f / (1.f + M_SQRT2 * K + K * K);
  300. this->b[0] = (1.f + M_SQRT2 * sqrtV * K + V * K * K) * norm;
  301. this->b[1] = 2.f * (V * K * K - 1.f) * norm;
  302. this->b[2] = (1.f - M_SQRT2 * sqrtV * K + V * K * K) * norm;
  303. this->a[0] = 2.f * (K * K - 1.f) * norm;
  304. this->a[1] = (1.f - M_SQRT2 * K + K * K) * norm;
  305. }
  306. else {
  307. float norm = 1.f / (1.f + M_SQRT2 / sqrtV * K + K * K / V);
  308. this->b[0] = (1.f + M_SQRT2 * K + K * K) * norm;
  309. this->b[1] = 2.f * (K * K - 1) * norm;
  310. this->b[2] = (1.f - M_SQRT2 * K + K * K) * norm;
  311. this->a[0] = 2.f * (K * K / V - 1.f) * norm;
  312. this->a[1] = (1.f - M_SQRT2 / sqrtV * K + K * K / V) * norm;
  313. }
  314. } break;
  315. case HIGHSHELF: {
  316. float sqrtV = std::sqrt(V);
  317. if (V >= 1.f) {
  318. float norm = 1.f / (1.f + M_SQRT2 * K + K * K);
  319. this->b[0] = (V + M_SQRT2 * sqrtV * K + K * K) * norm;
  320. this->b[1] = 2.f * (K * K - V) * norm;
  321. this->b[2] = (V - M_SQRT2 * sqrtV * K + K * K) * norm;
  322. this->a[0] = 2.f * (K * K - 1.f) * norm;
  323. this->a[1] = (1.f - M_SQRT2 * K + K * K) * norm;
  324. }
  325. else {
  326. float norm = 1.f / (1.f / V + M_SQRT2 / sqrtV * K + K * K);
  327. this->b[0] = (1.f + M_SQRT2 * K + K * K) * norm;
  328. this->b[1] = 2.f * (K * K - 1.f) * norm;
  329. this->b[2] = (1.f - M_SQRT2 * K + K * K) * norm;
  330. this->a[0] = 2.f * (K * K - 1.f / V) * norm;
  331. this->a[1] = (1.f / V - M_SQRT2 / sqrtV * K + K * K) * norm;
  332. }
  333. } break;
  334. case BANDPASS: {
  335. float norm = 1.f / (1.f + K / Q + K * K);
  336. this->b[0] = K / Q * norm;
  337. this->b[1] = 0.f;
  338. this->b[2] = -this->b[0];
  339. this->a[0] = 2.f * (K * K - 1.f) * norm;
  340. this->a[1] = (1.f - K / Q + K * K) * norm;
  341. } break;
  342. case PEAK: {
  343. if (V >= 1.f) {
  344. float norm = 1.f / (1.f + K / Q + K * K);
  345. this->b[0] = (1.f + K / Q * V + K * K) * norm;
  346. this->b[1] = 2.f * (K * K - 1.f) * norm;
  347. this->b[2] = (1.f - K / Q * V + K * K) * norm;
  348. this->a[0] = this->b[1];
  349. this->a[1] = (1.f - K / Q + K * K) * norm;
  350. }
  351. else {
  352. float norm = 1.f / (1.f + K / Q / V + K * K);
  353. this->b[0] = (1.f + K / Q + K * K) * norm;
  354. this->b[1] = 2.f * (K * K - 1.f) * norm;
  355. this->b[2] = (1.f - K / Q + K * K) * norm;
  356. this->a[0] = this->b[1];
  357. this->a[1] = (1.f - K / Q / V + K * K) * norm;
  358. }
  359. } break;
  360. case NOTCH: {
  361. float norm = 1.f / (1.f + K / Q + K * K);
  362. this->b[0] = (1.f + K * K) * norm;
  363. this->b[1] = 2.f * (K * K - 1.f) * norm;
  364. this->b[2] = this->b[0];
  365. this->a[0] = this->b[1];
  366. this->a[1] = (1.f - K / Q + K * K) * norm;
  367. } break;
  368. default: break;
  369. }
  370. }
  371. };
  372. typedef TBiquadFilter<> BiquadFilter;
  373. } // namespace dsp
  374. } // namespace rack