Audio plugin host https://kx.studio/carla
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.

433 lines
11KB

  1. /*
  2. ZynAddSubFX - a software synthesizer
  3. NotePool.cpp - Pool of Synthesizer Engines And Note Instances
  4. Copyright (C) 2016 Mark McCurry
  5. This program is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License
  7. as published by the Free Software Foundation; either version 2
  8. of the License, or (at your option) any later version.
  9. */
  10. #include "NotePool.h"
  11. #include "../Misc/Allocator.h"
  12. #include "../Synth/SynthNote.h"
  13. #include <cstring>
  14. #include <cassert>
  15. #include <iostream>
  16. #define SUSTAIN_BIT 0x04
  17. #define NOTE_MASK 0x03
  18. enum NoteStatus {
  19. KEY_OFF = 0x00,
  20. KEY_PLAYING = 0x01,
  21. KEY_RELEASED_AND_SUSTAINED = 0x02,
  22. KEY_RELEASED = 0x03
  23. };
  24. NotePool::NotePool(void)
  25. :needs_cleaning(0)
  26. {
  27. memset(ndesc, 0, sizeof(ndesc));
  28. memset(sdesc, 0, sizeof(sdesc));
  29. }
  30. bool NotePool::NoteDescriptor::playing(void) const
  31. {
  32. return (status&NOTE_MASK) == KEY_PLAYING;
  33. }
  34. bool NotePool::NoteDescriptor::sustained(void) const
  35. {
  36. return (status&NOTE_MASK) == KEY_RELEASED_AND_SUSTAINED;
  37. }
  38. bool NotePool::NoteDescriptor::released(void) const
  39. {
  40. return (status&NOTE_MASK) == KEY_RELEASED;
  41. }
  42. bool NotePool::NoteDescriptor::off(void) const
  43. {
  44. return (status&NOTE_MASK) == KEY_OFF;
  45. }
  46. void NotePool::NoteDescriptor::setStatus(uint8_t s)
  47. {
  48. status &= ~NOTE_MASK;
  49. status |= (NOTE_MASK&s);
  50. }
  51. void NotePool::NoteDescriptor::doSustain(void)
  52. {
  53. setStatus(KEY_RELEASED_AND_SUSTAINED);
  54. }
  55. bool NotePool::NoteDescriptor::canSustain(void) const
  56. {
  57. return !(status & SUSTAIN_BIT);
  58. }
  59. void NotePool::NoteDescriptor::makeUnsustainable(void)
  60. {
  61. status |= SUSTAIN_BIT;
  62. }
  63. NotePool::activeNotesIter NotePool::activeNotes(NoteDescriptor &n)
  64. {
  65. const int off_d1 = &n-ndesc;
  66. int off_d2 = 0;
  67. assert(off_d1 <= POLYPHONY);
  68. for(int i=0; i<off_d1; ++i)
  69. off_d2 += ndesc[i].size;
  70. return NotePool::activeNotesIter{sdesc+off_d2,sdesc+off_d2+n.size};
  71. }
  72. bool NotePool::NoteDescriptor::operator==(NoteDescriptor nd)
  73. {
  74. return age == nd.age && note == nd.note && sendto == nd.sendto && size == nd.size && status == nd.status;
  75. }
  76. //return either the first unused descriptor or the last valid descriptor which
  77. //matches note/sendto
  78. static int getMergeableDescriptor(uint8_t note, uint8_t sendto, bool legato,
  79. NotePool::NoteDescriptor *ndesc)
  80. {
  81. int desc_id = 0;
  82. for(int i=0; i<POLYPHONY; ++i, ++desc_id)
  83. if(ndesc[desc_id].off())
  84. break;
  85. if(desc_id != 0) {
  86. auto &nd = ndesc[desc_id-1];
  87. if(nd.age == 0 && nd.note == note && nd.sendto == sendto
  88. && nd.playing() && nd.legatoMirror == legato && nd.canSustain())
  89. return desc_id-1;
  90. }
  91. //Out of free descriptors
  92. if(desc_id >= POLYPHONY || !ndesc[desc_id].off()) {
  93. return -1;
  94. }
  95. return desc_id;
  96. }
  97. NotePool::activeDescIter NotePool::activeDesc(void)
  98. {
  99. cleanup();
  100. return activeDescIter{*this};
  101. }
  102. NotePool::constActiveDescIter NotePool::activeDesc(void) const
  103. {
  104. const_cast<NotePool*>(this)->cleanup();
  105. return constActiveDescIter{*this};
  106. }
  107. int NotePool::usedNoteDesc(void) const
  108. {
  109. if(needs_cleaning)
  110. const_cast<NotePool*>(this)->cleanup();
  111. int cnt = 0;
  112. for(int i=0; i<POLYPHONY; ++i)
  113. cnt += (ndesc[i].size != 0);
  114. return cnt;
  115. }
  116. int NotePool::usedSynthDesc(void) const
  117. {
  118. if(needs_cleaning)
  119. const_cast<NotePool*>(this)->cleanup();
  120. int cnt = 0;
  121. for(int i=0; i<POLYPHONY*EXPECTED_USAGE; ++i)
  122. cnt += (bool)sdesc[i].note;
  123. return cnt;
  124. }
  125. void NotePool::insertNote(uint8_t note, uint8_t sendto, SynthDescriptor desc, bool legato)
  126. {
  127. //Get first free note descriptor
  128. int desc_id = getMergeableDescriptor(note, sendto, legato, ndesc);
  129. assert(desc_id != -1);
  130. ndesc[desc_id].note = note;
  131. ndesc[desc_id].sendto = sendto;
  132. ndesc[desc_id].size += 1;
  133. ndesc[desc_id].status = KEY_PLAYING;
  134. ndesc[desc_id].legatoMirror = legato;
  135. //Get first free synth descriptor
  136. int sdesc_id = 0;
  137. while(sdesc[sdesc_id].note && sdesc_id < POLYPHONY*EXPECTED_USAGE)
  138. sdesc_id++;
  139. assert(sdesc_id < POLYPHONY*EXPECTED_USAGE);
  140. sdesc[sdesc_id] = desc;
  141. };
  142. void NotePool::upgradeToLegato(void)
  143. {
  144. for(auto &d:activeDesc())
  145. if(d.playing())
  146. for(auto &s:activeNotes(d))
  147. insertLegatoNote(d.note, d.sendto, s);
  148. }
  149. void NotePool::insertLegatoNote(uint8_t note, uint8_t sendto, SynthDescriptor desc)
  150. {
  151. assert(desc.note);
  152. try {
  153. desc.note = desc.note->cloneLegato();
  154. insertNote(note, sendto, desc, true);
  155. } catch (std::bad_alloc &ba) {
  156. std::cerr << "failed to insert legato note: " << ba.what() << std::endl;
  157. }
  158. };
  159. //There should only be one pair of notes which are still playing
  160. void NotePool::applyLegato(LegatoParams &par)
  161. {
  162. for(auto &desc:activeDesc()) {
  163. desc.note = par.midinote;
  164. for(auto &synth:activeNotes(desc))
  165. try {
  166. synth.note->legatonote(par);
  167. } catch (std::bad_alloc& ba) {
  168. std::cerr << "failed to create legato note: " << ba.what() << std::endl;
  169. }
  170. }
  171. }
  172. void NotePool::makeUnsustainable(uint8_t note)
  173. {
  174. for(auto &desc:activeDesc()) {
  175. if(desc.note == note) {
  176. desc.makeUnsustainable();
  177. if(desc.sustained())
  178. release(desc);
  179. }
  180. }
  181. }
  182. bool NotePool::full(void) const
  183. {
  184. for(int i=0; i<POLYPHONY; ++i)
  185. if(ndesc[i].off())
  186. return false;
  187. return true;
  188. }
  189. bool NotePool::synthFull(int sdesc_count) const
  190. {
  191. int actually_free=sizeof(sdesc)/sizeof(sdesc[0]);
  192. for(const auto &desc:activeDesc()) {
  193. actually_free -= desc.size;
  194. }
  195. return actually_free < sdesc_count;
  196. }
  197. //Note that isn't KEY_PLAYING or KEY_RELASED_AND_SUSTAINING
  198. bool NotePool::existsRunningNote(void) const
  199. {
  200. //printf("runing note # =%d\n", getRunningNotes());
  201. return getRunningNotes();
  202. }
  203. int NotePool::getRunningNotes(void) const
  204. {
  205. bool running[256] = {0};
  206. for(auto &desc:activeDesc()) {
  207. //printf("note!(%d)\n", desc.note);
  208. if(desc.playing() || desc.sustained())
  209. running[desc.note] = true;
  210. }
  211. int running_count = 0;
  212. for(int i=0; i<256; ++i)
  213. running_count += running[i];
  214. return running_count;
  215. }
  216. void NotePool::enforceKeyLimit(int limit)
  217. {
  218. int notes_to_kill = getRunningNotes() - limit;
  219. if(notes_to_kill <= 0)
  220. return;
  221. NoteDescriptor *to_kill = NULL;
  222. unsigned oldest = 0;
  223. for(auto &nd : activeDesc()) {
  224. if(to_kill == NULL) {
  225. //There must be something to kill
  226. oldest = nd.age;
  227. to_kill = &nd;
  228. } else if(to_kill->released() && nd.playing()) {
  229. //Prefer to kill off a running note
  230. oldest = nd.age;
  231. to_kill = &nd;
  232. } else if(nd.age > oldest && !(to_kill->playing() && nd.released())) {
  233. //Get an older note when it doesn't move from running to released
  234. oldest = nd.age;
  235. to_kill = &nd;
  236. }
  237. }
  238. if(to_kill) {
  239. auto &tk = *to_kill;
  240. if(tk.released() || tk.sustained())
  241. kill(*to_kill);
  242. else
  243. entomb(*to_kill);
  244. }
  245. }
  246. void NotePool::releasePlayingNotes(void)
  247. {
  248. for(auto &d:activeDesc()) {
  249. if(d.playing() || d.sustained()) {
  250. d.setStatus(KEY_RELEASED);
  251. for(auto s:activeNotes(d))
  252. s.note->releasekey();
  253. }
  254. }
  255. }
  256. void NotePool::release(NoteDescriptor &d)
  257. {
  258. d.setStatus(KEY_RELEASED);
  259. for(auto s:activeNotes(d))
  260. s.note->releasekey();
  261. }
  262. void NotePool::killAllNotes(void)
  263. {
  264. for(auto &d:activeDesc())
  265. kill(d);
  266. }
  267. void NotePool::killNote(uint8_t note)
  268. {
  269. for(auto &d:activeDesc()) {
  270. if(d.note == note)
  271. kill(d);
  272. }
  273. }
  274. void NotePool::kill(NoteDescriptor &d)
  275. {
  276. d.setStatus(KEY_OFF);
  277. for(auto &s:activeNotes(d))
  278. kill(s);
  279. }
  280. void NotePool::kill(SynthDescriptor &s)
  281. {
  282. //printf("Kill synth...\n");
  283. s.note->memory.dealloc(s.note);
  284. needs_cleaning = true;
  285. }
  286. void NotePool::entomb(NoteDescriptor &d)
  287. {
  288. d.setStatus(KEY_RELEASED);
  289. for(auto &s:activeNotes(d))
  290. s.note->entomb();
  291. }
  292. const char *getStatus(int status_bits)
  293. {
  294. switch(status_bits)
  295. {
  296. case 0: return "OFF ";
  297. case 1: return "PLAY";
  298. case 2: return "SUST";
  299. case 3: return "RELA";
  300. default: return "INVD";
  301. }
  302. }
  303. void NotePool::cleanup(void)
  304. {
  305. if(!needs_cleaning)
  306. return;
  307. needs_cleaning = false;
  308. int new_length[POLYPHONY] = {0};
  309. int cur_length[POLYPHONY] = {0};
  310. //printf("Cleanup Start\n");
  311. //dump();
  312. //Identify the current length of all segments
  313. //and the lengths discarding invalid entries
  314. int last_valid_desc = 0;
  315. for(int i=0; i<POLYPHONY; ++i)
  316. if(!ndesc[i].off())
  317. last_valid_desc = i;
  318. //Find the real numbers of allocated notes
  319. {
  320. int cum_old = 0;
  321. for(int i=0; i<=last_valid_desc; ++i) {
  322. cur_length[i] = ndesc[i].size;
  323. for(int j=0; j<ndesc[i].size; ++j)
  324. new_length[i] += (bool)sdesc[cum_old++].note;
  325. }
  326. }
  327. //Move the note descriptors
  328. {
  329. int cum_new = 0;
  330. for(int i=0; i<=last_valid_desc; ++i) {
  331. ndesc[i].size = new_length[i];
  332. if(new_length[i] != 0)
  333. ndesc[cum_new++] = ndesc[i];
  334. else
  335. ndesc[i].setStatus(KEY_OFF);
  336. }
  337. memset(ndesc+cum_new, 0, sizeof(*ndesc)*(POLYPHONY-cum_new));
  338. }
  339. //Move the synth descriptors
  340. {
  341. int total_notes=0;
  342. for(int i=0; i<=last_valid_desc; ++i)
  343. total_notes+=cur_length[i];
  344. int cum_new = 0;
  345. for(int i=0; i<total_notes; ++i)
  346. if(sdesc[i].note)
  347. sdesc[cum_new++] = sdesc[i];
  348. memset(sdesc+cum_new, 0, sizeof(*sdesc)*(POLYPHONY*EXPECTED_USAGE-cum_new));
  349. }
  350. //printf("Cleanup Done\n");
  351. //dump();
  352. }
  353. void NotePool::dump(void)
  354. {
  355. printf("NotePool::dump<\n");
  356. const char *format =
  357. " Note %d:%d age(%d) note(%d) sendto(%d) status(%s) legato(%d) type(%d) kit(%d) ptr(%p)\n";
  358. int note_id=0;
  359. int descriptor_id=0;
  360. for(auto &d:activeDesc()) {
  361. descriptor_id += 1;
  362. for(auto &s:activeNotes(d)) {
  363. note_id += 1;
  364. printf(format,
  365. note_id, descriptor_id,
  366. d.age, d.note, d.sendto,
  367. getStatus(d.status), d.legatoMirror, s.type, s.kit, s.note);
  368. }
  369. }
  370. printf(">NotePool::dump\n");
  371. }