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.

498 lines
12KB

  1. #include "GenerativeTriggerGenerator.h"
  2. #include "StochasticGrammar.h"
  3. #include "TriggerSequencer.h"
  4. #include <string>
  5. #include <vector>
  6. #include <set>
  7. //#include <random>
  8. static const int numRules = fullRuleTableSize;
  9. typedef GKEY(*INITFN)();
  10. static ProductionRule rules[numRules];
  11. // Test basic integrity of key data
  12. static void test0()
  13. {
  14. GKEY key;
  15. GKEY outKeys[ProductionRuleKeys::bufferSize];
  16. for (key = sg_first; key <= sg_last; ++key) {
  17. ProductionRuleKeys::breakDown(key, outKeys);
  18. for (GKEY* p = outKeys; *p != sg_invalid; ++p) {
  19. assert(*p >= sg_first);
  20. assert(*p <= sg_last);
  21. }
  22. std::string s = ProductionRuleKeys::toString(key);
  23. assert(!s.empty());
  24. assert(s.length() < 256);
  25. int dur = ProductionRuleKeys::getDuration(key);
  26. assert(dur > 0);
  27. assert(dur <= PPQ * 8);
  28. }
  29. }
  30. // test all the gkeys
  31. void testAllKeys()
  32. {
  33. const int siz = ProductionRuleKeys::bufferSize;
  34. GKEY buffer[siz];
  35. for (GKEY gk = sg_first; gk <= sg_last; ++gk) {
  36. // printf("testing key %d\n", gk);
  37. // printf("to string: %s\n", ProductionRuleKeys::toString(gk));
  38. const int dur = ProductionRuleKeys::getDuration(gk);
  39. ProductionRuleKeys::breakDown(gk, buffer);
  40. int sum = 0;
  41. for (GKEY * p = buffer; *p != sg_invalid; ++p) {
  42. // printf("adding to sum %d\n", ProductionRuleKeys::getDuration(*p));
  43. sum += ProductionRuleKeys::getDuration(*p);
  44. }
  45. // printf("dur = %d sum = %d (should be the same)\n", dur, sum);
  46. assert(dur == sum);
  47. }
  48. }
  49. /**************************************************************************************
  50. * Make some simple grammars and test them
  51. **************************************************************************************/
  52. #ifdef _DEBUG
  53. void gdt0()
  54. {
  55. {
  56. static ProductionRule rules[numRules];
  57. bool b = ProductionRule::isGrammarValid(rules, numRules, sg_invalid);
  58. assert(!b);
  59. }
  60. {
  61. // throw in a positive case
  62. static ProductionRule rules[numRules];
  63. ProductionRule& r = rules[sg_w];
  64. r.entries[0].probability = 1.0f;
  65. r.entries[0].code = sg_invalid;
  66. bool b = ProductionRule::isGrammarValid(rules, numRules, sg_w);
  67. assert(b);
  68. }
  69. {
  70. // terminal code wrong
  71. static ProductionRule rules[numRules];
  72. ProductionRule& r = rules[sg_w];
  73. r.entries[0].probability = 1.0f;
  74. r.entries[0].code = sg_q;
  75. bool b = ProductionRule::isGrammarValid(rules, numRules, sg_w);
  76. assert(!b);
  77. }
  78. {
  79. // bad order of probability
  80. static ProductionRule rules[numRules];
  81. ProductionRule& r = rules[sg_w];
  82. r.entries[0].probability = 1.0f;
  83. r.entries[0].code = sg_q;
  84. bool b = ProductionRule::isGrammarValid(rules, numRules, sg_w);
  85. assert(!b);
  86. }
  87. {
  88. // rule branches to nowhere
  89. static ProductionRule rules[numRules];
  90. // break w2 into w,w prob 100
  91. ProductionRule& r = rules[sg_w2];
  92. r.entries[0].probability = 1.0f;
  93. r.entries[0].code = sg_ww;
  94. bool b = ProductionRule::isGrammarValid(rules, numRules, sg_w);
  95. assert(!b);
  96. }
  97. }
  98. #endif
  99. class TestEvaluator : public ProductionRule::EvaluationState
  100. {
  101. public:
  102. TestEvaluator(AudioMath::RandomUniformFunc xr) : ProductionRule::EvaluationState(xr)
  103. {
  104. }
  105. void writeSymbol(GKEY key) override
  106. {
  107. keys.push_back(key);
  108. }
  109. int getNumSymbols()
  110. {
  111. //printf("final keys: ");
  112. // for (size_t i = 0; i< keys.size(); ++i) printf("%s, ", ProductionRuleKeys::toString(keys[i]));
  113. // printf("\n");
  114. return (int) keys.size();
  115. }
  116. private:
  117. std::vector<GKEY> keys;
  118. };
  119. /**
  120. * simplest possible grammar.
  121. */
  122. static GKEY init0()
  123. {
  124. // printf("called init0\n");
  125. // This rule always generate sg-w2 (two whole notes tied together)
  126. ProductionRule& r = rules[sg_w2];
  127. r.entries[0].probability = 1;
  128. r.entries[0].code = sg_invalid; // terminate expansion
  129. return sg_w2;
  130. }
  131. /**
  132. * Simple grammar with a rule but no random.
  133. */
  134. static GKEY init1()
  135. {
  136. {
  137. // start with w2 duration
  138. ProductionRule& r = rules[sg_w2];
  139. // break into w,w prob 100
  140. r.entries[0].probability = 1.0f;
  141. r.entries[0].code = sg_ww;
  142. }
  143. {
  144. // now need rule for w hole
  145. //printf("in init1 making 100 for %d\n", sg_w);
  146. ProductionRule& r = rules[sg_w];
  147. r.entries[0].probability = 1.0f;
  148. r.entries[1].code = sg_invalid;
  149. }
  150. //printf("leave init 1. rule 1 p0 = %f\n", rules[sg_w2].entries[0].probability);
  151. return sg_w2;
  152. }
  153. /**
  154. * Simple grammar with randomness initializer
  155. */
  156. static GKEY init2()
  157. {
  158. {
  159. // start with w2 duration
  160. ProductionRule& r = rules[sg_w2];
  161. // break into w,w prob 50
  162. r.entries[0].probability = .5f;
  163. r.entries[0].code = sg_ww;
  164. r.entries[1].probability = 1.0f;
  165. r.entries[1].code = sg_invalid; // always terminate
  166. }
  167. {
  168. // now need rule for w hole
  169. ProductionRule& r = rules[sg_w];
  170. r.entries[1].probability = 1.0f;
  171. r.entries[1].code = sg_invalid; // always terminate
  172. }
  173. return sg_w2;
  174. }
  175. #ifdef _DEBUG
  176. static void testGrammarSub(INITFN f)
  177. {
  178. GKEY init = f();
  179. bool b = ProductionRule::isGrammarValid(rules, numRules, init);
  180. assert(b);
  181. TestEvaluator es(AudioMath::random());
  182. es.rules = rules;
  183. es.numRules = numRules;
  184. ProductionRule::evaluate(es, init);
  185. assert(es.getNumSymbols() > 0);
  186. }
  187. #endif
  188. /*********************************************************************************************************
  189. * TriggerSequencer
  190. **********************************************************************************************************/
  191. // test event at zero fires at zero
  192. static void ts0()
  193. {
  194. TriggerSequencer::Event seq[] =
  195. {
  196. {TriggerSequencer::TRIGGER, 0},
  197. {TriggerSequencer::END, 100}
  198. };
  199. TriggerSequencer ts(seq);
  200. ts.clock();
  201. assert(ts.getTrigger());
  202. ts.clock();
  203. assert(!ts.getTrigger());
  204. }
  205. // test trigger at 1 happens at 1
  206. static void ts1()
  207. {
  208. TriggerSequencer::Event seq[] =
  209. {
  210. {TriggerSequencer::TRIGGER, 1},
  211. {TriggerSequencer::END, 0}
  212. };
  213. TriggerSequencer ts(seq);
  214. ts.clock();
  215. assert(!ts.getTrigger());
  216. ts.clock();
  217. assert(ts.getTrigger());
  218. ts.clock();
  219. assert(!ts.getTrigger());
  220. ts.clock();
  221. assert(!ts.getTrigger());
  222. }
  223. // 4 clock loop: delay 4, trigger, end
  224. static void ts2()
  225. {
  226. TriggerSequencer::Event seq[] =
  227. {
  228. {TriggerSequencer::TRIGGER, 4},
  229. {TriggerSequencer::END, 0}
  230. };
  231. TriggerSequencer ts(seq);
  232. bool firstTime = true;
  233. // first time through, 4 clocks of nothing. then clock, 0,0,0
  234. for (int i = 0; i < 4; ++i) {
  235. ts.clock();
  236. if (firstTime) {
  237. assert(!ts.getTrigger()); assert(!ts.getEnd());
  238. firstTime = false;
  239. } else {
  240. //printf("second time around, t=%d e=%d\n", ts.getTrigger(), ts.getEnd());
  241. // second time around we finally see the trigger
  242. assert(ts.getTrigger());
  243. // second time around, need to clock the end of the last time
  244. assert(ts.getEnd());
  245. ts.reset(seq); // start it up again
  246. assert(!ts.getTrigger()); // resetting should not set us up for a trigger
  247. }
  248. ts.clock(); assert(!ts.getTrigger()); assert(!ts.getEnd());
  249. ts.clock(); assert(!ts.getTrigger()); assert(!ts.getEnd());
  250. ts.clock(); assert(!ts.getTrigger());
  251. // assert(ts.getEnd());
  252. // ts.reset(seq);
  253. }
  254. }
  255. // test trigger seq qith
  256. // 4 clock loop: trigger, delay 4 end
  257. static void ts3()
  258. {
  259. TriggerSequencer::Event seq[] =
  260. {
  261. {TriggerSequencer::TRIGGER, 0},
  262. {TriggerSequencer::END, 4}
  263. };
  264. TriggerSequencer ts(seq);
  265. bool firstLoop = true;
  266. for (int i = 0; i < 4; ++i) {
  267. //printf("--- loop ----\n");
  268. // 1
  269. ts.clock();
  270. if (firstLoop) {
  271. assert(ts.getTrigger());
  272. // we just primed loop at top, so it's got a ways
  273. assert(!ts.getEnd());
  274. firstLoop = false;
  275. } else {
  276. // second time around, need to clock the end of the last time
  277. assert(ts.getEnd());
  278. ts.reset(seq); // start it up again
  279. assert(ts.getTrigger()); // resetting should have set us up for a trigger
  280. }
  281. // 2
  282. ts.clock(); assert(!ts.getTrigger()); assert(!ts.getEnd());
  283. // 3
  284. ts.clock(); assert(!ts.getTrigger()); assert(!ts.getEnd());
  285. // 4
  286. ts.clock();
  287. assert(!ts.getTrigger());
  288. assert(!ts.getEnd());
  289. }
  290. }
  291. // test trigger seq with straight ahead 4/4 as generated by a grammar
  292. static void ts4()
  293. {
  294. TriggerSequencer::Event seq[] =
  295. {
  296. {TriggerSequencer::TRIGGER, 0},
  297. {TriggerSequencer::TRIGGER, 4},
  298. {TriggerSequencer::TRIGGER, 4},
  299. {TriggerSequencer::TRIGGER, 4},
  300. {TriggerSequencer::END, 4}
  301. };
  302. TriggerSequencer ts(seq);
  303. //bool firstLoop = true;
  304. for (int i = 0; i < 100; ++i) {
  305. bool firstTime = (i == 0);
  306. // repeating pattern of trigg, no, no, no
  307. for (int j = 0; j < 4; ++j) {
  308. for (int k = 0; k < 4; ++k) {
  309. // printf("test loop, i=%d, j=%d, k=%d\n", i, j, k);
  310. ts.clock();
  311. bool expectEnd = (k == 0) && (j == 0) && !firstTime;
  312. assert(ts.getEnd() == expectEnd);
  313. if (ts.getEnd()) {
  314. ts.reset(seq);
  315. }
  316. assert(ts.getTrigger() == (k == 0));
  317. }
  318. }
  319. }
  320. }
  321. /*******************************************************************************
  322. ** StochasticGrammarDictionary
  323. */
  324. #ifdef _DEBUG
  325. void gdt1()
  326. {
  327. assert(StochasticGrammarDictionary::getNumGrammars() > 0);
  328. for (int i = 0; i < StochasticGrammarDictionary::getNumGrammars(); ++i) {
  329. StochasticGrammarDictionary::Grammar g = StochasticGrammarDictionary::getGrammar(i);
  330. bool b = ProductionRule::isGrammarValid(g.rules, g.numRules, g.firstRule);
  331. assert(b);
  332. }
  333. }
  334. #endif
  335. /********************************************************************************************
  336. * GenerativeTriggerGenerator
  337. **********************************************************************************************/
  338. // test that we get some clocks and some not
  339. static void gtg0()
  340. {
  341. GKEY key = init1();
  342. GenerativeTriggerGenerator gtg(AudioMath::random(), rules, numRules, key);
  343. bool yes = false;
  344. bool no = false;
  345. for (int i = 0; i < 100000; ++i) {
  346. if (gtg.clock())
  347. yes = true;
  348. else
  349. no = true;
  350. if (yes && no) {
  351. //printf("clocked at %d\n", i);
  352. return;
  353. }
  354. }
  355. assert(false);
  356. }
  357. // test that we get everything in even quarter notes
  358. static void gtg1()
  359. {
  360. GKEY key = init1();
  361. std::set<int> counts;
  362. GenerativeTriggerGenerator gtg(AudioMath::random(), rules, numRules, key);
  363. int ct = 0;
  364. for (int i = 0; i < 10000; ++i) {
  365. bool b = gtg.clock();
  366. if (b) {
  367. //printf("clocked at %d\n", ct);
  368. counts.insert(ct);
  369. ct = 0;
  370. }
  371. ct++;
  372. }
  373. //counts.insert(50);
  374. assert(!counts.empty());
  375. for (std::set<int>::iterator it = counts.begin(); it != counts.end(); ++it) {
  376. int c = *it;
  377. if ((c % PPQ) != 0) {
  378. //printf("PPQ=%d, c modePPQ =%d\n", PPQ, (c % PPQ));
  379. //printf("2ppq = %d, 4ppq=%d\n", 2 * PPQ, 4 * PPQ);
  380. assert(false);
  381. }
  382. }
  383. }
  384. void testStochasticGrammar()
  385. {
  386. test0();
  387. testAllKeys();
  388. #ifdef _DEBUG
  389. gdt0();
  390. testGrammarSub(init0);
  391. testGrammarSub(init1);
  392. testGrammarSub(init2);
  393. #endif
  394. ts0();
  395. ts1();
  396. ts2();
  397. ts3();
  398. ts4();
  399. #ifdef _DEBUG
  400. gdt1();
  401. #endif
  402. gtg0();
  403. gtg1();
  404. }