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.

139 lines
3.6KB

  1. #include <assert.h>
  2. #include <iostream>
  3. #include "asserts.h"
  4. #include "SinOscillator.h"
  5. using namespace std;
  6. // test that it can be hooked up
  7. template<typename T>
  8. static void test1()
  9. {
  10. SinOscillatorParams<T> p;
  11. SinOscillatorState<T> s;
  12. SinOscillator<T, true>::setFrequency(p, T(.1));
  13. T x = SinOscillator<T, true>::run(s, p);
  14. (void) x;
  15. }
  16. // test that it makes output
  17. template<typename T>
  18. static void test2()
  19. {
  20. SinOscillatorParams<T> p;
  21. SinOscillatorState<T> s;
  22. SinOscillator<T, false>::setFrequency(p, T(.1));
  23. T x = SinOscillator<T, false>::run(s, p);
  24. assert(x == 0);
  25. x = SinOscillator<T, false>::run(s, p);
  26. assert(x > 0);
  27. }
  28. // test that sin lookup is correct
  29. template<typename T>
  30. static void test3()
  31. {
  32. SinOscillatorParams<T> params;
  33. SinOscillatorState<T> s;
  34. SinOscillator<T, true>::setFrequency(params, T(.1));
  35. auto& lookup = params.lookupParams;
  36. const double delta = .00001;
  37. // sin(0) == 0;
  38. T y = LookupTable<T>::lookup(*lookup, 0);
  39. assert(AudioMath::closeTo(y, 0, delta));
  40. // sin(2pi) == 0
  41. y = LookupTable<T>::lookup(*lookup, 1);
  42. assert(AudioMath::closeTo(y, 0, delta));
  43. // sin(pi/2) == 1
  44. y = LookupTable<T>::lookup(*lookup, .25);
  45. assert(AudioMath::closeTo(y, 1, delta));
  46. // sin(pi) == 0
  47. y = LookupTable<T>::lookup(*lookup, .5);
  48. assert(AudioMath::closeTo(y, 0, delta));
  49. }
  50. // test that output is correct freq
  51. template<typename T>
  52. static void test4()
  53. {
  54. const int clocksPerPeriod = 64;
  55. SinOscillatorParams<T> params;
  56. SinOscillatorState<T> state;
  57. SinOscillator<T, false>::setFrequency(params, T(1.0 / clocksPerPeriod));
  58. const double delta = .00001;
  59. T output, quadrature;
  60. for (int i = 0; i <= clocksPerPeriod; ++i) {
  61. SinOscillator<T, false>::runQuadrature(output, quadrature, state, params);
  62. if (i == 0) {
  63. // sin+cos(0) = 0 + 1
  64. assert(AudioMath::closeTo(output, 0, delta));
  65. assert(AudioMath::closeTo(quadrature, 1, delta));
  66. }
  67. if (i == 64) {
  68. // sin+cos(0) = 0 + 1
  69. assert(AudioMath::closeTo(output, 0, delta));
  70. assert(AudioMath::closeTo(quadrature, 1, delta));
  71. }
  72. if (i == 16) {
  73. // sin+cos(pi/2) = 1 0
  74. assert(AudioMath::closeTo(output, 1, delta));
  75. assert(AudioMath::closeTo(quadrature, 0, delta));
  76. }
  77. if (i == 32) {
  78. // sin+cos(pi) = 0 -1
  79. assert(AudioMath::closeTo(output, 0, delta));
  80. assert(AudioMath::closeTo(quadrature, -1, delta));
  81. }
  82. if (i == 48) {
  83. // sin+cos(3pi/2) = -1 0
  84. assert(AudioMath::closeTo(output, -1, delta));
  85. assert(AudioMath::closeTo(quadrature, 0, delta));
  86. }
  87. }
  88. }
  89. template<typename T>
  90. static void testDistortion()
  91. {
  92. SinOscillatorParams<T> params;
  93. SinOscillatorState<T> s;
  94. SinOscillator<T, true>::setFrequency(params, T(.0423781));
  95. auto& lookup = params.lookupParams;
  96. double err = 0;
  97. for (double d = 0; d < 1; d += .00123) {
  98. double x = LookupTable<T>::lookup(*lookup, (T) d);
  99. double y = sin(d * AudioMath::Pi * 2);
  100. // printf("d=%f sin=%f look=%f\n", d, y, x);
  101. assertClose(x, y, .01);
  102. const double e = std::abs(x - y);
  103. err = std::max(err, e);
  104. }
  105. double errDb = AudioMath::db(err);
  106. // printf("THD = %f\n", errDb);
  107. assertLT(errDb, -80);
  108. }
  109. template<typename T>
  110. static void test()
  111. {
  112. test1<T>();
  113. test2<T>();
  114. test3<T>();
  115. test4<T>();
  116. testDistortion<T>();
  117. }
  118. void testSinOscillator()
  119. {
  120. test<double>();
  121. test<float>();
  122. }