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.

389 lines
9.5KB

  1. #include <assert.h>
  2. #include <memory>
  3. #include "MidiLock.h"
  4. #include "MidiSelectionModel.h"
  5. #include "MidiSong.h"
  6. #include "MidiTrack.h"
  7. #include "asserts.h"
  8. static void testCanInsert()
  9. {
  10. auto lock = MidiLock::make();
  11. MidiTrack mt(lock);
  12. MidiLocker l(lock);
  13. MidiNoteEventPtr ev = std::make_shared<MidiNoteEvent>();
  14. ev->pitchCV = 3.3f;
  15. ev->startTime = 55.f;
  16. assert(mt.size() == 0);
  17. mt.insertEvent(ev);
  18. assert(mt.size() == 1);
  19. mt.insertEnd(100);
  20. // MidiEndEventPtr end = std::make_shared<MidiEndEvent>();
  21. // end->startTime = 100;
  22. // mt.insertEvent(end);
  23. MidiEventPtr ev2 = mt._testGetVector()[0];
  24. assert(*ev2 == *ev);
  25. mt.assertValid();
  26. }
  27. static void testInsertSorted()
  28. {
  29. auto lock = MidiLock::make();
  30. MidiTrack mt(lock);
  31. MidiLocker l(lock);
  32. MidiNoteEventPtr ev = std::make_shared<MidiNoteEvent>();
  33. ev->pitchCV = 3.3f;
  34. ev->startTime = 11;
  35. MidiNoteEventPtr ev2 = std::make_shared<MidiNoteEvent>();
  36. ev2->pitchCV = 4.4f;
  37. ev2->startTime = 1;
  38. mt.insertEvent(ev);
  39. mt.insertEvent(ev2);
  40. mt.insertEnd(100);
  41. auto mv = mt._testGetVector();
  42. MidiEventPtr ev3 = mv.at(0);
  43. MidiNoteEventPtr no3 = safe_cast<MidiNoteEvent>(ev3);
  44. assert(ev3 == ev2);
  45. ev3 = mv.at(1);
  46. assert(ev3 == ev);
  47. mt.assertValid();
  48. }
  49. static void testDelete()
  50. {
  51. auto lock = MidiLock::make();
  52. MidiTrack mt(lock);
  53. MidiLocker l(lock);
  54. MidiNoteEventPtr ev = std::make_shared<MidiNoteEvent>();
  55. ev->pitchCV = 33;
  56. ev->startTime = 11;
  57. mt.insertEvent(ev);
  58. mt.deleteEvent(*ev);
  59. assert(mt.size() == 0);
  60. }
  61. static void testDelete2()
  62. {
  63. auto lock = MidiLock::make();
  64. MidiTrack mt(lock);
  65. MidiLocker l(lock);
  66. MidiNoteEventPtr ev = std::make_shared<MidiNoteEvent>();
  67. ev->pitchCV = 33;
  68. ev->startTime = 11;
  69. mt.insertEvent(ev);
  70. MidiNoteEventPtr ev2 = std::make_shared<MidiNoteEvent>();
  71. ev2->pitchCV = 44;
  72. mt.insertEvent(ev2);
  73. mt.deleteEvent(*ev2); // delete the second one, with pitch 44
  74. auto mv = mt._testGetVector();
  75. assert(mt.size() == 1);
  76. MidiNoteEventPtr no = safe_cast<MidiNoteEvent>(mv[0]);
  77. assert(no->pitchCV == 33);
  78. }
  79. static void testDelete3()
  80. {
  81. auto lock = MidiLock::make();
  82. MidiTrack mt(lock);
  83. MidiLocker l(lock);
  84. MidiNoteEventPtr ev = std::make_shared<MidiNoteEvent>();
  85. #ifdef _DEBUG
  86. assert(MidiEvent::_count > 0);
  87. #endif
  88. ev->pitchCV = 44;
  89. ev->startTime = 11;
  90. mt.insertEvent(ev);
  91. MidiNoteEventPtr ev2 = std::make_shared<MidiNoteEvent>();
  92. ev2->pitchCV = 33;
  93. mt.insertEvent(ev2);
  94. MidiNoteEventPtr ev3 = std::make_shared<MidiNoteEvent>();
  95. ev3->pitchCV = 44;
  96. mt.deleteEvent(*ev); // delete the first one, with pitch 44
  97. auto mv = mt._testGetVector();
  98. assert(mt.size() == 1);
  99. MidiNoteEventPtr no = safe_cast<MidiNoteEvent>(mv[0]);
  100. assert(no->pitchCV == 33);
  101. }
  102. static void testFind1()
  103. {
  104. auto lock = MidiLock::make();
  105. MidiTrack mt(lock);
  106. MidiLocker l(lock);
  107. MidiNoteEventPtr ev = std::make_shared<MidiNoteEvent>();
  108. ev->pitchCV = 5;
  109. mt.insertEvent(ev);
  110. auto found = mt.findEventDeep(*ev);
  111. assert(found->second == ev);
  112. }
  113. static void testTimeRange0()
  114. {
  115. auto lock = MidiLock::make();
  116. MidiTrack mt(lock);
  117. MidiLocker l(lock);
  118. MidiNoteEventPtr ev = std::make_shared<MidiNoteEvent>();
  119. ev->startTime = 100;
  120. mt.insertEvent(ev);
  121. MidiTrack::iterator_pair its = mt.timeRange(99, 101);
  122. assert(its.first != its.second);
  123. auto count = std::distance(its.first, its.second);
  124. assertEQ(count, 1);
  125. its = mt.timeRange(101, 1000);
  126. assert(its.first == its.second);
  127. count = std::distance(its.first, its.second);
  128. assertEQ(count, 0);
  129. }
  130. static void testNoteTimeRange0()
  131. {
  132. auto lock = MidiLock::make();
  133. MidiTrack mt(lock);
  134. MidiLocker l(lock);
  135. MidiNoteEventPtr ev = std::make_shared<MidiNoteEvent>();
  136. ev->startTime = 100;
  137. mt.insertEvent(ev);
  138. MidiTrack::note_iterator_pair its = mt.timeRangeNotes(99, 101);
  139. assert(its.first != its.second);
  140. auto count = std::distance(its.first, its.second);
  141. assertEQ(count, 1);
  142. its = mt.timeRangeNotes(101, 1000);
  143. assert(its.first == its.second);
  144. count = std::distance(its.first, its.second);
  145. assertEQ(count, 0);
  146. }
  147. //should skip over non-note events
  148. static void testNoteTimeRange0Mixed()
  149. {
  150. auto lock = MidiLock::make();
  151. MidiTrack mt(lock);
  152. MidiLocker l(lock);
  153. MidiNoteEventPtr ev = std::make_shared<MidiNoteEvent>();
  154. ev->startTime = 100;
  155. mt.insertEvent(ev);
  156. MidiTestEventPtr tev = std::make_shared<MidiTestEvent>();
  157. tev->startTime = 100.1f;
  158. mt.insertEvent(tev);
  159. MidiTrack::note_iterator_pair its = mt.timeRangeNotes(99, 101);
  160. assert(its.first != its.second);
  161. auto count = std::distance(its.first, its.second);
  162. assertEQ(count, 1);
  163. its = mt.timeRangeNotes(101, 1000);
  164. assert(its.first == its.second);
  165. count = std::distance(its.first, its.second);
  166. assertEQ(count, 0);
  167. }
  168. static void testTimeRange1()
  169. {
  170. auto lock = MidiLock::make();
  171. MidiTrack mt(lock);
  172. MidiLocker l(lock);
  173. MidiNoteEventPtr ev = std::make_shared<MidiNoteEvent>();
  174. ev->startTime = 100;
  175. mt.insertEvent(ev);
  176. ev = std::make_shared<MidiNoteEvent>();
  177. ev->startTime = 110;
  178. mt.insertEvent(ev);
  179. ev = std::make_shared<MidiNoteEvent>();
  180. ev->startTime = 120;
  181. mt.insertEvent(ev);
  182. ev = std::make_shared<MidiNoteEvent>();
  183. ev->startTime = 130;
  184. mt.insertEvent(ev);
  185. MidiTrack::iterator_pair its = mt.timeRange(110, 120);
  186. assert(its.first != its.second);
  187. auto count = std::distance(its.first, its.second);
  188. assertEQ(count, 2);
  189. }
  190. static void testNoteTimeRange1()
  191. {
  192. auto lock = MidiLock::make();
  193. MidiTrack mt(lock);
  194. MidiLocker l(lock);
  195. MidiNoteEventPtr ev = std::make_shared<MidiNoteEvent>();
  196. MidiTestEventPtr evt = std::make_shared<MidiTestEvent>();
  197. // This is a terrible hack putting the "same" event in multiple time.
  198. ev->startTime = 100;
  199. mt.insertEvent(ev);
  200. ev = std::make_shared<MidiNoteEvent>();
  201. ev->startTime = 110;
  202. mt.insertEvent(ev);
  203. ev = std::make_shared<MidiNoteEvent>();
  204. ev->startTime = 120;
  205. mt.insertEvent(ev);
  206. ev = std::make_shared<MidiNoteEvent>();
  207. ev->startTime = 130;
  208. mt.insertEvent(ev);
  209. evt->startTime = 111;
  210. mt.insertEvent(evt);
  211. MidiTrack::note_iterator_pair its = mt.timeRangeNotes(110, 120);
  212. assert(its.first != its.second);
  213. auto count = std::distance(its.first, its.second);
  214. assertEQ(count, 2);
  215. }
  216. static void testSameTime()
  217. {
  218. printf("ADD A TEST FOR SAME TIME\n");
  219. }
  220. static void testSong()
  221. {
  222. auto p = MidiSong::makeTest(MidiTrack::TestContent::eightQNotes, 0);
  223. assert(_mdb > 0);
  224. p->assertValid();
  225. }
  226. static void testQuant()
  227. {
  228. float pitchCV = 0;
  229. const float quarterStep = PitchUtils::semitone / 2.f;
  230. const float eighthStep = PitchUtils::semitone / 4.f;
  231. const int x = PitchUtils::cvToSemitone(pitchCV);
  232. assertEQ(PitchUtils::cvToSemitone(pitchCV + eighthStep), x); // round to middle
  233. assertEQ(PitchUtils::cvToSemitone(pitchCV - eighthStep), x); // round to middle
  234. assertEQ(PitchUtils::cvToSemitone(pitchCV + (quarterStep * .99f)), x); // round to middle
  235. assertEQ(PitchUtils::cvToSemitone(pitchCV - (quarterStep * .99f)), x); // round to middle
  236. assertEQ(PitchUtils::cvToSemitone(pitchCV + (quarterStep * 1.01f)), x+1); // round to middle
  237. assertEQ(PitchUtils::cvToSemitone(pitchCV - (quarterStep * 1.01f)), x-1); // round to middle
  238. // TODO: why isn't this 64 - looks at specs for VCV and MIDI
  239. //assertEQ(x, 64);
  240. }
  241. static void testSelection()
  242. {
  243. MidiSelectionModel sel;
  244. MidiNoteEventPtr note1 = std::make_shared<MidiNoteEvent>();
  245. MidiNoteEventPtr note2 = std::make_shared<MidiNoteEvent>();
  246. note1->startTime = 1;
  247. note1->pitchCV = 1.1f;
  248. note2->startTime = 2;
  249. note2->pitchCV = 2.1f;
  250. assert(sel.empty());
  251. assertEQ(sel.size(), 0);
  252. sel.select(note2);
  253. sel.extendSelection(note1);
  254. assert(!sel.empty());
  255. assertEQ(sel.size(), 2);
  256. MidiSelectionModel::const_iterator it = sel.begin();
  257. assert(it != sel.end());
  258. MidiEventPtr ev = *it;
  259. assert(*ev == *note1);
  260. ++it;
  261. assert(it != sel.end());
  262. ev = *it;
  263. assert(*ev == *note2);
  264. ++it;
  265. assert(it == sel.end());
  266. }
  267. static void testSelection2()
  268. {
  269. MidiSelectionModel selOrig;
  270. MidiNoteEventPtr note1 = std::make_shared<MidiNoteEvent>();
  271. MidiNoteEventPtr note2 = std::make_shared<MidiNoteEvent>();
  272. MidiNoteEventPtr note3 = std::make_shared<MidiNoteEvent>();
  273. note1->startTime = 1;
  274. note1->pitchCV = 1.1f;
  275. note2->startTime = 2;
  276. note2->pitchCV = 2.1f;
  277. note3->startTime = 3;
  278. assert(selOrig.empty());
  279. assertEQ(selOrig.size(), 0);
  280. selOrig.select(note2);
  281. selOrig.extendSelection(note1);
  282. assert(!selOrig.empty());
  283. assertEQ(selOrig.size(), 2);
  284. MidiSelectionModelPtr sel = selOrig.clone();
  285. assert(sel);
  286. assert(sel->size() == selOrig.size());
  287. assert(sel->isSelectedDeep(note1));
  288. assert(sel->isSelectedDeep(note2));
  289. assert(!sel->isSelectedDeep(note3));
  290. }
  291. void testMidiDataModel()
  292. {
  293. assertNoMidi(); // check for leaks
  294. testCanInsert();
  295. testInsertSorted();
  296. testDelete();
  297. testDelete2();
  298. testDelete3();
  299. testFind1();
  300. testTimeRange0();
  301. testNoteTimeRange0();
  302. testNoteTimeRange0Mixed();
  303. testTimeRange1();
  304. testNoteTimeRange1();
  305. testSameTime();
  306. testSong();
  307. testQuant();
  308. testSelection();
  309. testSelection2();
  310. assertNoMidi(); // check for leaks
  311. }