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.

380 lines
9.7KB

  1. #include <assert.h>
  2. #if !defined(M_PI)
  3. #define M_PI 3.14159265358979323846264338327950288
  4. #endif
  5. #include "asserts.h"
  6. #include "EV3.h"
  7. #include "MinBLEPVCO.h"
  8. #include "TestComposite.h"
  9. static float sampleTime = 1.0f / 44100.0f;
  10. class TestMB
  11. {
  12. public:
  13. //static void setAllWaveforms(MinBLEPVCO* vco);
  14. // static void test1();
  15. static void testSync2();
  16. static void testSync3();
  17. static void setPitch(EV3<TestComposite>& ev3);
  18. };
  19. #if 0
  20. // puts non-zero in all the waveforms
  21. void TestMB::setAllWaveforms(MinBLEPVCO* vco)
  22. {
  23. // float * wave = vco->_getWaveforms();
  24. for (int i = 0; i < (int)MinBLEPVCO::Waveform::END; ++i) {
  25. vco->waveformOutputs[i] = 1;
  26. }
  27. }
  28. #endif
  29. #if 0
  30. void TestMB::test1()
  31. {
  32. MinBLEPVCO vco;
  33. setAllWaveforms(&vco);
  34. assertNE(vco.getWaveform(MinBLEPVCO::Waveform::Saw), 0);
  35. assertNE(vco.getWaveform(MinBLEPVCO::Waveform::Sin), 0);
  36. assertNE(vco.getWaveform(MinBLEPVCO::Waveform::Square), 0);
  37. assertNE(vco.getWaveform(MinBLEPVCO::Waveform::Tri), 0);
  38. assertNE(vco.getWaveform(MinBLEPVCO::Waveform::Even), 0);
  39. vco.zeroOutputsExcept(MinBLEPVCO::Waveform::Saw);
  40. assertNE(vco.getWaveform(MinBLEPVCO::Waveform::Saw), 0);
  41. assertEQ(vco.getWaveform(MinBLEPVCO::Waveform::Sin), 0);
  42. assertEQ(vco.getWaveform(MinBLEPVCO::Waveform::Square), 0);
  43. assertEQ(vco.getWaveform(MinBLEPVCO::Waveform::Tri), 0);
  44. assertEQ(vco.getWaveform(MinBLEPVCO::Waveform::Even), 0);
  45. // special case for even and sin
  46. setAllWaveforms(&vco);
  47. vco.zeroOutputsExcept(MinBLEPVCO::Waveform::Even);
  48. assertEQ(vco.getWaveform(MinBLEPVCO::Waveform::Saw), 0);
  49. assertNE(vco.getWaveform(MinBLEPVCO::Waveform::Sin), 0);
  50. assertEQ(vco.getWaveform(MinBLEPVCO::Waveform::Square), 0);
  51. assertEQ(vco.getWaveform(MinBLEPVCO::Waveform::Tri), 0);
  52. assertNE(vco.getWaveform(MinBLEPVCO::Waveform::Even), 0);
  53. setAllWaveforms(&vco);
  54. vco.zeroOutputsExcept(MinBLEPVCO::Waveform::Square);
  55. assertEQ(vco.getWaveform(MinBLEPVCO::Waveform::Saw), 0);
  56. assertEQ(vco.getWaveform(MinBLEPVCO::Waveform::Sin), 0);
  57. assertNE(vco.getWaveform(MinBLEPVCO::Waveform::Square), 0);
  58. assertEQ(vco.getWaveform(MinBLEPVCO::Waveform::Tri), 0);
  59. assertEQ(vco.getWaveform(MinBLEPVCO::Waveform::Even), 0);
  60. }
  61. static void test0()
  62. {
  63. MinBLEPVCO vco;
  64. // Don't enable any waveforms
  65. // vco.setSampleTime(sampleTime);
  66. vco.setNormalizedFreq(1000 * sampleTime);
  67. vco.step();
  68. // should get nothing out.
  69. assert(vco.getWaveform(MinBLEPVCO::Waveform::Sin) == 0);
  70. assert(vco.getWaveform(MinBLEPVCO::Waveform::Square) == 0);
  71. assert(vco.getWaveform(MinBLEPVCO::Waveform::Saw) == 0);
  72. assert(vco.getWaveform(MinBLEPVCO::Waveform::Tri) == 0);
  73. assert(vco.getWaveform(MinBLEPVCO::Waveform::Even) == 0);
  74. }
  75. #endif
  76. static void testSaw1()
  77. {
  78. MinBLEPVCO vco;
  79. vco.setNormalizedFreq(1000 * sampleTime, sampleTime);
  80. vco.setWaveform(MinBLEPVCO::Waveform::Saw);
  81. vco.step();
  82. // should get saw out.
  83. // assertEQ(vco.getWaveform(MinBLEPVCO::Waveform::Sin), 0);
  84. // assertEQ(vco.getWaveform(MinBLEPVCO::Waveform::Square), 0);
  85. // assertNE(vco.getWaveform(MinBLEPVCO::Waveform::Saw), 0);
  86. // assertEQ(vco.getWaveform(MinBLEPVCO::Waveform::Tri), 0);
  87. // assertEQ(vco.getWaveform(MinBLEPVCO::Waveform::Even), 0);
  88. assertNE(vco.getOutput(), 0);
  89. }
  90. static void testSync1()
  91. {
  92. MinBLEPVCO vco;
  93. vco.setNormalizedFreq(1000 * sampleTime, sampleTime);
  94. vco.setWaveform(MinBLEPVCO::Waveform::Saw);
  95. float lastOut = -1000;
  96. vco.step();
  97. // first make sure it's going up.
  98. for (int i = 0; i < 10; ++i) {
  99. vco.step();
  100. const float x = vco.getOutput();
  101. assertGT(x, lastOut);
  102. lastOut = x;
  103. }
  104. vco.onMasterSync(10); // set a reset to VCO
  105. vco.step();
  106. const float x = vco.getOutput();
  107. assertLT(x, lastOut);
  108. }
  109. void TestMB::setPitch(EV3<TestComposite>& ev3)
  110. {
  111. ev3.params[EV3<TestComposite>::OCTAVE1_PARAM].value = 2;
  112. ev3.params[EV3<TestComposite>::OCTAVE2_PARAM].value = 3;
  113. ev3.params[EV3<TestComposite>::OCTAVE3_PARAM].value = 3;
  114. // raise 2,3 by an oct and a semitone
  115. ev3.params[EV3<TestComposite>::SEMI1_PARAM].value = 0;
  116. ev3.params[EV3<TestComposite>::SEMI2_PARAM].value = 1;
  117. ev3.params[EV3<TestComposite>::SEMI3_PARAM].value = 1;
  118. ev3.vcos[0].setWaveform(MinBLEPVCO::Waveform::Saw);
  119. ev3.vcos[1].setWaveform(MinBLEPVCO::Waveform::Saw);
  120. ev3.vcos[2].setWaveform(MinBLEPVCO::Waveform::Saw);
  121. ev3.params[EV3<TestComposite>::SYNC2_PARAM].value = 1;
  122. ev3.vcos[0].name = "VCO1";
  123. ev3.vcos[1].name = "VCO2";
  124. ev3.vcos[2].name = "VCO3";
  125. }
  126. void TestMB::testSync2()
  127. {
  128. printf("***** testSync2*****\n");
  129. EV3<TestComposite> ev3;
  130. setPitch(ev3);
  131. ev3.step();
  132. const float f0 = ev3._freq[0];
  133. const float f1 = ev3._freq[1];
  134. assertClose(f0, 2093.02, .005);
  135. assertClose(f1, 4434.95, .005);
  136. float last0 = -10;
  137. float last1 = -10;
  138. for (int i = 0; i < 100; ++i) {
  139. ev3.step();
  140. //printf("phase==%.2f phase1==%.2f ", ev3.vcos[0].phase, ev3.vcos[1].phase);
  141. float x = ev3._out[0];
  142. // assert(x > last0);
  143. //printf("%d delta0=%.2f",i, x - last0);
  144. last0 = x;
  145. x = ev3._out[1];
  146. // assert(x > last1);
  147. printf(" delta1=%.2f", x - last1);
  148. printf(" 0=%.2f 1=%.2f\n", last0, last1);
  149. fflush(stdout);
  150. last1 = x;
  151. }
  152. // TODO: test the sync on/off
  153. }
  154. void TestMB::testSync3()
  155. {
  156. EV3<TestComposite> ev3;
  157. setPitch(ev3);
  158. ev3.step();
  159. const float f0 = ev3._freq[0];
  160. const float f1 = ev3._freq[1];
  161. assertClose(f0, 2093.02, .01);
  162. assertClose(f1, 4434.95, .01);
  163. float last0 = -10;
  164. float last1 = -10;
  165. for (int i = 0; i < 100; ++i) {
  166. // printf("-------- sample %d -----------\n", i);
  167. ev3.step();
  168. }
  169. // TODO: test the sync on/off
  170. }
  171. static void testBlepx(float crossing, float jump)
  172. {
  173. printf("BLEP crossing = %.2f, jump =%.2f\n", crossing, jump);
  174. rack::MinBLEP<16> syncMinBLEP;
  175. syncMinBLEP.minblep = rack::minblep_16_32;
  176. syncMinBLEP.oversample = 32;
  177. // syncMinBLEP.jump(-.5, -2);
  178. syncMinBLEP.jump(crossing, jump);
  179. for (int i = 0; i < 32; ++i) {
  180. //float saw = -1.0 + 2.0*phase;
  181. float x = syncMinBLEP.shift();
  182. printf("blep[%d] = %.2f\n", i, x);
  183. }
  184. }
  185. static void testEnums()
  186. {
  187. assertEQ((int) EV3<TestComposite>::Waves::SIN, (int) MinBLEPVCO::Waveform::Sin);
  188. assertEQ((int) EV3<TestComposite>::Waves::TRI, (int) MinBLEPVCO::Waveform::Tri);
  189. assertEQ((int) EV3<TestComposite>::Waves::SAW, (int) MinBLEPVCO::Waveform::Saw);
  190. assertEQ((int) EV3<TestComposite>::Waves::SQUARE, (int) MinBLEPVCO::Waveform::Square);
  191. assertEQ((int) EV3<TestComposite>::Waves::EVEN, (int) MinBLEPVCO::Waveform::Even);
  192. }
  193. static void testOutput(MinBLEPVCO::Waveform wf, bool expectFlat)
  194. {
  195. MinBLEPVCO osc;
  196. osc.setWaveform(wf);
  197. osc.setNormalizedFreq(.1f, 1.0f / 44100); // high freq
  198. bool hasChanged = false;
  199. float last = -100;
  200. for (int i = 0; i < 100; ++i) {
  201. osc.step();
  202. float x = osc.getOutput();
  203. if (!expectFlat) assertNE(x, last);
  204. if (last != x) hasChanged = true;
  205. last = x;
  206. }
  207. assert(hasChanged);
  208. }
  209. static void testOutputs()
  210. {
  211. testOutput(MinBLEPVCO::Waveform::Saw, false);
  212. testOutput(MinBLEPVCO::Waveform::Square, true);
  213. testOutput(MinBLEPVCO::Waveform::Sin, false);
  214. testOutput(MinBLEPVCO::Waveform::Tri, false);
  215. testOutput(MinBLEPVCO::Waveform::Even, false);
  216. }
  217. static void testBlep()
  218. {
  219. testBlepx(-.5, -2);
  220. testBlepx(-.5, 1);
  221. testBlepx(-.9f, .2f);
  222. }
  223. static void testZero()
  224. {
  225. MinBLEPVCO osc;
  226. osc.setWaveform(MinBLEPVCO::Waveform::Saw);
  227. osc.setNormalizedFreq(.1f, 1.0f / 44100); // high freq
  228. osc.step();
  229. osc.setWaveform(MinBLEPVCO::Waveform::END);
  230. osc.step();
  231. float x = osc.getOutput();
  232. assertEQ(x, 0);
  233. }
  234. static void testSyncOut(MinBLEPVCO::Waveform wf)
  235. {
  236. MinBLEPVCO osc;
  237. int callbackCount = 0;
  238. osc.setWaveform(wf);
  239. osc.setNormalizedFreq(.1f, 1.0f / 44100); // high freq
  240. osc.setSyncCallback([&callbackCount](float p) {
  241. assert(p <= 0 && p >= -1);
  242. callbackCount++;
  243. });
  244. for (int i = 0; i < 15; ++i) {
  245. osc.step();
  246. }
  247. assertEQ(callbackCount, 1);
  248. // assertGE(callbackCount, 1); // TODO: why does square do 3??
  249. }
  250. static void testSyncOut()
  251. {
  252. testSyncOut(MinBLEPVCO::Waveform::Saw);
  253. testSyncOut(MinBLEPVCO::Waveform::Square);
  254. testSyncOut(MinBLEPVCO::Waveform::Sin);
  255. testSyncOut(MinBLEPVCO::Waveform::Tri);
  256. testSyncOut(MinBLEPVCO::Waveform::Even);
  257. }
  258. static void testSyncIn(MinBLEPVCO::Waveform wf)
  259. {
  260. MinBLEPVCO osc;
  261. osc.setWaveform(wf);
  262. osc.setNormalizedFreq(.1f, 1.0f / 44100); // high freq
  263. for (int i = 0; i < 4; ++i) {
  264. osc.step();
  265. }
  266. osc.step();
  267. float x = osc.getOutput();
  268. osc.onMasterSync(0);
  269. osc.step(); // this one catches the callback
  270. osc.step(); // this one generates new sample (TODO: is this extra required?)
  271. float y = osc.getOutput();
  272. assert(!AudioMath::closeTo(x, y, .1));
  273. // TODO: pick freq that will make this more robust
  274. }
  275. static void testSyncIn()
  276. {
  277. testSyncIn(MinBLEPVCO::Waveform::Saw);
  278. testSyncIn(MinBLEPVCO::Waveform::Sin);
  279. testSyncIn(MinBLEPVCO::Waveform::Tri);
  280. testSyncIn(MinBLEPVCO::Waveform::Square);
  281. testSyncIn(MinBLEPVCO::Waveform::Even);
  282. }
  283. void testMinBLEPVCO()
  284. {
  285. // A lot of these tests are from old API
  286. // TestMB::test1();
  287. // printf("fix the minb tests\n");
  288. // test0();
  289. testSaw1();
  290. //testSync1();
  291. // this one doesn't work, either.
  292. //TestMB::testSync2();
  293. TestMB::testSync3();
  294. // testBlep();
  295. testEnums();
  296. testOutputs();
  297. testZero();
  298. testSyncOut();
  299. testSyncIn();
  300. }