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.

237 lines
5.8KB

  1. #include <assert.h>
  2. #include "Analyzer.h"
  3. #include "asserts.h"
  4. #include "CHB.h"
  5. #include "EvenVCO.h"
  6. #include "FunVCO.h"
  7. #include "SawOscillator.h"
  8. #include "TestComposite.h"
  9. using EVCO = EvenVCO <TestComposite>;
  10. //using FUN = VoltageControlledOscillator<16, 16>;
  11. using CH = CHB<TestComposite>;
  12. float desiredPitch(float octave, float tune, float cv1, float cv2, float mod)
  13. {
  14. float pitch = 1.0f + roundf(octave) + tune / 12.0f;
  15. pitch += cv1 + cv2;
  16. pitch += mod / 4.0f;
  17. float freq = 261.626f * powf(2.0f, pitch);
  18. // printf("theirs: pitch = %f exp = %f\n", pitch, freq);
  19. return freq;
  20. }
  21. float desiredPitchEv(const EVCO& vco)
  22. {
  23. #if 1
  24. return desiredPitch(
  25. vco.params[(int) EVCO::OCTAVE_PARAM].value,
  26. vco.params[(int) EVCO::TUNE_PARAM].value,
  27. vco.inputs[(int) EVCO::PITCH1_INPUT].value,
  28. vco.inputs[(int) EVCO::PITCH2_INPUT].value,
  29. vco.inputs[(int) EVCO::FM_INPUT].value
  30. );
  31. #else
  32. // This is just the original code as reference
  33. float pitch = 1.0f + roundf(vco.params[(int) EVCO::OCTAVE_PARAM].value) + vco.params[(int) EVCO::TUNE_PARAM].value / 12.0f;
  34. pitch += vco.inputs[(int) EVCO::PITCH1_INPUT].value + vco.inputs[(int) EVCO::PITCH2_INPUT].value;
  35. pitch += vco.inputs[(int) EVCO::FM_INPUT].value / 4.0f;
  36. float freq = 261.626f * powf(2.0f, pitch);
  37. // printf("theirs: pitch = %f exp = %f\n", pitch, freq);
  38. return freq;
  39. #endif
  40. }
  41. float desiredPitchCh(const CH& vco)
  42. {
  43. return desiredPitch(
  44. vco.params[(int) CH::PARAM_OCTAVE].value,
  45. vco.params[(int) CH::PARAM_TUNE].value,
  46. vco.inputs[(int) CH::CV_INPUT].value,
  47. 0,
  48. vco.inputs[(int) CH::PITCH_MOD_INPUT].value
  49. );
  50. #if 0
  51. float pitch = 1.0f + roundf(vco.params[(int) CH::PARAM_OCTAVE].value) + vco.params[(int) CH::PARAM_TUNE].value / 12.0f;
  52. pitch += vco.inputs[(int) CH::CV_INPUT].value;
  53. pitch += vco.inputs[(int) CH::PITCH_MOD_INPUT].value / 4.0f;
  54. // TODO: atenuverter on FM
  55. float freq = 261.626f * powf(2.0f, pitch);
  56. // printf("theirs: pitch = %f exp = %f\n", pitch, freq);
  57. printf("in desiredPitchCh oct=%f, tune=%f cv=%f, mode=%f\n",
  58. vco.params[(int) CH::PARAM_OCTAVE].value,
  59. vco.params[(int) CH::PARAM_TUNE].value,
  60. vco.inputs[(int) CH::CV_INPUT].value,
  61. vco.inputs[(int) CH::PITCH_MOD_INPUT].value);
  62. printf(" freq = %f\n", freq);
  63. return freq;
  64. #endif
  65. }
  66. static void testxEv(float octave, float tune = 0, float pitch1 = 0, float pitch2 = 0, float fm = 0)
  67. {
  68. EVCO vco;
  69. vco.params[(int) EVCO::OCTAVE_PARAM].value = octave;
  70. vco.params[(int) EVCO::TUNE_PARAM].value = tune;
  71. vco.inputs[(int) EVCO::PITCH1_INPUT].value = pitch1;
  72. vco.inputs[(int) EVCO::PITCH2_INPUT].value = pitch2;
  73. vco.inputs[(int) EVCO::FM_INPUT].value = fm;
  74. vco.outputs[(int) EVCO::SAW_OUTPUT].active = true;
  75. vco.outputs[(int) EVCO::EVEN_OUTPUT].active = false;
  76. vco.outputs[(int) EVCO::TRI_OUTPUT].active = false;
  77. vco.outputs[(int) EVCO::SQUARE_OUTPUT].active = false;
  78. vco.outputs[(int) EVCO::SINE_OUTPUT].active = false;
  79. vco.step();
  80. const float desired = desiredPitchEv(vco);
  81. // printf("test, oct=%f, freq=%.2f desired=%.2f\n", octave, vco._freq, desired);
  82. if (desired > 20000) {
  83. // lookup table doesn't go past 20k. that's fine
  84. assertGE(vco._freq, 20000 - 1);
  85. } else {
  86. assertClose(vco._freq, desired, 1.5); // todo: make better tolerance
  87. }
  88. }
  89. static void testxCh(float octave, float tune = 0, float pitch1 = 0, float pitch2 = 0, float fm = 0)
  90. {
  91. CH vco;
  92. assert(pitch2 == 0); // ch doesn't have one
  93. vco.params[(int) CH::PARAM_OCTAVE].value = octave;
  94. vco.params[(int) CH::PARAM_TUNE].value = tune;
  95. vco.inputs[(int) CH::CV_INPUT].value = pitch1;
  96. // vco.inputs[(int) CH::PITCH2_INPUT].value = pitch2;
  97. vco.inputs[(int) CH::PITCH_MOD_INPUT].value = fm;
  98. vco.step();
  99. const float desired = desiredPitchCh(vco);
  100. // printf("test, oct=%f, freq=%.2f desired=%.2f\n", octave, vco._freq, desired);
  101. if (desired > 20000) {
  102. // lookup table doesn't go past 20k. that's fine
  103. assertGE(vco._freq, 20000 - 1);
  104. } else {
  105. assertClose(vco._freq, desired, 1.5); // todo: make better tolerance
  106. }
  107. }
  108. static void testInitEv()
  109. {
  110. EVCO vco;
  111. vco.step();
  112. const float desired = desiredPitchEv(vco);
  113. assertClose(vco._freq, desired, 1); // todo: tighten up
  114. }
  115. static void testInitCh()
  116. {
  117. CH vco;
  118. vco.step();
  119. const float desired = desiredPitchCh(vco);
  120. assertClose(vco._freq, desired, 1); // todo: tighten up
  121. }
  122. static void testOctavesEv()
  123. {
  124. EVCO vco;
  125. for (int octave = -5; octave <= 4; ++octave) {
  126. testxEv(float(octave));
  127. }
  128. }
  129. static void testOctavesCh()
  130. {
  131. CH vco;
  132. for (int octave = -5; octave <= 4; ++octave) {
  133. testxCh(float(octave));
  134. }
  135. }
  136. // test that we go up to 20k
  137. static void testMaxFreqEv()
  138. {
  139. testxEv(4, 7, 0, 0);
  140. testxEv(4, 7, 1, 0);
  141. testxEv(4, 7, 0, 1);
  142. }
  143. static void testMaxFreqCh()
  144. {
  145. testxCh(4, 7, 0, 0);
  146. testxCh(4, 7, 1, 0);
  147. }
  148. static void testMinFreqEv()
  149. {
  150. testxEv(-5, -7, 0, 0);
  151. testxEv(-5, -7, -2, 0);
  152. }
  153. static void testMinFreqCh()
  154. {
  155. testxCh(-5, -7, 0, 0);
  156. testxCh(-5, -7, -2, 0);
  157. }
  158. static void testTuneEv()
  159. {
  160. testxEv(0, -7, 0, 0);
  161. testxEv(0, 7, 0, 0);
  162. }
  163. static void testTuneCh()
  164. {
  165. testxCh(0, -7, 0, 0);
  166. testxCh(0, 7, 0, 0);
  167. }
  168. static void testClamp()
  169. {
  170. assertEQ(std::clamp(12, 0, 14), 12);
  171. assertEQ(std::clamp(12, 0, 10), 10);
  172. assertEQ(std::clamp(12, 13, 15), 13);
  173. }
  174. #if 1
  175. void testVCO()
  176. {
  177. testInitEv();
  178. testInitCh();
  179. testOctavesEv();
  180. testOctavesCh();
  181. testMaxFreqEv();
  182. testMaxFreqCh();
  183. testMinFreqEv();
  184. testMinFreqCh();
  185. testClamp();
  186. testTuneEv();
  187. testTuneCh();
  188. }
  189. #else
  190. void testVCO()
  191. {
  192. testOctavesCh();
  193. }
  194. #endif