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.

93 lines
2.7KB

  1. #pragma once
  2. #include <cmath>
  3. #include <functional>
  4. #include <algorithm>
  5. class AudioMath
  6. {
  7. public:
  8. AudioMath() = delete; // we are only static
  9. static const double Pi;
  10. static const double Pi_2; // Pi / 2
  11. static const double Ln2;
  12. static const double Ln10;
  13. static const double E;
  14. static bool closeTo(double x, double y, double tolerance)
  15. {
  16. const bool ret = std::abs(x - y) < tolerance;
  17. return ret;
  18. }
  19. static double db(double g)
  20. {
  21. return 20 * log(g) / Ln10;
  22. }
  23. static double gainFromDb(double db)
  24. {
  25. return std::exp(Ln10 * db / 20.0);
  26. }
  27. /**
  28. * Returns a function that generates one period of sin for x = {0..1}.
  29. * Range (output) is -1 to 1.
  30. */
  31. static std::function<double(double)> makeFunc_Sin();
  32. /*
  33. * Returns a function that generates an exponential defined by two points
  34. * At input = xMin, output will be yMin.
  35. * At input = xMax, output will be yMax.
  36. */
  37. static std::function<double(double)> makeFunc_Exp(double xMin, double xMax, double yMin, double yMax);
  38. /**
  39. * Returns a function for an "audio taper" attenuator gain.
  40. * function is pure exponential for x > .25, linear for x < .25
  41. * At input 1, output is 1
  42. * At input .25, output is the gain corresponding to adAtten
  43. * At input 0, the output is zero.
  44. */
  45. static std::function<double(double)> makeFunc_AudioTaper(double dbAtten);
  46. /**
  47. * ScaleFun is a function the combines CV, knob, and trim into a voltage.
  48. * Typically a ScaleFun is like an "attenuverter"
  49. */
  50. template <typename T>
  51. using ScaleFun = std::function<T(T cv, T knob, T trim)>;
  52. /**
  53. * Create a ScaleFun with the following properties:
  54. * 1) The values are combined with the typical formula: x = cv * trim + knob;
  55. * 2) x is clipped between -5 and 5
  56. * 3) range is then interpolated between y0, and y1.
  57. *
  58. * This particular function is used when knobs are -5..5,
  59. * and CV range is -5..5.
  60. */
  61. template <typename T>
  62. static ScaleFun<T> makeLinearScaler(T y0, T y1)
  63. {
  64. const T x0 = -5;
  65. const T x1 = 5;
  66. const T a = (y1 - y0) / (x1 - x0);
  67. const T b = y0 - a * x0;
  68. return [a, b](T cv, T knob, T trim) {
  69. T x = cv * trim + knob;
  70. x = std::max<T>(-5.0f, x);
  71. x = std::min(5.0f, x);
  72. return a * x + b;
  73. };
  74. }
  75. /**
  76. * Generates a scale function for an audio taper attenuverter.
  77. * Details the same as makeLinearScaler except that the CV
  78. * scaling will be exponential for most values, becoming
  79. * linear near zero.
  80. */
  81. static ScaleFun<float> makeBipolarAudioScaler(float y0, float y1);
  82. };