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.

195 lines
4.7KB

  1. #include <assert.h>
  2. #include <iostream>
  3. #include "asserts.h"
  4. #include "AudioMath.h"
  5. #include "LookupTableFactory.h"
  6. using namespace std;
  7. static void test0()
  8. {
  9. assert(AudioMath::closeTo(0, 0, .000001));
  10. assert(AudioMath::closeTo(1000, 1001, 1.1));
  11. assert(!AudioMath::closeTo(1000, 1010, 1.1));
  12. assert(!AudioMath::closeTo(1010, 1000, 1.1));
  13. }
  14. static void test1()
  15. {
  16. assert(AudioMath::closeTo(3.145, AudioMath::Pi, .1));
  17. assert(AudioMath::closeTo(3.145 / 2, AudioMath::Pi_2, .1));
  18. assert(AudioMath::closeTo(log(10), AudioMath::Ln10, .001));
  19. }
  20. static void test2()
  21. {
  22. const double d = .0001;
  23. std::function<double(double)> f = AudioMath::makeFunc_Sin();
  24. assert(AudioMath::closeTo(f(0), 0, d));
  25. assert(AudioMath::closeTo(f(.5), 0, d));
  26. assert(AudioMath::closeTo(f(.25), 1, d));
  27. assert(AudioMath::closeTo(f(.75), -1, d));
  28. assert(AudioMath::closeTo(f(.125), 1.0 / sqrt(2), d));
  29. }
  30. static void test3()
  31. {
  32. const double d = .0001;
  33. std::function<double(double)> f = AudioMath::makeFunc_Exp(0, 4, 2, 32);
  34. assert(AudioMath::closeTo(f(0), 2, d));
  35. assert(AudioMath::closeTo(f(1), 4, d));
  36. assert(AudioMath::closeTo(f(2), 8, d));
  37. assert(AudioMath::closeTo(f(3), 16, d));
  38. assert(AudioMath::closeTo(f(4), 32, d));
  39. assert(f(5) > 33);
  40. assert(f(-1) < 1.5);
  41. }
  42. static void testAudioTaper()
  43. {
  44. double db = -18;
  45. std::function<double(double)> f = AudioMath::makeFunc_AudioTaper(db);
  46. assertClose(f(1), 1, .001);
  47. assertClose(f(.25), .125, .001);
  48. assertClose(f(.251), .126, .001);
  49. assertClose(f(.249), 1.0 / 8.0, .001);
  50. assertClose(f(0), 0, .001);
  51. }
  52. static void testScaler()
  53. {
  54. AudioMath::ScaleFun<float> f = AudioMath::makeLinearScaler<float>(3, 4);
  55. // scale(cv, knob, trim
  56. // knob comes through only shifted
  57. assertEQ(f(0, -5, 0), 3.);
  58. assertEQ(f(0, 5, 0), 4.);
  59. assertEQ(f(0, 0, 0), 3.5);
  60. // cv also come through, it trim up
  61. assertEQ(f(-5, 0, 1), 3.);
  62. assertEQ(f(5, 0, 1), 4.);
  63. assertEQ(f(0, 0, 1), 3.5);
  64. // no cv if trim 0
  65. assertEQ(f(-5, 0, 0), 3.5);
  66. // neg trim inverts cv
  67. assertEQ(f(-5, 0, -1), 4.);
  68. // trim half way
  69. assertEQ(f(5, 0, .5), 3.75);
  70. }
  71. static void testBipolarAudioScaler()
  72. {
  73. AudioMath::ScaleFun<float> f = AudioMath::makeScalerWithBipolarAudioTrim(3, 4);
  74. // scale(cv, knob, trim
  75. // knob comes through only shifted
  76. assertEQ(f(0, -5, 0), 3.);
  77. assertEQ(f(0, 5, 0), 4.);
  78. assertEQ(f(0, 0, 0), 3.5);
  79. // cv also come through, it trim up
  80. assertEQ(f(-5, 0, 1), 3.);
  81. assertEQ(f(5, 0, 1), 4.);
  82. assertEQ(f(0, 0, 1), 3.5);
  83. // no cv if trim 0
  84. assertEQ(f(-5, 0, 0), 3.5);
  85. // neg trim inverts cv
  86. assertEQ(f(-5, 0, -1), 4.);
  87. // trim quarter - should be audio knee
  88. auto f2 = AudioMath::makeScalerWithBipolarAudioTrim(-1, 1);
  89. float x = f2(5, 0, .25);
  90. float y = (float) AudioMath::gainFromDb(LookupTableFactory<float>::audioTaperKnee());
  91. assertClose(x, y, .001);
  92. }
  93. static void testAudioScaler()
  94. {
  95. AudioMath::SimpleScaleFun<float> f = AudioMath::makeSimpleScalerAudioTaper(3, 4);
  96. float kneeGain = (float) AudioMath::gainFromDb(LookupTableFactory<float>::audioTaperKnee());
  97. // knob comes through with taper
  98. assertEQ(f(0, -5), 3.);
  99. assertEQ(f(0, 5), 4.);
  100. // 1/4, is the knee
  101. assertEQ(f(0, -2.5), 3.0f + kneeGain);
  102. // cv also come through, it trim up
  103. assertEQ(f(-5, 0), 3.);
  104. assertEQ(f(5, 0), 4.);
  105. assertEQ(f(-2.5, 0), 3.0f + kneeGain);
  106. }
  107. static void testAudioScaler2()
  108. {
  109. AudioMath::SimpleScaleFun<float> f = AudioMath::makeSimpleScalerAudioTaper(0, 20);
  110. float kneeGain = (float) AudioMath::gainFromDb(LookupTableFactory<float>::audioTaperKnee());
  111. // knob comes through with taper
  112. assertEQ(f(0, -5), 0);
  113. assertEQ(f(0, 5), 20);
  114. // 1/4, is the knee
  115. assertEQ(f(0, -2.5), 20 * kneeGain);
  116. // cv also come through, it trim up
  117. assertEQ(f(-5, 0), 0);
  118. assertEQ(f(5, 0), 20);
  119. assertEQ(f(-2.5, 0), 20 * kneeGain);
  120. }
  121. static void testFold()
  122. {
  123. float last = 0;
  124. const float deltaX = 0.05f;
  125. for (float x = 0; x < 15; x += deltaX) {
  126. float y = AudioMath::fold(x);
  127. float absChange = std::abs(y - last);
  128. last = y;
  129. assertLE(absChange, deltaX + .0001f);
  130. }
  131. }
  132. static void testFoldNegative()
  133. {
  134. float last = 0;
  135. const float deltaX = 0.05f;
  136. for (float x = 0; x > -15; x -= deltaX) {
  137. float y = AudioMath::fold(x);
  138. float absChange = std::abs(y - last);
  139. last = y;
  140. assertLE(absChange, deltaX + .0001f);
  141. }
  142. }
  143. void testAudioMath()
  144. {
  145. test0();
  146. test1();
  147. test2();
  148. test3();
  149. testAudioTaper();
  150. testScaler();
  151. testBipolarAudioScaler();
  152. testAudioScaler();
  153. testAudioScaler2();
  154. testFold();
  155. testFoldNegative();
  156. }