PageRenderTime 76ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 1ms

/frontends/CsoundAC/allegro.cpp

https://github.com/tim81cortes/csound
C++ | 3516 lines | 2491 code | 387 blank | 638 comment | 558 complexity | f781d11ec5458eac6955eee0a82cddf9 MD5 | raw file
Possible License(s): LGPL-3.0, LGPL-2.1, BSD-3-Clause, LGPL-2.0
  1. // Allegro: music representation system, with
  2. // extensible in-memory sequence structure
  3. // upward compatible with MIDI
  4. // implementations in C++ and Serpent
  5. // external, text-based representation
  6. // compatible with Aura
  7. //
  8. /* CHANGE LOG:
  9. 04 apr 03 -- fixed bug in add_track that caused infinite loop
  10. */
  11. #include "assert.h"
  12. #include "stdlib.h"
  13. #include "stdio.h"
  14. #include "string.h"
  15. #include "memory.h"
  16. #include <iostream>
  17. #include <fstream>
  18. using namespace std;
  19. #include "allegro.h"
  20. #include "algrd_internal.h"
  21. #include "algsmfrd_internal.h"
  22. // #include "trace.h" -- only needed for debugging
  23. #include "math.h"
  24. #define STREQL(x, y) (strcmp(x, y) == 0)
  25. #define MAX(x, y) ((x) > (y) ? (x) : (y))
  26. #define ROUND(x) ((int) ((x) + 0.5))
  27. // 4311 is type cast ponter to long warning
  28. // 4996 is warning against strcpy
  29. // 4267 is size_t to long warning
  30. #pragma warning(disable: 4311 4996 4267)
  31. Alg_atoms symbol_table;
  32. Serial_read_buffer Alg_track::ser_read_buf; // declare the static variables
  33. Serial_write_buffer Alg_track::ser_write_buf;
  34. bool within(double d1, double d2, double epsilon)
  35. {
  36. d1 -= d2;
  37. return d1 < epsilon && d1 > -epsilon;
  38. }
  39. char *heapify(const char *s)
  40. {
  41. char *h = new char[strlen(s) + 1];
  42. strcpy(h, s);
  43. return h;
  44. }
  45. void Alg_atoms::expand()
  46. {
  47. maxlen = (maxlen + 5); // extra growth for small sizes
  48. maxlen += (maxlen >> 2); // add 25%
  49. Alg_attribute *new_atoms = new Alg_attribute[maxlen];
  50. // now do copy
  51. memcpy(new_atoms, atoms, len * sizeof(Alg_attribute));
  52. if (atoms) delete[] atoms;
  53. atoms = new_atoms;
  54. }
  55. // insert_new -- insert an attribute name and type
  56. //
  57. // attributes are stored as a string consisting of the type
  58. // (a char) followed by the attribute name. This makes it
  59. // easy to retrieve the type or the name or both.
  60. //
  61. Alg_attribute Alg_atoms::insert_new(const char *name, char attr_type)
  62. {
  63. if (len == maxlen) expand();
  64. char *h = new char[strlen(name) + 2];
  65. strcpy(h + 1, name);
  66. *h = attr_type;
  67. atoms[len++] = h;
  68. return h;
  69. }
  70. Alg_attribute Alg_atoms::insert_attribute(Alg_attribute attr)
  71. {
  72. // should use hash algorithm
  73. for (int i = 0; i < len; i++) {
  74. if (STREQL(attr, atoms[i])) {
  75. return atoms[i];
  76. }
  77. }
  78. return insert_new(attr + 1, attr[0]);
  79. }
  80. Alg_attribute Alg_atoms::insert_string(const char *name)
  81. {
  82. char attr_type = name[strlen(name) - 1];
  83. for (int i = 0; i < len; i++) {
  84. if (attr_type == atoms[i][0] &&
  85. STREQL(name, atoms[i] + 1)) {
  86. return atoms[i];
  87. }
  88. }
  89. return insert_new(name, attr_type);
  90. }
  91. void Alg_parameter::copy(Alg_parameter_ptr parm)
  92. {
  93. *this = *parm; // copy all fields
  94. // if the value is a string, copy the string
  95. if (attr_type() == 's') {
  96. s = heapify(s);
  97. }
  98. }
  99. void Alg_parameter::show()
  100. {
  101. switch (attr[0]) {
  102. case 'r':
  103. printf("%s:%g", attr_name(), r);
  104. break;
  105. case 's':
  106. printf("%s:%s", attr_name(), s);
  107. break;
  108. case 'i':
  109. printf("%s:%ld", attr_name(), i);
  110. break;
  111. case 'l':
  112. printf("%s:%s", attr_name(), (l ? "t" : "f"));
  113. break;
  114. case 'a':
  115. printf("%s:%s", attr_name(), a);
  116. break;
  117. }
  118. }
  119. Alg_parameter::~Alg_parameter()
  120. {
  121. if (attr_type() == 's' && s) {
  122. delete[] s;
  123. }
  124. }
  125. void Alg_parameters::insert_real(Alg_parameters **list, const char *name,
  126. double r)
  127. {
  128. Alg_parameters_ptr a = new Alg_parameters(*list);
  129. *list = a;
  130. a->parm.set_attr(symbol_table.insert_string(name));
  131. a->parm.r = r;
  132. assert(a->parm.attr_type() == 'r');
  133. }
  134. void Alg_parameters::insert_string(Alg_parameters **list, const char *name,
  135. const char *s)
  136. {
  137. Alg_parameters_ptr a = new Alg_parameters(*list);
  138. *list = a;
  139. a->parm.set_attr(symbol_table.insert_string(name));
  140. // string is deleted when parameter is deleted
  141. a->parm.s = heapify(s);
  142. assert(a->parm.attr_type() == 's');
  143. }
  144. void Alg_parameters::insert_integer(Alg_parameters **list, const char *name,
  145. long i)
  146. {
  147. Alg_parameters_ptr a = new Alg_parameters(*list);
  148. *list = a;
  149. a->parm.set_attr(symbol_table.insert_string(name));
  150. a->parm.i = i;
  151. assert(a->parm.attr_type() == 'i');
  152. }
  153. void Alg_parameters::insert_logical(Alg_parameters **list, const char *name,
  154. bool l)
  155. {
  156. Alg_parameters_ptr a = new Alg_parameters(*list);
  157. *list = a;
  158. a->parm.set_attr(symbol_table.insert_string(name));
  159. a->parm.l = l;
  160. assert(a->parm.attr_type() == 'l');
  161. }
  162. void Alg_parameters::insert_atom(Alg_parameters **list, const char *name,
  163. const char *s)
  164. {
  165. Alg_parameters_ptr a = new Alg_parameters(*list);
  166. *list = a;
  167. a->parm.set_attr(symbol_table.insert_string(name));
  168. a->parm.a = symbol_table.insert_string(s);
  169. assert(a->parm.attr_type() == 'a');
  170. }
  171. Alg_parameters *Alg_parameters::remove_key(Alg_parameters **list,
  172. const char *name)
  173. {
  174. while (*list) {
  175. if (STREQL((*list)->parm.attr_name(), name)) {
  176. Alg_parameters_ptr p = *list;
  177. *list = p->next;
  178. p->next = NULL;
  179. return p; // caller should free this pointer
  180. }
  181. list = &((*list)->next);
  182. }
  183. return NULL;
  184. }
  185. Alg_parameter_ptr Alg_parameters::find(Alg_attribute attr)
  186. {
  187. assert(attr);
  188. Alg_parameters_ptr temp = this;
  189. while (temp) {
  190. if (temp->parm.attr == attr) {
  191. return &(temp->parm);
  192. }
  193. }
  194. return NULL;
  195. }
  196. int Alg_event::get_type_code()
  197. {
  198. if (!is_note()) {
  199. const char* attr = get_attribute();
  200. if (STREQL(attr, "gater")) // volume change
  201. return ALG_GATE;
  202. if (STREQL(attr, "bendr")) // pitch bend
  203. return ALG_BEND;
  204. if (strncmp(attr, "control", 7) == 0) // control change
  205. // note that midi control changes have attributes of the form
  206. // "control<n>" where n is the decimal number (as a character string)
  207. // of the midi controller, e.g. control2 is the breath controller.
  208. // We don't check for decimal numbers in the range 0-127, so any
  209. // attribute that begins with "control" is an ALG_CONTROL:
  210. return ALG_CONTROL;
  211. if (STREQL(attr, "programi")) // program change
  212. return ALG_PROGRAM;
  213. if (STREQL(attr, "pressurer")) // pressure change
  214. return ALG_PRESSURE;
  215. if (STREQL(attr, "keysigi")) // key signature
  216. return ALG_KEYSIG;
  217. if (STREQL(attr, "timesig_numi")) // time signature numerator
  218. return ALG_TIMESIG_NUM;
  219. if (STREQL(attr, "timesig_deni")) // time signature denominator
  220. return ALG_TIMESIG_DEN;
  221. return ALG_OTHER;
  222. }
  223. return ALG_NOTE; // it is a note
  224. }
  225. void Alg_event::set_parameter(Alg_parameter_ptr new_parameter)
  226. {
  227. Alg_parameter_ptr parm;
  228. if (is_note()) {
  229. Alg_note_ptr note = (Alg_note_ptr) this;
  230. parm = note->parameters->find(new_parameter->attr);
  231. if (!parm) {
  232. note->parameters = new Alg_parameters(note->parameters);
  233. parm = &(note->parameters->parm);
  234. }
  235. } else { // update
  236. Alg_update_ptr update = (Alg_update_ptr) this;
  237. parm = &(update->parameter);
  238. }
  239. parm->copy(new_parameter); // copy entire parameter
  240. }
  241. void Alg_event::set_string_value(const char *a, const char *value)
  242. {
  243. assert(a); // must be non-null
  244. Alg_attribute attr = symbol_table.insert_string(a);
  245. assert(attr[0] == 's');
  246. Alg_parameter parm;
  247. parm.set_attr(attr);
  248. parm.s = value;
  249. set_parameter(&parm);
  250. parm.s = NULL; // do this to prevent string from being freed
  251. }
  252. void Alg_event::set_real_value(const char *a, double value)
  253. {
  254. assert(a); // must be non-null
  255. // attr is like a, but it has the type code prefixed for
  256. // fast lookup, and it is a unique string in symbol_table
  257. // e.g. a="attackr" -> attr="rattackr"
  258. Alg_attribute attr = symbol_table.insert_string(a);
  259. assert(attr[0] == 'r');
  260. Alg_parameter parm;
  261. parm.set_attr(attr);
  262. parm.r = value;
  263. set_parameter(&parm);
  264. // since type is 'r' we don't have to NULL the string
  265. }
  266. void Alg_event::set_logical_value(const char *a, bool value)
  267. {
  268. assert(a); // must be non-null
  269. Alg_attribute attr = symbol_table.insert_string(a);
  270. assert(attr[0] == 'l');
  271. Alg_parameter parm;
  272. parm.set_attr(attr);
  273. parm.l = value;
  274. set_parameter(&parm);
  275. // since type is 'l' we don't have to NULL the string
  276. }
  277. void Alg_event::set_integer_value(const char *a, long value)
  278. {
  279. assert(a); // must be non-null
  280. Alg_attribute attr = symbol_table.insert_string(a);
  281. assert(attr[0] == 'i');
  282. Alg_parameter parm;
  283. parm.set_attr(attr);
  284. parm.i = value;
  285. set_parameter(&parm);
  286. // since tpye is 'i' we don't have to NULL the string
  287. }
  288. void Alg_event::set_atom_value(const char *a, const char *value)
  289. {
  290. assert(a); // must be non-null
  291. Alg_attribute attr = symbol_table.insert_string(a);
  292. assert(attr[0] == 'a');
  293. Alg_parameter parm;
  294. parm.set_attr(attr);
  295. parm.a = value;
  296. set_parameter(&parm);
  297. /* since type is 'a' we don't have to null the string */
  298. }
  299. float Alg_event::get_pitch()
  300. {
  301. assert(is_note());
  302. Alg_note* note = (Alg_note *) this;
  303. return note->pitch;
  304. }
  305. float Alg_event::get_loud()
  306. {
  307. assert(is_note());
  308. Alg_note* note = (Alg_note *) this;
  309. return note->loud;
  310. }
  311. double Alg_event::get_start_time()
  312. {
  313. assert(is_note());
  314. Alg_note* note = (Alg_note *) this;
  315. return note->time;
  316. }
  317. double Alg_event::get_end_time()
  318. {
  319. assert(is_note());
  320. Alg_note* note = (Alg_note *) this;
  321. return note->time + note->dur;
  322. }
  323. double Alg_event::get_duration()
  324. {
  325. assert(is_note());
  326. Alg_note* note = (Alg_note *) this;
  327. return note->dur;
  328. }
  329. void Alg_event::set_pitch(float p)
  330. {
  331. assert(is_note());
  332. Alg_note* note = (Alg_note *) this;
  333. note->pitch = p;
  334. }
  335. void Alg_event::set_loud(float l)
  336. {
  337. assert(is_note());
  338. Alg_note *note = (Alg_note *) this;
  339. note->loud = l;
  340. }
  341. void Alg_event::set_duration(double d)
  342. {
  343. assert(is_note());
  344. Alg_note* note = (Alg_note *) this;
  345. note->dur = d;
  346. }
  347. bool Alg_event::has_attribute(const char *a)
  348. {
  349. assert(is_note());
  350. assert(a); // must be non-null
  351. Alg_note* note = (Alg_note *) this;
  352. Alg_attribute attr = symbol_table.insert_string(a);
  353. Alg_parameter_ptr parm = note->parameters->find(attr);
  354. return parm != NULL;
  355. }
  356. char Alg_event::get_attribute_type(const char *a)
  357. {
  358. assert(is_note());
  359. assert(a);
  360. return a[strlen(a) - 1];
  361. }
  362. const char *Alg_event::get_string_value(const char *a, const char *value)
  363. {
  364. assert(is_note());
  365. assert(a); // must be non-null
  366. Alg_note* note = (Alg_note *) this;
  367. Alg_attribute attr = symbol_table.insert_string(a);
  368. assert(a[0] == 's'); // must be of type string
  369. Alg_parameter_ptr parm = note->parameters->find(attr);
  370. if (parm) return parm->s;
  371. return value;
  372. }
  373. double Alg_event::get_real_value(const char *a, double value)
  374. {
  375. assert(is_note());
  376. assert(a);
  377. Alg_note* note = (Alg_note *) this;
  378. Alg_attribute attr = symbol_table.insert_string(a);
  379. assert(a[0] == 'r'); // must be of type real
  380. Alg_parameter_ptr parm = note->parameters->find(attr);
  381. if (parm) return parm->r;
  382. return value;
  383. }
  384. bool Alg_event::get_logical_value(const char *a, bool value)
  385. {
  386. assert(is_note());
  387. assert(a);
  388. Alg_note* note = (Alg_note *) this;
  389. Alg_attribute attr = symbol_table.insert_string(a);
  390. assert(a[0] == 'l'); // must be of type logical
  391. Alg_parameter_ptr parm = note->parameters->find(attr);
  392. if (parm) return parm->l;
  393. return value;
  394. }
  395. long Alg_event::get_integer_value(const char *a, long value)
  396. {
  397. assert(is_note());
  398. assert(a);
  399. Alg_note* note = (Alg_note *) this;
  400. Alg_attribute attr = symbol_table.insert_string(a);
  401. assert(a[0] == 'i'); // must be of type integer
  402. Alg_parameter_ptr parm = note->parameters->find(attr);
  403. if (parm) return parm->i;
  404. return value;
  405. }
  406. const char *Alg_event::get_atom_value(const char *a, const char *value)
  407. {
  408. assert(is_note());
  409. assert(a);
  410. Alg_note* note = (Alg_note *) this;
  411. Alg_attribute attr = symbol_table.insert_string(a);
  412. assert(a[0] == 'a'); // must be of type atom
  413. Alg_parameter_ptr parm = note->parameters->find(attr);
  414. if (parm) return parm->a;
  415. // if default is a string, convert to an atom (unique
  416. // string in symbol table) and return it
  417. return (value == NULL ? NULL :
  418. symbol_table.insert_string(value));
  419. }
  420. void Alg_event::delete_attribute(const char *a)
  421. {
  422. assert(is_note());
  423. Alg_note* note = (Alg_note *) this;
  424. Alg_parameters::remove_key(&(note->parameters), a);
  425. }
  426. const char *Alg_event::get_attribute()
  427. // Note: this returns a string, not an Alg_attribute
  428. {
  429. assert(is_update());
  430. Alg_update* update = (Alg_update *) this;
  431. return update->parameter.attr_name();
  432. }
  433. char Alg_event::get_update_type()
  434. {
  435. assert(is_update());
  436. Alg_update* update = (Alg_update *) this;
  437. return update->parameter.attr_type();
  438. }
  439. const char *Alg_event::get_string_value()
  440. {
  441. assert(is_update());
  442. Alg_update* update = (Alg_update *) this;
  443. assert(get_update_type() == 's');
  444. return update->parameter.s;
  445. }
  446. double Alg_event::get_real_value()
  447. {
  448. assert(is_update());
  449. Alg_update* update = (Alg_update *) this;
  450. assert(get_update_type() == 'r');
  451. return update->parameter.r;
  452. }
  453. bool Alg_event::get_logical_value()
  454. {
  455. assert(is_update());
  456. Alg_update* update = (Alg_update *) this;
  457. assert(get_update_type() == 'l');
  458. return update->parameter.l;
  459. }
  460. long Alg_event::get_integer_value()
  461. {
  462. assert(is_update());
  463. Alg_update* update = (Alg_update *) this;
  464. assert(get_update_type() == 'i');
  465. return update->parameter.i;
  466. }
  467. const char *Alg_event::get_atom_value()
  468. {
  469. assert(is_update());
  470. Alg_update* update = (Alg_update *) this;
  471. assert(get_update_type() == 'a');
  472. return update->parameter.a;
  473. }
  474. bool Alg_event::overlap(double t, double len, bool all)
  475. {
  476. // event starts within region
  477. if (time >= t && time <= t + len - ALG_EPS)
  478. return true;
  479. if (all && is_note()) {
  480. double dur = ((Alg_note_ptr) this)->dur;
  481. // note overlaps with region
  482. if (time < t && time + dur - ALG_EPS > t)
  483. return true;
  484. }
  485. // does not overlap
  486. return false;
  487. }
  488. Alg_note::Alg_note(Alg_note_ptr note)
  489. {
  490. *this = *note; // copy all fields
  491. // parameters is now a shared pointer. We need to copy the
  492. // parameters
  493. Alg_parameters_ptr next_param_ptr = parameters;
  494. while (next_param_ptr) {
  495. Alg_parameters_ptr new_params = new Alg_parameters(next_param_ptr->next);
  496. new_params->parm.copy(&(next_param_ptr->parm)); // copy the attribute and value
  497. next_param_ptr = new_params->next;
  498. }
  499. }
  500. Alg_note::~Alg_note()
  501. {
  502. while (parameters) {
  503. Alg_parameters_ptr to_delete = parameters;
  504. parameters = parameters->next;
  505. delete to_delete;
  506. }
  507. }
  508. void Alg_note::show()
  509. {
  510. printf("Alg_note: time %g, chan %ld, dur %g, key %ld, "
  511. "pitch %g, loud %g, attributes ",
  512. time, chan, dur, key, pitch, loud);
  513. Alg_parameters_ptr parms = parameters;
  514. while (parms) {
  515. parms->parm.show();
  516. printf(" ");
  517. parms = parms->next;
  518. }
  519. printf("\n");
  520. }
  521. Alg_update::Alg_update(Alg_update_ptr update)
  522. {
  523. *this = *update; // copy all fields
  524. // parameter requires careful copy to possibly duplicate string value:
  525. this->parameter.copy(&(update->parameter));
  526. }
  527. void Alg_update::show()
  528. {
  529. printf("Alg_update: ");
  530. parameter.show();
  531. printf("\n");
  532. }
  533. void Alg_events::expand()
  534. {
  535. maxlen = (maxlen + 5); // extra growth for small sizes
  536. maxlen += (maxlen >> 2); // add 25%
  537. Alg_event_ptr *new_events = new Alg_event_ptr[maxlen];
  538. // now do copy
  539. memcpy(new_events, events, len * sizeof(Alg_event_ptr));
  540. if (events) delete[] events;
  541. events = new_events;
  542. }
  543. void Alg_events::insert(Alg_event_ptr event)
  544. {
  545. if (maxlen <= len) {
  546. expand();
  547. }
  548. // Note: if the new event is the last one, the assignment
  549. // events[i] = event; (below) will never execute, so just
  550. // in case, we do the assignment here. events[len] will
  551. // be replaced during the memmove() operation below if
  552. // this is not the last event.
  553. events[len] = event;
  554. len++;
  555. // find insertion point: (this could be a binary search)
  556. for (int i = 0; i < len; i++) {
  557. if (events[i]->time > event->time) {
  558. // insert event at i
  559. memmove(&events[i + 1], &events[i],
  560. sizeof(Alg_event_ptr) * (len - i - 1));
  561. events[i] = event;
  562. return;
  563. }
  564. }
  565. }
  566. Alg_event_ptr Alg_events::uninsert(long index)
  567. {
  568. assert(0 <= index && index < len);
  569. Alg_event_ptr event = events[index];
  570. //printf("memmove: %x from %x (%d)\n", events + index, events + index + 1,
  571. // sizeof(Alg_event_ptr) * (len - index - 1));
  572. memmove(events + index, events + index + 1,
  573. sizeof(Alg_event_ptr) * (len - index - 1));
  574. len--;
  575. return event;
  576. }
  577. void Alg_events::append(Alg_event_ptr event)
  578. {
  579. if (maxlen <= len) {
  580. expand();
  581. }
  582. events[len++] = event;
  583. // keep track of last note_off time
  584. if (event->is_note()) {
  585. Alg_note_ptr note = (Alg_note_ptr) event;
  586. double note_off = note->time + note->dur;
  587. if (note_off > last_note_off)
  588. last_note_off = note_off;
  589. }
  590. }
  591. Alg_events::~Alg_events()
  592. {
  593. assert(!in_use);
  594. // individual events are not deleted, only the array
  595. if (events) {
  596. delete[] events;
  597. }
  598. }
  599. Alg_event_list::Alg_event_list(Alg_track *owner)
  600. {
  601. events_owner = owner;
  602. sequence_number = owner->sequence_number;
  603. beat_dur = 0.0; real_dur = 0.0; type = 'e';
  604. }
  605. Alg_event_ptr &Alg_event_list::operator [](int i)
  606. {
  607. assert(i >= 0 && i < len);
  608. return events[i];
  609. }
  610. Alg_event_list::~Alg_event_list()
  611. {
  612. // note that the events contained in the list are not destroyed
  613. }
  614. void Alg_event_list::set_start_time(Alg_event *event, double t)
  615. {
  616. // For Alg_event_list, find the owner and do the update there
  617. // For Alg_track, change the time and move the event to the right place
  618. // For Alg_seq, find the track and do the update there
  619. long index, i;
  620. Alg_track_ptr track_ptr;
  621. if (type == 'e') { // this is an Alg_event_list
  622. // make sure the owner has not changed its event set
  623. assert(events_owner &&
  624. sequence_number == events_owner->sequence_number);
  625. // do the update on the owner
  626. events_owner->set_start_time(event, t);
  627. return;
  628. } else if (type == 't') { // this is an Alg_track
  629. // find the event in the track
  630. track_ptr = (Alg_track_ptr) this;
  631. // this should be a binary search since events are in time order
  632. // probably there should be member function to do the search
  633. for (index = 0; index < length(); index++) {
  634. if ((*track_ptr)[index] == event) goto found_event;
  635. }
  636. } else { // type == 's', an Alg_seq
  637. Alg_seq_ptr seq = (Alg_seq_ptr) this;
  638. for (i = 0; i < seq->tracks(); i++) {
  639. track_ptr = seq->track(i);
  640. // if you implemented binary search, you could call it
  641. // instead of this loop too.
  642. for (index = 0; index < track_ptr->length(); index++) {
  643. if ((*track_ptr)[index] == event) goto found_event;
  644. }
  645. }
  646. }
  647. assert(false); // event not found seq or track!
  648. found_event:
  649. // at this point, track[index] == event
  650. // we could be clever and figure out exactly what notes to move
  651. // but it is simpler to just remove the event and reinsert it:
  652. track_ptr->uninsert(index);
  653. event->time = t;
  654. track_ptr->insert(event);
  655. }
  656. void Alg_beats::expand()
  657. {
  658. maxlen = (maxlen + 5); // extra growth for small sizes
  659. maxlen += (maxlen >> 2); // add 25%
  660. Alg_beat_ptr new_beats = new Alg_beat[maxlen];
  661. // now do copy
  662. memcpy(new_beats, beats, len * sizeof(Alg_beat));
  663. if (beats) delete[] beats;
  664. beats = new_beats;
  665. }
  666. void Alg_beats::insert(long i, Alg_beat_ptr beat)
  667. {
  668. assert(i >= 0 && i <= len);
  669. if (maxlen <= len) {
  670. expand();
  671. }
  672. memmove(&beats[i + 1], &beats[i], sizeof(Alg_beat) * (len - i));
  673. memcpy(&beats[i], beat, sizeof(Alg_beat));
  674. len++;
  675. }
  676. Alg_time_map::Alg_time_map(Alg_time_map *map)
  677. {
  678. refcount = 0;
  679. assert(map->beats[0].beat == 0 && map->beats[0].time == 0);
  680. assert(map->beats.len > 0);
  681. // new_beats[0] = map->beats[0];
  682. // this is commented because
  683. // both new_beats[0] and map->beats[0] should be (0, 0)
  684. for (int i = 1; i < map->beats.len; i++) {
  685. beats.insert(i, &map->beats[i]);
  686. }
  687. last_tempo = map->last_tempo;
  688. last_tempo_flag = map->last_tempo_flag;
  689. }
  690. void Alg_time_map::show()
  691. {
  692. printf("Alg_time_map: ");
  693. for (int i = 0; i < beats.len; i++) {
  694. Alg_beat &b = beats[i];
  695. printf("(%g, %g) ", b.time, b.beat);
  696. }
  697. printf("last tempo: %g\n", last_tempo);
  698. }
  699. long Alg_time_map::locate_time(double time)
  700. {
  701. int i = 0;
  702. while ((i < beats.len) && (time > beats[i].time)) {
  703. i++;
  704. }
  705. return i;
  706. }
  707. long Alg_time_map::locate_beat(double beat)
  708. {
  709. int i = 0;
  710. while ((i < beats.len) && (beat > beats[i].beat)) {
  711. i++;
  712. }
  713. return i;
  714. }
  715. double Alg_time_map::beat_to_time(double beat)
  716. {
  717. Alg_beat_ptr mbi;
  718. Alg_beat_ptr mbi1;
  719. if (beat <= 0) {
  720. return beat;
  721. }
  722. int i = locate_beat(beat);
  723. // case 1: beat is between two time/beat pairs
  724. if (0 < i && i < beats.len) {
  725. mbi = &beats[i - 1];
  726. mbi1 = &beats[i];
  727. // case 2: beat is beyond last time/beat pair
  728. } else if (i == beats.len) {
  729. if (last_tempo_flag) {
  730. return beats[i - 1].time +
  731. (beat - beats[i - 1].beat) / last_tempo;
  732. } else if (i == 1) {
  733. return beat * 60.0 / ALG_DEFAULT_BPM;
  734. // so we use that as default allegro tempo too
  735. } else {
  736. mbi = &beats[i - 2];
  737. mbi1 = &beats[i - 1];
  738. }
  739. // case 3: beat is at time 0
  740. } else /* if (i == 0) */ {
  741. return beats[0].time;
  742. }
  743. // whether we extrapolate or interpolate, the math is the same
  744. double time_dif = mbi1->time - mbi->time;
  745. double beat_dif = mbi1->beat - mbi->beat;
  746. return mbi->time + (beat - mbi->beat) * time_dif / beat_dif;
  747. }
  748. double Alg_time_map::time_to_beat(double time)
  749. {
  750. Alg_beat_ptr mbi;
  751. Alg_beat_ptr mbi1;
  752. if (time <= 0.0) return time;
  753. int i = locate_time(time);
  754. if (i == beats.len) {
  755. if (last_tempo_flag) {
  756. return beats[i - 1].beat +
  757. (time - beats[i - 1].time) * last_tempo;
  758. } else if (i == 1) {
  759. return time * (ALG_DEFAULT_BPM / 60.0);
  760. } else {
  761. mbi = &beats[i - 2];
  762. mbi1 = &beats[i - 1];
  763. }
  764. } else {
  765. mbi = &beats[i - 1];
  766. mbi1 = & beats[i];
  767. }
  768. double time_dif = mbi1->time - mbi->time;
  769. double beat_dif = mbi1->beat - mbi->beat;
  770. return mbi->beat + (time - mbi->time) * beat_dif / time_dif;
  771. }
  772. void Alg_time_map::insert_beat(double time, double beat)
  773. {
  774. int i = locate_time(time); // i is insertion point
  775. if (i < beats.len && within(beats[i].time, time, 0.000001)) {
  776. // replace beat if time is already in the map
  777. beats[i].beat = beat;
  778. } else {
  779. Alg_beat point;
  780. point.beat = beat;
  781. point.time = time;
  782. beats.insert(i, &point);
  783. }
  784. // beats[i] contains new beat
  785. // make sure we didn't generate a zero tempo.
  786. // if so, space beats by one microbeat as necessary
  787. long j = i;
  788. if (j == 0) j = 1; // do not adjust beats[0]
  789. while (j < beats.len &&
  790. beats[j - 1].beat + 0.000001 >= beats[j].beat) {
  791. beats[j].beat = beats[j - 1].beat + 0.000001;
  792. j++;
  793. }
  794. }
  795. bool Alg_time_map::insert_tempo(double tempo, double beat)
  796. {
  797. tempo = tempo / 60.0; // convert to beats per second
  798. // change the tempo at the given beat until the next beat event
  799. if (beat < 0) return false;
  800. double time = beat_to_time(beat);
  801. long i = locate_time(time);
  802. if (i >= beats.len || !within(beats[i].time, time, 0.000001)) {
  803. insert_beat(time, beat);
  804. }
  805. // now i is index of beat where tempo will change
  806. if (i == beats.len - 1) {
  807. last_tempo = tempo;
  808. // printf("last_tempo to %g\n", last_tempo);
  809. last_tempo_flag = true;
  810. } else { // adjust all future beats
  811. // compute the difference in beats
  812. double diff = beats[i + 1].beat - beats[i].beat;
  813. // convert beat difference to seconds at new tempo
  814. diff = diff / tempo;
  815. // figure out old time difference:
  816. double old_diff = beats[i + 1].time - time;
  817. // compute difference too
  818. diff = diff - old_diff;
  819. // apply new_diff to score and beats
  820. i++;
  821. while (i < beats.len) {
  822. beats[i].time = beats[i].time + diff;
  823. i++;
  824. }
  825. }
  826. return true;
  827. }
  828. double Alg_time_map::get_tempo(double beat)
  829. {
  830. Alg_beat_ptr mbi;
  831. Alg_beat_ptr mbi1;
  832. // if beat < 0, there is probably an error; return something nice anyway
  833. if (beat < 0) return ALG_DEFAULT_BPM / 60.0;
  834. long i = locate_beat(beat);
  835. // this code is similar to beat_to_time() so far, but we want to get
  836. // beyond beat if possible because we want the tempo FOLLOWING beat
  837. // (Consider the case beat == 0.0)
  838. if (i < beats.len && beat >= beats[i].beat) i++;
  839. // case 1: beat is between two time/beat pairs
  840. if (i < beats.len) {
  841. mbi = &beats[i - 1];
  842. mbi1 = &beats[i];
  843. // case 2: beat is beyond last time/beat pair
  844. } else /* if (i == beats.len) */ {
  845. if (last_tempo_flag) {
  846. return last_tempo;
  847. } else if (i == 1) {
  848. return ALG_DEFAULT_BPM / 60.0;
  849. } else {
  850. mbi = &beats[i - 2];
  851. mbi1 = &beats[i - 1];
  852. }
  853. }
  854. double time_dif = mbi1->time - mbi->time;
  855. double beat_dif = mbi1->beat - mbi->beat;
  856. return beat_dif / time_dif;
  857. }
  858. bool Alg_time_map::set_tempo(double tempo, double start_beat, double end_beat)
  859. {
  860. if (start_beat >= end_beat) return false;
  861. // algorithm: insert a beat event if necessary at start_beat
  862. // and at end_beat
  863. // delete intervening map elements
  864. // change the tempo
  865. insert_beat(beat_to_time(start_beat), start_beat);
  866. insert_beat(beat_to_time(end_beat), end_beat);
  867. long start_x = locate_beat(start_beat) + 1;
  868. long stop_x = locate_beat(end_beat);
  869. while (stop_x < beats.len) {
  870. beats[start_x] = beats[stop_x];
  871. start_x++;
  872. stop_x++;
  873. }
  874. beats.len = start_x; // truncate the map to new length
  875. return insert_tempo(tempo, start_beat);
  876. }
  877. bool Alg_time_map::stretch_region(double b0, double b1, double dur)
  878. {
  879. // find current duration
  880. double t0 = beat_to_time(b0);
  881. double t1 = beat_to_time(b1);
  882. double old_dur = t1 - t0;
  883. if (old_dur <= 0 || dur <= 0) return false;
  884. double scale = dur / old_dur; // larger scale => slower
  885. // insert a beat if necessary at b0 and b1
  886. insert_beat(t0, b0);
  887. insert_beat(t1, b1);
  888. long start_x = locate_beat(b0);
  889. long stop_x = locate_beat(b1);
  890. double orig_time = beats[start_x].time;
  891. double prev_time = orig_time;
  892. for (int i = start_x + 1; i < beats.len; i++) {
  893. double delta = beats[i].time - orig_time;
  894. if (i <= stop_x) { // change tempo to next Alg_beat
  895. delta *= scale;
  896. }
  897. orig_time = beats[i].time;
  898. prev_time += delta;
  899. beats[i].time = prev_time;
  900. }
  901. return true;
  902. }
  903. void Alg_time_map::trim(double start, double end, bool units_are_seconds)
  904. {
  905. // extract the time map from start to end and shift to time zero
  906. // start and end are time in seconds if units_are_seconds is true
  907. int i = 0; // index into beats
  908. int start_index; // index of first breakpoint after start
  909. int count = 1;
  910. double initial_beat = start;
  911. double final_beat = end;
  912. if (units_are_seconds) {
  913. initial_beat = time_to_beat(start);
  914. final_beat = time_to_beat(end);
  915. } else {
  916. start = beat_to_time(initial_beat);
  917. end = beat_to_time(final_beat);
  918. }
  919. while (i < length() && beats[i].time < start) i++;
  920. // now i is index into beats of the first breakpoint after start
  921. // beats[0] is (0,0) and remains that way
  922. // copy beats[start_index] to beats[1], etc.
  923. // skip any beats at or near (start,initial_beat), using count
  924. // to keep track of how many entries there are
  925. start_index = i;
  926. while (i < length() && beats[i].time < end) {
  927. if (beats[i].time - start > ALG_EPS &&
  928. beats[i].beat - initial_beat > ALG_EPS) {
  929. beats[i].time = beats[i].time - start;
  930. beats[i].beat = beats[i].beat - initial_beat;
  931. beats[i - start_index + 1] = beats[i];
  932. count = count + 1;
  933. } else {
  934. start_index = start_index + 1;
  935. }
  936. i = i + 1;
  937. }
  938. // set last tempo data
  939. // we last examined beats[i-1] and copied it to
  940. // beats[i - start_index]. Next tempo should come
  941. // from beats[i] and store in beats[i - start_index + 1]
  942. // case 1: there is at least one breakpoint beyond end
  943. // => interpolate to put a breakpoint at end
  944. // case 2: no more breakpoints => set last tempo data
  945. if (i < length()) {
  946. // we know beats[i].time >= end, so case 1 applies
  947. beats[i - start_index + 1].time = end - start;
  948. beats[i - start_index + 1].beat = final_beat - initial_beat;
  949. count = count + 1;
  950. }
  951. // else we'll just use stored last tempo (if any)
  952. beats.len = count;
  953. }
  954. void Alg_time_map::cut(double start, double len, bool units_are_seconds)
  955. {
  956. // remove portion of time map from start to start + len,
  957. // shifting the tail left by len. start and len are in whatever
  958. // units the score is in. If you cut the time_map as well as cut
  959. // the tracks of the sequence, then sequences will preserve the
  960. // association between tempo changes and events
  961. double end = start + len;
  962. double initial_beat = start;
  963. double final_beat = end;
  964. int i = 0;
  965. if (units_are_seconds) {
  966. initial_beat = time_to_beat(start);
  967. final_beat = time_to_beat(end);
  968. } else {
  969. start = beat_to_time(initial_beat);
  970. end = beat_to_time(final_beat);
  971. len = end - start;
  972. }
  973. double beat_len = final_beat - initial_beat;
  974. while (i < length() && beats[i].time < start - ALG_EPS) {
  975. i = i + 1;
  976. }
  977. // if no beats exist at or after start, just return; nothing to cut
  978. if (i == length()) return;
  979. // now i is index into beats of the first breakpoint on or
  980. // after start, insert (start, initial_beat) in map
  981. if (i < length() && within(beats[i].time, start, ALG_EPS)) {
  982. // perterb time map slightly (within alg_eps) to place
  983. // break point exactly at the start time
  984. beats[i].time = start;
  985. beats[i].beat = initial_beat;
  986. } else {
  987. Alg_beat point(start, initial_beat);
  988. beats.insert(i, &point);
  989. }
  990. // now, we're correct up to beats[i] and beats[i] happens at start.
  991. // find first beat after end so we can start shifting from there
  992. i = i + 1;
  993. int start_index = i;
  994. while (i < length() && beats[i].time < end + ALG_EPS) i++;
  995. // now beats[i] is the next point to be included in beats
  996. // but from i onward, we must shift by (-len, -beat_len)
  997. while (i < length()) {
  998. Alg_beat &b = beats[i];
  999. b.time = b.time - len;
  1000. b.beat = b.beat - beat_len;
  1001. beats[start_index] = b;
  1002. i = i + 1;
  1003. start_index = start_index + 1;
  1004. }
  1005. beats.len = start_index;
  1006. }
  1007. void Alg_time_map::paste(double beat, Alg_track *tr)
  1008. {
  1009. // insert a given time map at a given time and dur (in beats)
  1010. Alg_time_map_ptr from_map = tr->get_time_map();
  1011. // printf("time map paste\nfrom map\n");
  1012. // from_map->show();
  1013. // printf("to map\n");
  1014. // show();
  1015. Alg_beats &from = from_map->beats;
  1016. double time = beat_to_time(beat);
  1017. // Locate the point at which dur occurs
  1018. double dur = tr->get_beat_dur();
  1019. double tr_end_time = from_map->beat_to_time(dur);
  1020. // add offset to make room for insert
  1021. int i = locate_beat(beat);
  1022. while (i < length()) {
  1023. beats[i].beat += dur;
  1024. beats[i].time += tr_end_time;
  1025. i++;
  1026. }
  1027. // printf("after opening up\n");
  1028. // show();
  1029. // insert point at beginning and end of paste
  1030. insert_beat(time, beat);
  1031. // printf("after beginning point insert\n");
  1032. // show();
  1033. // insert_beat(time + tr_end_time, beat + dur);
  1034. // printf("after ending point insert\n");
  1035. // show();
  1036. int j = from_map->locate_beat(dur);
  1037. for (i = 0; i < j; i++) {
  1038. insert_beat(from[i].time + time, // shift by time
  1039. from[i].beat + beat); // and beat
  1040. }
  1041. // printf("after inserts\n");
  1042. show();
  1043. }
  1044. void Alg_time_map::insert_time(double start, double len)
  1045. {
  1046. // find time,beat pair that determines tempo at start
  1047. // compute beat offset = (delta beat / delta time) * len
  1048. // add len,beat offset to each following Alg_beat
  1049. // show();
  1050. int i = locate_time(start); // start <= beats[i].time
  1051. if (beats[i].time == start) i++; // start < beats[i].time
  1052. // case 1: between beats
  1053. if (i > 0 && i < length()) {
  1054. double beat_offset = len * (beats[i].beat - beats[i-1].beat) /
  1055. (beats[i].time - beats[i-1].time);
  1056. while (i < length()) {
  1057. beats[i].beat += beat_offset;
  1058. beats[i].time += len;
  1059. i++;
  1060. }
  1061. } // otherwise, last tempo is in effect; nothing to do
  1062. // printf("time_map AFTER INSERT\n");
  1063. // show();
  1064. }
  1065. void Alg_time_map::insert_beats(double start, double len)
  1066. {
  1067. int i = locate_beat(start); // start <= beats[i].beat
  1068. if (beats[i].beat == start) i++;
  1069. if (i > 0 && i < length()) {
  1070. double time_offset = len * (beats[i].time - beats[i-1].time) /
  1071. (beats[i].beat - beats[i-1].beat);
  1072. while (i < length()) {
  1073. beats[i].time += time_offset;
  1074. beats[i].beat += len;
  1075. i++;
  1076. }
  1077. } // otherwise, last tempo is in effect; nothing to do
  1078. // printf("time_map AFTER INSERT\n");
  1079. // show();
  1080. }
  1081. Alg_track::Alg_track(Alg_time_map *map, bool seconds)
  1082. {
  1083. type = 't';
  1084. time_map = NULL;
  1085. units_are_seconds = seconds;
  1086. set_time_map(map);
  1087. }
  1088. Alg_event_ptr Alg_track::copy_event(Alg_event_ptr event)
  1089. {
  1090. Alg_event *new_event;
  1091. if (event->is_note()) {
  1092. new_event = new Alg_note((Alg_note_ptr) event);
  1093. } else { // update
  1094. new_event = new Alg_update((Alg_update_ptr) event);
  1095. }
  1096. return new_event;
  1097. }
  1098. Alg_track::Alg_track(Alg_track &track)
  1099. {
  1100. type = 't';
  1101. time_map = NULL;
  1102. for (int i = 0; i < track.length(); i++) {
  1103. append(copy_event(track.events[i]));
  1104. }
  1105. set_time_map(track.time_map);
  1106. units_are_seconds = track.units_are_seconds;
  1107. }
  1108. Alg_track::Alg_track(Alg_event_list_ref event_list, Alg_time_map_ptr map,
  1109. bool units_are_seconds)
  1110. {
  1111. type = 't';
  1112. time_map = NULL;
  1113. for (int i = 0; i < event_list.length(); i++) {
  1114. append(copy_event(event_list[i]));
  1115. }
  1116. set_time_map(map);
  1117. this->units_are_seconds = units_are_seconds;
  1118. }
  1119. void Alg_track::serialize(void **buffer, long *bytes)
  1120. {
  1121. // first determine whether this is a seq or a track.
  1122. // if it is a seq, then we will write the time map and a set of tracks
  1123. // if it is a track, we just write the track data and not the time map
  1124. //
  1125. // The code will align doubles on ALIGN boundaries, and longs and
  1126. // floats are aligned to multiples of 4 bytes.
  1127. //
  1128. // The format for a seq is:
  1129. // 'ALGS' -- indicates that this is a sequence
  1130. // long length of all seq data in bytes starting with 'ALGS'
  1131. // long channel_offset_per_track
  1132. // long units_are_seconds
  1133. // time_map:
  1134. // double last_tempo
  1135. // long last_tempo_flag
  1136. // long len -- number of tempo changes
  1137. // for each tempo change (Alg_beat):
  1138. // double time
  1139. // double beat
  1140. // time_sigs:
  1141. // long len -- number of time_sigs
  1142. // long pad
  1143. // for each time signature:
  1144. // double beat
  1145. // double num
  1146. // double den
  1147. // tracks:
  1148. // long len -- number of tracks
  1149. // long pad
  1150. // for each track:
  1151. // 'ALGT' -- indicates this is a track
  1152. // long length of all track data in bytes starting with 'ALGT'
  1153. // long units_are_seconds
  1154. // double beat_dur
  1155. // double real_dur
  1156. // long len -- number of events
  1157. // for each event:
  1158. // long selected
  1159. // long type
  1160. // long key
  1161. // long channel
  1162. // double time
  1163. // if this is a note:
  1164. // double pitch
  1165. // double dur
  1166. // double loud
  1167. // long len -- number of parameters
  1168. // for each parameter:
  1169. // char attribute[] with zero pad to ALIGN
  1170. // one of the following, depending on type:
  1171. // double r
  1172. // char s[] terminated by zero
  1173. // long i
  1174. // long l
  1175. // char a[] terminated by zero
  1176. // zero pad to ALIGN
  1177. // else if this is an update
  1178. // (same representation as parameter above)
  1179. // zero pad to ALIGN
  1180. //
  1181. // The format for a track is given within the Seq format above
  1182. assert(get_type() == 't');
  1183. ser_write_buf.init_for_write();
  1184. serialize_track();
  1185. *buffer = ser_write_buf.to_heap(bytes);
  1186. }
  1187. void Alg_seq::serialize(void **buffer, long *bytes)
  1188. {
  1189. assert(get_type() == 's');
  1190. ser_write_buf.init_for_write();
  1191. serialize_seq();
  1192. *buffer = ser_write_buf.to_heap(bytes);
  1193. }
  1194. void Serial_write_buffer::check_buffer(long needed)
  1195. {
  1196. if (len < (ptr - buffer) + needed) { // do we need more space?
  1197. long new_len = len * 2; // exponential growth is important
  1198. // initially, length is zero, so bump new_len to a starting value
  1199. if (new_len == 0) new_len = 1024;
  1200. // make sure new_len is as big as needed
  1201. if (needed > new_len) new_len = needed;
  1202. char *new_buffer = new char[new_len]; // allocate space
  1203. ptr = new_buffer + (ptr - buffer); // relocate ptr to new buffer
  1204. if (len > 0) { // we had a buffer already
  1205. memcpy(new_buffer, buffer, len); // copy from old buffer
  1206. delete buffer; // free old buffer
  1207. }
  1208. buffer = new_buffer; // update buffer information
  1209. len = new_len;
  1210. }
  1211. }
  1212. void Alg_seq::serialize_seq()
  1213. {
  1214. int i; // loop counters
  1215. // we can easily compute how much buffer space we need until we
  1216. // get to tracks, so expand at least that much
  1217. long needed = 64 + 16 * time_map->beats.len + 24 * time_sig.length();
  1218. ser_write_buf.check_buffer(needed);
  1219. ser_write_buf.set_char('A');
  1220. ser_write_buf.set_char('L');
  1221. ser_write_buf.set_char('G');
  1222. ser_write_buf.set_char('S');
  1223. long length_offset = ser_write_buf.get_posn();
  1224. ser_write_buf.set_int32(0); // leave room to come back and write length
  1225. ser_write_buf.set_int32(channel_offset_per_track);
  1226. ser_write_buf.set_int32(units_are_seconds);
  1227. ser_write_buf.set_double(beat_dur);
  1228. ser_write_buf.set_double(real_dur);
  1229. ser_write_buf.set_double(time_map->last_tempo);
  1230. ser_write_buf.set_int32(time_map->last_tempo_flag);
  1231. ser_write_buf.set_int32(time_map->beats.len);
  1232. for (i = 0; i < time_map->beats.len; i++) {
  1233. ser_write_buf.set_double(time_map->beats[i].time);
  1234. ser_write_buf.set_double(time_map->beats[i].beat);
  1235. }
  1236. ser_write_buf.set_int32(time_sig.length());
  1237. ser_write_buf.pad();
  1238. for (i = 0; i < time_sig.length(); i++) {
  1239. ser_write_buf.set_double(time_sig[i].beat);
  1240. ser_write_buf.set_double(time_sig[i].num);
  1241. ser_write_buf.set_double(time_sig[i].den);
  1242. }
  1243. ser_write_buf.set_int32(tracks());
  1244. ser_write_buf.pad();
  1245. for (i = 0; i < tracks(); i++) {
  1246. track(i)->serialize_track();
  1247. }
  1248. // do not include ALGS, include padding at end
  1249. ser_write_buf.store_long(length_offset, ser_write_buf.get_posn() - length_offset);
  1250. }
  1251. void Alg_track::serialize_track()
  1252. {
  1253. // to simplify the code, copy from parameter addresses to locals
  1254. int j;
  1255. ser_write_buf.check_buffer(32);
  1256. ser_write_buf.set_char('A');
  1257. ser_write_buf.set_char('L');
  1258. ser_write_buf.set_char('G');
  1259. ser_write_buf.set_char('T');
  1260. long length_offset = ser_write_buf.get_posn(); // save location for track length
  1261. ser_write_buf.set_int32(0); // room to write track length
  1262. ser_write_buf.set_int32(units_are_seconds);
  1263. ser_write_buf.set_double(beat_dur);
  1264. ser_write_buf.set_double(real_dur);
  1265. ser_write_buf.set_int32(len);
  1266. for (j = 0; j < len; j++) {
  1267. ser_write_buf.check_buffer(24);
  1268. Alg_event *event = (*this)[j];
  1269. ser_write_buf.set_int32(event->get_selected());
  1270. ser_write_buf.set_int32(event->get_type());
  1271. ser_write_buf.set_int32(event->get_identifier());
  1272. ser_write_buf.set_int32(event->chan);
  1273. ser_write_buf.set_double(event->time);
  1274. if (event->is_note()) {
  1275. ser_write_buf.check_buffer(20);
  1276. Alg_note *note = (Alg_note *) event;
  1277. ser_write_buf.set_float(note->pitch);
  1278. ser_write_buf.set_float(note->loud);
  1279. ser_write_buf.set_double(note->dur);
  1280. long parm_num_offset = ser_write_buf.get_posn();
  1281. long parm_num = 0;
  1282. ser_write_buf.set_int32(0); // placeholder for no. parameters
  1283. Alg_parameters_ptr parms = note->parameters;
  1284. while (parms) {
  1285. serialize_parameter(&(parms->parm));
  1286. parms = parms->next;
  1287. parm_num++;
  1288. }
  1289. ser_write_buf.store_long(parm_num_offset, parm_num);
  1290. } else {
  1291. assert(event->is_update());
  1292. Alg_update *update = (Alg_update *) event;
  1293. serialize_parameter(&(update->parameter));
  1294. }
  1295. ser_write_buf.check_buffer(7); // maximum padding possible
  1296. ser_write_buf.pad();
  1297. }
  1298. // write length, not including ALGT, including padding at end
  1299. ser_write_buf.store_long(length_offset, ser_write_buf.get_posn() - length_offset);
  1300. }
  1301. void Alg_track::serialize_parameter(Alg_parameter *parm)
  1302. {
  1303. // add eight to account for name + zero end-of-string and the
  1304. // possibility of adding 7 padding bytes
  1305. long len = strlen(parm->attr_name()) + 8;
  1306. ser_write_buf.check_buffer(len);
  1307. ser_write_buf.set_string(parm->attr_name());
  1308. ser_write_buf.pad();
  1309. switch (parm->attr_type()) {
  1310. case 'r':
  1311. ser_write_buf.check_buffer(8);
  1312. ser_write_buf.set_double(parm->r);
  1313. break;
  1314. case 's':
  1315. ser_write_buf.check_buffer(strlen(parm->s) + 1);
  1316. ser_write_buf.set_string(parm->s);
  1317. break;
  1318. case 'i':
  1319. ser_write_buf.check_buffer(4);
  1320. ser_write_buf.set_int32(parm->i);
  1321. break;
  1322. case 'l':
  1323. ser_write_buf.check_buffer(4);
  1324. ser_write_buf.set_int32(parm->l);
  1325. break;
  1326. case 'a':
  1327. ser_write_buf.check_buffer(strlen(parm->a) + 1);
  1328. ser_write_buf.set_string(parm->a);
  1329. break;
  1330. }
  1331. }
  1332. Alg_track *Alg_track::unserialize(void *buffer, long len)
  1333. {
  1334. assert(len > 8);
  1335. ser_read_buf.init_for_read(buffer, len);
  1336. bool alg = ser_read_buf.get_char() == 'A' &&
  1337. ser_read_buf.get_char() == 'L' &&
  1338. ser_read_buf.get_char() == 'G';
  1339. assert(alg);
  1340. char c = ser_read_buf.get_char();
  1341. if (c == 'S') {
  1342. Alg_seq *seq = new Alg_seq;
  1343. ser_read_buf.unget_chars(4); // undo get_char() of A,L,G,S
  1344. seq->unserialize_seq();
  1345. return seq;
  1346. } else {
  1347. assert(c == 'T');
  1348. Alg_track *track = new Alg_track;
  1349. ser_read_buf.unget_chars(4); // undo get_char() of A,L,G,T
  1350. track->unserialize_track();
  1351. return track;
  1352. }
  1353. }
  1354. #pragma warning(disable: 4800) // long to bool performance warning
  1355. /* Note: this Alg_seq must have a default initialized Alg_time_map.
  1356. * It will be filled in with data from the ser_read_buf buffer.
  1357. */
  1358. void Alg_seq::unserialize_seq()
  1359. {
  1360. ser_read_buf.check_input_buffer(48);
  1361. bool algs = (ser_read_buf.get_char() == 'A') &&
  1362. (ser_read_buf.get_char() == 'L') &&
  1363. (ser_read_buf.get_char() == 'G') &&
  1364. (ser_read_buf.get_char() == 'S');
  1365. assert(algs);
  1366. long len = ser_read_buf.get_int32();
  1367. assert(ser_read_buf.get_len() >= len);
  1368. channel_offset_per_track = ser_read_buf.get_int32();
  1369. units_are_seconds = ser_read_buf.get_int32() != 0;
  1370. beat_dur = ser_read_buf.get_double();
  1371. real_dur = ser_read_buf.get_double();
  1372. // no need to allocate an Alg_time_map since it's done during initialization
  1373. time_map->last_tempo = ser_read_buf.get_double();
  1374. time_map->last_tempo_flag = ser_read_buf.get_int32() != 0;
  1375. long beats = ser_read_buf.get_int32();
  1376. ser_read_buf.check_input_buffer(beats * 16 + 4);
  1377. int i;
  1378. for (i = 0; i < beats; i++) {
  1379. double time = ser_read_buf.get_double();
  1380. double beat = ser_read_buf.get_double();
  1381. time_map->insert_beat(time, beat);
  1382. // printf("time_map: %g, %g\n", time, beat);
  1383. }
  1384. long time_sig_len = ser_read_buf.get_int32();
  1385. ser_read_buf.get_pad();
  1386. ser_read_buf.check_input_buffer(time_sig_len * 24 + 8);
  1387. for (i = 0; i < time_sig_len; i++) {
  1388. double beat = ser_read_buf.get_double();
  1389. double num = ser_read_buf.get_double();
  1390. double den = ser_read_buf.get_double();
  1391. time_sig.insert(beat, num, den);
  1392. }
  1393. long tracks_num = ser_read_buf.get_int32();
  1394. ser_read_buf.get_pad();
  1395. add_track(tracks_num - 1); // create tracks_num tracks
  1396. for (i = 0; i < tracks_num; i++) {
  1397. track(i)->unserialize_track();
  1398. }
  1399. // assume seq started at beginning of buffer. len measures
  1400. // bytes after 'ALGS' header, so add 4 bytes and compare to
  1401. // current buffer position -- they should agree
  1402. assert(ser_read_buf.get_posn() == len + 4);
  1403. }
  1404. void Alg_track::unserialize_track()
  1405. {
  1406. ser_read_buf.check_input_buffer(32);
  1407. bool algt = (ser_read_buf.get_char() == 'A') &&
  1408. (ser_read_buf.get_char() == 'L') &&
  1409. (ser_read_buf.get_char() == 'G') &&
  1410. (ser_read_buf.get_char() == 'T');
  1411. assert(algt);
  1412. long offset = ser_read_buf.get_posn(); // stored length does not include 'ALGT'
  1413. long bytes = ser_read_buf.get_int32();
  1414. assert(bytes <= ser_read_buf.get_len() - offset);
  1415. units_are_seconds = (bool) ser_read_buf.get_int32();
  1416. beat_dur = ser_read_buf.get_double();
  1417. real_dur = ser_read_buf.get_double();
  1418. int event_count = ser_read_buf.get_int32();
  1419. for (int i = 0; i < event_count; i++) {
  1420. ser_read_buf.check_input_buffer(24);
  1421. long selected = ser_read_buf.get_int32();
  1422. char type = (char) ser_read_buf.get_int32();
  1423. long key = ser_read_buf.get_int32();
  1424. long channel = ser_read_buf.get_int32();
  1425. double time = ser_read_buf.get_double();
  1426. if (type == 'n') {
  1427. ser_read_buf.check_input_buffer(20);
  1428. float pitch = ser_read_buf.get_float();
  1429. float loud = ser_read_buf.get_float();
  1430. double dur = ser_read_buf.get_double();
  1431. Alg_note *note =
  1432. create_note(time, channel, key, pitch, loud, dur);
  1433. note->set_selected(selected != 0);
  1434. long param_num = ser_read_buf.get_int32();
  1435. int j;
  1436. // this builds a list of parameters in the correct order
  1437. // (although order shouldn't matter)
  1438. Alg_parameters_ptr *list = &note->parameters;
  1439. for (j = 0; j < param_num; j++) {
  1440. *list = new Alg_parameters(NULL);
  1441. unserialize_parameter(&((*list)->parm));
  1442. list = &((*list)->next);
  1443. }
  1444. append(note);
  1445. } else {
  1446. assert(type == 'u');
  1447. Alg_update *update = create_update(time, channel, key);
  1448. update->set_selected(selected != 0);
  1449. unserialize_parameter(&(update->parameter));
  1450. append(update);
  1451. }
  1452. ser_read_buf.get_pad();
  1453. }
  1454. assert(offset + bytes == ser_read_buf.get_posn());
  1455. }
  1456. void Alg_track::unserialize_parameter(Alg_parameter_ptr parm_ptr)
  1457. {
  1458. Alg_attribute attr = ser_read_buf.get_string();
  1459. parm_ptr->attr = symbol_table.insert_string(attr);
  1460. switch (parm_ptr->attr_type()) {
  1461. case 'r':
  1462. ser_read_buf.check_input_buffer(8);
  1463. parm_ptr->r = ser_read_buf.get_double();
  1464. break;
  1465. case 's':
  1466. parm_ptr->s = heapify(ser_read_buf.get_string());
  1467. break;
  1468. case 'i':
  1469. ser_read_buf.check_input_buffer(4);
  1470. parm_ptr->i = ser_read_buf.get_int32();
  1471. break;
  1472. case 'l':
  1473. ser_read_buf.check_input_buffer(4);
  1474. parm_ptr->l = ser_read_buf.get_int32() != 0;
  1475. break;
  1476. case 'a':
  1477. parm_ptr->a = symbol_table.insert_attribute(ser_read_buf.get_string());
  1478. break;
  1479. }
  1480. }
  1481. #pragma warning(default: 4800)
  1482. void Alg_track::set_time_map(Alg_time_map *map)
  1483. {
  1484. if (time_map) time_map->dereference();
  1485. if (map == NULL) {
  1486. time_map = new Alg_time_map(); // new default map
  1487. time_map->reference();
  1488. } else {
  1489. time_map = map;
  1490. time_map->reference();
  1491. }
  1492. }
  1493. void Alg_track::convert_to_beats()
  1494. // modify all times and durations in notes to beats
  1495. {
  1496. if (units_are_seconds) {
  1497. units_are_seconds = false;
  1498. long i;
  1499. for (i = 0; i < length(); i++) {
  1500. Alg_event_ptr e = events[i];
  1501. double beat = time_map->time_to_beat(e->time);
  1502. if (e->is_note()) {
  1503. Alg_note_ptr n = (Alg_note_ptr) e;
  1504. n->dur = time_map->time_to_beat(n->time + n->dur) - beat;
  1505. }
  1506. e->time = beat;
  1507. }
  1508. }
  1509. }
  1510. void Alg_track::convert_to_seconds()
  1511. // modify all times and durations in notes to seconds
  1512. {
  1513. if (!units_are_seconds) {
  1514. last_note_off = time_map->beat_to_time(last_note_off);
  1515. units_are_seconds = true;
  1516. long i;
  1517. for (i = 0; i < length(); i++) {
  1518. Alg_event_ptr e = events[i];
  1519. double time = time_map->beat_to_time(e->time);
  1520. if (e->is_note()) {
  1521. Alg_note_ptr n = (Alg_note_ptr) e;
  1522. n->dur = time_map->beat_to_time(n->time + n->dur) - time;
  1523. }
  1524. e->time = time;
  1525. }
  1526. }
  1527. }
  1528. void Alg_track::set_dur(double duration)
  1529. {
  1530. // set beat_dur and real_dur
  1531. if (units_are_seconds) {
  1532. set_real_dur(duration);
  1533. set_beat_dur(time_map->time_to_beat(duration));
  1534. } else {
  1535. set_beat_dur(duration);
  1536. set_real_dur(time_map->beat_to_time(duration));
  1537. }
  1538. }
  1539. Alg_note *Alg_track::create_note(double time, int channel, int identifier,
  1540. float pitch, float loudness, double duration)
  1541. {
  1542. Alg_note *note = new Alg_note();
  1543. note->time = time;
  1544. note->chan = channel;
  1545. note->set_identifier(identifier);
  1546. note->pitch = pitch;
  1547. note->loud = loudness;
  1548. note->dur = duration;
  1549. return note;
  1550. }
  1551. Alg_update *Alg_track::create_update(double time, int channel, int identifier)
  1552. {
  1553. Alg_update *update = new Alg_update();
  1554. update->time = time;
  1555. update->chan = channel;
  1556. update->set_identifier(identifier);
  1557. return update;
  1558. }
  1559. Alg_track_ptr Alg_track::cut(double t, double len, bool all)
  1560. {
  1561. // since we are translating notes in time, do not copy or use old timemap
  1562. Alg_track_ptr track = new Alg_track();
  1563. track->units_are_seconds = units_are_seconds;
  1564. if (units_are_seconds) {
  1565. track->set_real_dur(len);
  1566. track->set_beat_dur(time_map->time_to_beat(t + len) -
  1567. time_map->time_to_beat(t));
  1568. } else {
  1569. track->set_beat_dur(len);
  1570. track->set_real_dur(time_map->beat_to_time(t + len) -
  1571. time_map->beat_to_time(t));
  1572. }
  1573. int i;
  1574. int new_len = 0;
  1575. int change = 0;
  1576. for (i = 0; i < length(); i++) {
  1577. Alg_event_ptr event = events[i];
  1578. if (event->overlap(t, len, all)) {
  1579. event->time -= t;
  1580. track->append(event);
  1581. change = 1;
  1582. } else { // if we're not cutting this event, move it to
  1583. // eliminate the gaps in events left by cut events
  1584. events[new_len] = event;
  1585. // adjust times of events after t + len
  1586. if (event->time > t + len - ALG_EPS) {
  1587. event->time -= len;
  1588. change = 1;
  1589. }
  1590. new_len++;
  1591. }
  1592. }
  1593. // Alg_event_lists based on this track become invalid
  1594. sequence_number += change;
  1595. this->len = new_len; // adjust length since we removed events
  1596. return track;
  1597. }
  1598. Alg_track_ptr Alg_track::copy(double t, double len, bool all)
  1599. {
  1600. // since we are translating notes in time, do not copy or use old timemap
  1601. Alg_track_ptr track = new Alg_track();
  1602. track->units_are_seconds = units_are_seconds;
  1603. if (units_are_seconds) {
  1604. track->set_real_dur(len);
  1605. track->set_beat_dur(time_map->time_to_beat(t + len) -
  1606. time_map->time_to_beat(t));
  1607. } else {
  1608. track->set_beat_dur(len);
  1609. track->set_real_dur(time_map->beat_to_time(t + len) -
  1610. time_map->beat_to_time(t));
  1611. }
  1612. int i;
  1613. for (i = 0; i < length(); i++) {
  1614. Alg_event_ptr event = events[i];
  1615. if (event->overlap(t, len, all)) {
  1616. Alg_event_ptr new_event = copy_event(event);
  1617. new_event->time -= t;
  1618. track->append(new_event);
  1619. }
  1620. }
  1621. return track;
  1622. }
  1623. void Alg_track::paste(double t, Alg_event_list *seq)
  1624. {
  1625. assert(get_type() == 't');
  1626. // seq can be an Alg_event_list, an Alg_track, or an Alg_seq
  1627. // if it is an Alg_event_list, units_are_seconds must match
  1628. bool prev_units_are_seconds;
  1629. if (seq->get_type() == 'e') {
  1630. assert(seq->get_owner()->get_units_are_seconds() == units_are_seconds);
  1631. } else { // make it match
  1632. Alg_track_ptr tr = (Alg_track_ptr) seq;
  1633. prev_units_are_seconds = tr->get_units_are_seconds();
  1634. if (units_are_seconds) tr->convert_to_seconds();
  1635. else tr->convert_to_beats();
  1636. }
  1637. double dur = (units_are_seconds ? seq->get_real_dur() :
  1638. seq->get_beat_dur());
  1639. // Note: in the worst case, seq may contain notes
  1640. // that start almost anytime up to it's duration,
  1641. // so the simplest algorithm is simply a sequence
  1642. // of inserts. If this turns out to be too slow,
  1643. // we can do a merge sort in the case that seq
  1644. // is an Alg_track (if it's an Alg_event_list, we
  1645. // are not guaranteed that the events are in time
  1646. // order, but currently, only a true seq is allowed)
  1647. int i;
  1648. for (i = 0; i < length(); i++) {
  1649. if (events[i]->time > t - ALG_EPS) {
  1650. events[i]->time += dur;
  1651. }
  1652. }
  1653. for (i = 0; i < seq->length(); i++) {
  1654. Alg_event *new_event = copy_event((*seq)[i]);
  1655. new_event->time += t;
  1656. insert(new_event);
  1657. }
  1658. // restore track units to what they were before
  1659. if (seq->get_type() != 'e') {
  1660. Alg_track_ptr tr = (Alg_track_ptr) seq;
  1661. if (prev_units_are_seconds) tr->convert_to_seconds();
  1662. else tr->convert_to_beats();
  1663. }
  1664. }
  1665. void Alg_track::merge(double t, Alg_event_list_ptr seq)
  1666. {
  1667. Alg_event_list_ref s = *seq;
  1668. for (int i = 0; i < s.length(); i++) {
  1669. Alg_event *new_event;
  1670. if (s[i]->is_note()) {
  1671. new_event = new Alg_note((Alg_note_ptr) s[i]);
  1672. } else {
  1673. new_event = new Alg_update((Alg_update_ptr) s[i]);
  1674. }
  1675. new_event->time += t;
  1676. insert(new_event);
  1677. }
  1678. }
  1679. void Alg_track::clear(double t, double len, bool all)
  1680. {
  1681. int i;
  1682. int move_to = 0;
  1683. for (i = 0; i < length(); i++) {
  1684. Alg_event_ptr event = events[i];
  1685. if (event->overlap(t, len, all)) {
  1686. delete events[i];
  1687. } else { // if we're not clearing this event, move it to
  1688. // eliminate the gaps in events left by cleared events
  1689. events[move_to] = event;
  1690. // adjust times of events after t + len. This test is based
  1691. // on the one in Alg_event::overlap() for consistency.
  1692. if (event->time > t + len - ALG_EPS && event->time > t)
  1693. event->time -= len;
  1694. move_to++;
  1695. }
  1696. }
  1697. if (move_to != this->len) { // we cleared at least one note
  1698. sequence_number++; // Alg_event_lists based on this track become invalid
  1699. }
  1700. this->len = move_to; // adjust length since we removed events
  1701. }
  1702. void Alg_track::silence(double t, double len, bool all)
  1703. {
  1704. int i;
  1705. int move_to = 0;
  1706. for (i = 0; i < length(); i++) {
  1707. Alg_event_ptr event = events[i];
  1708. if (event->overlap(t, len, all)) {
  1709. delete events[i];
  1710. } else { // if we're not clearing this event, move it to
  1711. // eliminate the gaps in events left by cleared events
  1712. events[move_to] = event;
  1713. move_to++;
  1714. }
  1715. }
  1716. if (move_to != this->len) { // we cleared at least one note
  1717. sequence_number++; // Alg_event_lists based on this track become invalid
  1718. }
  1719. this->len = move_to; // adjust length since we removed events
  1720. }
  1721. void Alg_track::insert_silence(double t, double len)
  1722. {
  1723. int i;
  1724. for (i = 0; i < length(); i++) {
  1725. Alg_event_ptr event = events[i];
  1726. if (event->time > t - ALG_EPS) event->time += len;
  1727. }
  1728. }
  1729. Alg_event_list *Alg_track::find(double t, double len, bool all,
  1730. long channel_mask, long event_type_mask)
  1731. {
  1732. int i;
  1733. Alg_event_list *list = new Alg_event_list(this);
  1734. if (units_are_seconds) { // t and len are seconds
  1735. list->set_real_dur(len);
  1736. list->set_beat_dur(get_time_map()->time_to_beat(t + len) -
  1737. get_time_map()->time_to_beat(t));
  1738. } else { // t and len are beats
  1739. list->set_real_dur(get_time_map()->beat_to_time(t + len) -
  1740. get_time_map()->beat_to_time(t));
  1741. list->set_beat_dur(len);
  1742. }
  1743. for (i = 0; i < length(); i++) {
  1744. Alg_event_ptr event = events[i];
  1745. if (event->overlap(t, len, all)) {
  1746. if ((channel_mask == 0 ||
  1747. (event->chan < 32 &&
  1748. (channel_mask & (1 << event->chan)))) &&
  1749. ((event_type_mask == 0 ||
  1750. (event_type_mask & (1 << event->get_type_code()))))) {
  1751. list->append(event);
  1752. }
  1753. }
  1754. }
  1755. return list;
  1756. }
  1757. void Alg_time_sigs::expand()
  1758. {
  1759. assert(maxlen >= len);
  1760. maxlen = (maxlen + 5); // extra growth for small sizes
  1761. maxlen += (maxlen >> 2); // add 25%
  1762. Alg_time_sig_ptr new_time_sigs = new Alg_time_sig[maxlen];
  1763. // now do copy
  1764. memcpy(new_time_sigs, time_sigs, len * sizeof(Alg_time_sig));
  1765. if (time_sigs)
  1766. delete[] time_sigs;
  1767. time_sigs = new_time_sigs;
  1768. }
  1769. void Alg_time_sigs::insert(double beat, double num, double den, bool force)
  1770. {
  1771. // find insertion point:
  1772. for (int i = 0; i < len; i++) {
  1773. if (within(time_sigs[i].beat, beat, ALG_EPS)) {
  1774. // overwrite location i with new info
  1775. time_sigs[i].beat = beat;
  1776. time_sigs[i].num = num;
  1777. time_sigs[i].den = den;
  1778. return;
  1779. } else if (time_sigs[i].beat > beat) {
  1780. if ((i > 0 && // check if redundant with prev. time sig
  1781. time_sigs[i - 1].num == num &&
  1782. time_sigs[i - 1].den == den &&
  1783. within(fmod(beat - time_sigs[i - 1].beat,
  1784. 4 * time_sigs[i-1].num / time_sigs[i-1].den),
  1785. 0, ALG_EPS)) ||
  1786. // check if redundant with implied initial 4/4 time sig:
  1787. (i == 0 && num == 4 && den == 4 &&
  1788. within(fmod(beat, 4), 0, ALG_EPS))) {
  1789. if (!force) return; // redundant inserts can be ignored here
  1790. }
  1791. // make room for new event
  1792. if (maxlen <= len) expand();
  1793. // insert new event at i
  1794. memmove(&time_sigs[i + 1], &time_sigs[i],
  1795. sizeof(Alg_time_sig) * (len - i));
  1796. time_sigs[i].beat = beat;
  1797. time_sigs[i].num = num;
  1798. time_sigs[i].den = den;
  1799. len++;
  1800. return;
  1801. }
  1802. }
  1803. // if we fall out of loop, then this goes at end
  1804. if (maxlen <= len) expand();
  1805. time_sigs[len].beat = beat;
  1806. time_sigs[len].num = num;
  1807. time_sigs[len].den = den;
  1808. len++;
  1809. }
  1810. void Alg_time_sigs::show()
  1811. {
  1812. printf("Alg_time_sig: ");
  1813. for (int i = 0; i < len; i++) {
  1814. printf("(%g: %g/%g) ", time_sigs[i].beat, time_sigs[i].num, time_sigs[i].den);
  1815. }
  1816. printf("\n");
  1817. }
  1818. int Alg_time_sigs::find_beat(double beat)
  1819. {
  1820. // index where you would insert a new time signature at beat
  1821. int i = 0;
  1822. while (i < len && time_sigs[i].beat < beat - ALG_EPS) i++;
  1823. return i;
  1824. }
  1825. double Alg_time_sigs::get_bar_len(double beat)
  1826. {
  1827. int i = find_beat(beat);
  1828. double num = 4.0;
  1829. double den = 4.0;
  1830. if (i != 0) {
  1831. num = time_sigs[i - 1].num;
  1832. den = time_sigs[i - 1].den;
  1833. }
  1834. return 4 * num / den;
  1835. }
  1836. void Alg_time_sigs::cut(double start, double end, double dur)
  1837. {
  1838. // remove time_sig's from start to end -- these must be
  1839. // in beats (not seconds).
  1840. // The duration of the whole sequence is dur (beats).
  1841. // If the first bar line after end comes before a time signature
  1842. // and does not fall on a bar line, insert a time signature at
  1843. // the time of the bar line to retain relative bar line positions
  1844. int i = find_beat(end);
  1845. // i is where you would insert a new time sig at beat,
  1846. // Case 1: beat coincides with a time sig at i. Time signature
  1847. // at beat means that there is a barline at beat, so when beat
  1848. // is shifted to start, the relative barline positions are preserved
  1849. if (len > 0 &&
  1850. within(end, time_sigs[i].beat, ALG_EPS)) {
  1851. // beat coincides with time signature change, so end is on a barline
  1852. /* do nothing */ ;
  1853. // Case 2: there is no time signature before end
  1854. } else if (i == 0 && (len == 0 ||
  1855. time_sigs[0].beat > end)) {
  1856. // If the next time signature does not fall on a barline,
  1857. // then end must not be on a barline, so there is a partial
  1858. // measure from end to the next barline. We need
  1859. // a time signature there to preserve relative barline
  1860. // locations. It may be that the next bar after start is
  1861. // due to another time signature, in which case we do not
  1862. // need to insert anything.
  1863. double measures = end / 4.0;
  1864. double imeasures = ROUND(measures);
  1865. if (!within(measures, imeasures, ALG_EPS)) {
  1866. // start is not on a barline, maybe add one here:
  1867. double bar_loc = (int(measures) + 1) * 4.0;
  1868. if (bar_loc < dur - ALG_EPS &&
  1869. (len == 0 || time_sigs[0].beat > bar_loc + ALG_EPS)) {
  1870. insert(bar_loc, 4, 4, true); // forced insert
  1871. }
  1872. }
  1873. // This case should never be true because if i == 0, either there
  1874. // are no time signatures before beat (Case 2),
  1875. // or there is one time signature at beat (Case 1)
  1876. } else if (i == 0) {
  1877. /* do nothing (might be good to assert(false)) */ ;
  1878. // Case 3: i-1 must be the effective time sig position
  1879. } else {
  1880. // get the time signature in effect at end
  1881. Alg_time_sig &tsp = time_sigs[i - 1];
  1882. double beats_per_measure = (tsp.num * 4) / tsp.den;
  1883. double measures = (end - tsp.beat) / beats_per_measure;
  1884. int imeasures = ROUND(measures);
  1885. if (!within(measures, imeasures, ALG_EPS)) {
  1886. // end is not on a measure, so we need to insert a time sig
  1887. // to force a bar line at the first measure location after
  1888. // beat, if any
  1889. double bar_loc = tsp.beat + beats_per_measure * (int(measures) + 1);
  1890. // insert new time signature at bar_loc
  1891. // It will have the same time signature, but the position will
  1892. // force a barline to match the barline before the shift
  1893. // However, we should not insert a barline if there is a
  1894. // time signature earlier than the barline time
  1895. if (i < len /* time_sigs[i] is the last one */ &&
  1896. time_sigs[i].beat < bar_loc - ALG_EPS) {
  1897. /* do not insert because there's already a time signature */;
  1898. } else if (bar_loc < dur - ALG_EPS) {
  1899. insert(bar_loc, tsp.num, tsp.den, true); // forced insert
  1900. }
  1901. }
  1902. // else beat coincides with a barline, so no need for an extra
  1903. // time signature to force barline alignment
  1904. }
  1905. // Figure out if time signature at start matches
  1906. // the time signature at end. If not, we need to insert a
  1907. // time signature at end to force the correct time signature
  1908. // there.
  1909. // Find time signature at start:
  1910. double start_num = 4.0; // default if no time signature specified
  1911. double start_den = 4.0;
  1912. i = find_beat(start);
  1913. // A time signature at start would go at index i, so the effective
  1914. // time signature prior to start is at i - 1. If i == 0, the default
  1915. // time signature is in effect prior to start.
  1916. if (i != 0) {
  1917. start_num = time_sigs[i - 1].num;
  1918. start_den = time_sigs[i - 1].den;
  1919. }
  1920. // Find the time signature at end:
  1921. double end_num = 4.0; // default if no time signature specified
  1922. double end_den = 4.0;
  1923. int j = find_beat(end);
  1924. if (j != 0) {
  1925. end_num = time_sigs[j - 1].num;
  1926. end_den = time_sigs[j - 1].den;
  1927. }
  1928. // compare: If meter changes and there is no time signature at end,
  1929. // insert a time signature at end
  1930. if (end < dur - ALG_EPS &&
  1931. (start_num != end_num || start_den != end_den) &&
  1932. (j >= len || !within(time_sigs[j].beat, end, ALG_EPS))) {
  1933. insert(end, end_num, end_den, true);
  1934. }
  1935. // Remove time signatures from start to end (not including one AT
  1936. // end, if there is one there. Be careful with ALG_EPS on that one.)
  1937. // since we may have inserted a time signature, find position again:
  1938. int i0 = find_beat(start);
  1939. int i1 = i0;
  1940. // scan to end of cut region
  1941. while (i1 < len && time_sigs[i1].beat < end - ALG_EPS) {
  1942. i1++;
  1943. }
  1944. // scan from end to len(time_sig)
  1945. while (i1 < len) {
  1946. Alg_time_sig &ts = time_sigs[i1];
  1947. ts.beat -= (end - start);
  1948. time_sigs[i0] = ts;
  1949. i0++;
  1950. i1++;
  1951. }
  1952. len = i1;
  1953. }
  1954. void Alg_time_sigs::trim(double start, double end)
  1955. {
  1956. // remove time_sig's not in [start, end), but retain
  1957. // barline positions relative to the notes. This means that
  1958. // if the meter (time signature) changes between start and
  1959. // end that we need to insert a time signature at start.
  1960. // Also, if trim() would cause barlines to move, we need to
  1961. // insert a time signature on a barline (timesignatures
  1962. // imply the beginning of a bar even if the previous bar
  1963. // does not have enough beats. Note that bars do not need
  1964. // to have an integer number of beats).
  1965. //
  1966. // units must be in beats (not seconds)
  1967. //
  1968. // Uses Alg_time_sigs::cut() to avoid writing a special case
  1969. double dur = end + 1000;
  1970. if (len > 0) {
  1971. dur = time_sigs[len - 1].beat + 1000;
  1972. }
  1973. cut(end, dur, dur);
  1974. cut(0, start, dur);
  1975. #ifdef IGNORE_THIS_OLD_CODE
  1976. // first, skip time signatures up to start
  1977. int i = find_beat(start);
  1978. // i is where you would insert a new time sig at beat,
  1979. // Case 1: beat coincides with a time sig at i. Time signature
  1980. // at beat means that there is a barline at beat, so when beat
  1981. // is shifted to 0, the relative barline positions are preserved
  1982. if (len > 0 &&
  1983. within(start, time_sigs[i].beat, ALG_EPS)) {
  1984. // beat coincides with time signature change, so offset must
  1985. // be a multiple of beats
  1986. /* do nothing */ ;
  1987. // Case 2: there is no time signature before start
  1988. } else if (i == 0 && (len == 0 ||
  1989. time_sigs[0].beat > start)) {
  1990. // If the next time signature does not fall on a barline,
  1991. // then start must not be on a barline, so there is a partial
  1992. // measure from start to the next barline. We need
  1993. // a time signature there to preserve relative barline
  1994. // locations. It may be that the next bar after start is
  1995. // due to another time signature, in which case we do not
  1996. // need to insert anything.
  1997. double measures = start / 4.0;
  1998. double imeasures = ROUND(measures);
  1999. if (!within(measures, imeasures, ALG_EPS)) {
  2000. // start is not on a barline, maybe add one here:
  2001. double bar_loc = (int(measures) + 1) * 4.0;
  2002. if (len == 0 || time_sigs[1].beat > bar_loc + ALG_EPS) {
  2003. insert(bar_loc, 4, 4, true);
  2004. }
  2005. }
  2006. // This case should never be true because if i == 0, either there
  2007. // are no time signatures before beat (Case 2),
  2008. // or there is one time signature at beat (Case 1)
  2009. } else if (i == 0) {
  2010. /* do nothing (might be good to assert(false)) */ ;
  2011. // Case 3: i-1 must be the effective time sig position
  2012. } else {
  2013. i -= 1; // index the time signature in effect at start
  2014. Alg_time_sig &tsp = time_sigs[i];
  2015. double beats_per_measure = (tsp.num * 4) / tsp.den;
  2016. double measures = (start - tsp.beat) / beats_per_measure;
  2017. int imeasures = ROUND(measures);
  2018. if (!within(measures, imeasures, ALG_EPS)) {
  2019. // beat is not on a measure, so we need to insert a time sig
  2020. // to force a bar line at the first measure location after
  2021. // beat, if any
  2022. double bar_loc = tsp.beat + beats_per_measure * (int(measures) + 1);
  2023. // insert new time signature at bar_loc
  2024. // It will have the same time signature, but the position will
  2025. // force a barline to match the barline before the shift
  2026. insert(bar_loc, tsp.num, tsp.den, true);
  2027. }
  2028. // else beat coincides with a barline, so no need for an extra
  2029. // time signature to force barline alignment
  2030. }
  2031. // since we may have inserted a time signature, find position again:
  2032. int i_in = find_beat(start);
  2033. int i_out = 0;
  2034. // put time_sig at start if necessary
  2035. // if 0 < i_in < len, then the time sig at i_in is either
  2036. // at start or after start.
  2037. // If after start, then insert time sig at i_in-1 at 0.
  2038. // Otherwise, we'll pick up time sig at i_in below.
  2039. // If 0 == i_in < len, then the time sig at i_in is either
  2040. // at start or after start.
  2041. // If after start, then time sig at 0 is 4/4, but that's the
  2042. // default, so do nothing.
  2043. // Otherwise, we'll pick up time sig at i_in below.
  2044. // If 0 < i_in == len, then insert time_sig at i_in-1 at start
  2045. // If 0 == i_in == len, then 4/4 default applies and we're done.
  2046. //
  2047. // So the conditions for inserting time_sig[in_i-1] at 0 are:
  2048. // (0 < i_in < len and time_sig[i] > start+ALG_EPS) OR
  2049. // (0 < i_in == len)
  2050. // We can rewrite this to
  2051. // (0 < i_in) && ((i_in < len && time_sig[i_in].beat > start + ALG_EPS) ||
  2052. // (i_in == len)))
  2053. //
  2054. if (0 < i_in && ((i_in < len && time_sigs[i_in].beat > start + ALG_EPS) ||
  2055. (i_in == len))) {
  2056. time_sigs[0] = time_sigs[i_in - 1];
  2057. time_sigs[0].beat = 0.0;
  2058. i_out = 1;
  2059. }
  2060. // copy from i_in to i_out as we scan time_sig array to end of cut region
  2061. while (i_in < len && time_sigs[i_in].beat < end - ALG_EPS) {
  2062. Alg_time_sig &ts = time_sigs[i_in];
  2063. ts.beat = ts.beat - start;
  2064. time_sigs[i_out] = ts;
  2065. i_in++;
  2066. i_out++;
  2067. }
  2068. len = i_out;
  2069. #endif
  2070. }
  2071. void Alg_time_sigs::paste(double start, Alg_seq *seq)
  2072. {
  2073. // printf("time_sig::insert before paste\n");
  2074. // show();
  2075. Alg_time_sigs &from = seq->time_sig;
  2076. // printf("time_sig::insert from\n");
  2077. // from.show();
  2078. // insert time signatures from seq into this time_sigs at start
  2079. if (len == 0 && from.len == 0) {
  2080. return; // default applies
  2081. }
  2082. int i = find_beat(start);
  2083. // remember the time signature at the splice point
  2084. double num_after_splice = 4;
  2085. double den_after_splice = 4; // default
  2086. double num_before_splice = 4;
  2087. double den_before_splice = 4; // default
  2088. // this is computed for use in aligning beats after the inserted
  2089. // time signatures and duration. It is the position of time signature
  2090. // in effect immediately after start (the time signature will be
  2091. // before start or at start)
  2092. double beat_after_splice = 0.0;
  2093. // three cases:
  2094. // 1) time sig at splice is at i-1
  2095. // for this, we must have len>0 & i>0
  2096. // two sub-cases:
  2097. // A) i < len && time_sig[i].beat > start
  2098. // B) i == len
  2099. // 2) time_sig at splice is at i
  2100. // for this, i < len && time_sig[i].beat ~= start
  2101. // 3) time_sig at splice is default 4/4
  2102. if (len > 0 && i > 0 &&
  2103. ((i < len && time_sigs[i].beat > start + ALG_EPS) ||
  2104. (i == len))) {
  2105. // no time_signature at i
  2106. num_after_splice = time_sigs[i-1].num;
  2107. den_after_splice = time_sigs[i-1].den;
  2108. beat_after_splice = time_sigs[i - 1].beat;
  2109. num_before_splice = num_after_splice;
  2110. den_before_splice = den_after_splice;
  2111. } else if (i < len && time_sigs[i].beat <= start + ALG_EPS) {
  2112. // time_signature at i is at "start" beats
  2113. num_after_splice = time_sigs[i].num;
  2114. den_after_splice = time_sigs[i].den;
  2115. beat_after_splice = start;
  2116. if (i > 0) { // time signature before start is at i - 1
  2117. num_before_splice = time_sigs[i-1].num;
  2118. den_before_splice = time_sigs[i-1].den;
  2119. }
  2120. }
  2121. // i is where insert will go, time_sig[i].beat >= start
  2122. // begin by adding duration to time_sig's at i and above
  2123. // move time signatures forward by duration of seq
  2124. double dur = seq->get_beat_dur();
  2125. while (i < len) {
  2126. time_sigs[i].beat += dur;
  2127. i++;
  2128. }
  2129. //printf("time_sig::insert after making space\n");
  2130. //show();
  2131. // If time signature of "from" is not the effective time signature
  2132. // at start, insert a time_signature at start. This may create
  2133. // an extra measure if seq does not begin on a measure boundary
  2134. double num_of_insert = 4.0;
  2135. double den_of_insert = 4.0;
  2136. double beat_of_insert = 0.0;
  2137. int first_from_index = 0; // where to start copying from
  2138. if (from.length() > 0 && from[0].beat < ALG_EPS) {
  2139. // there is an initial time signature in "from"
  2140. num_of_insert = from[0].num;
  2141. den_of_insert = from[0].den;
  2142. // since we are handling the first time signature in from,
  2143. // we can start copying at index == 1:
  2144. first_from_index = 1;
  2145. }
  2146. // compare time signatures to see if we need a change at start:
  2147. if (num_before_splice != num_of_insert ||
  2148. den_before_splice != den_of_insert) {
  2149. // note that this will overwrite an existing time signature if
  2150. // it is within ALG_EPS of start -- this is correct because the
  2151. // existing time signature will already be recorded as
  2152. // num_after_splice and den_after_splice
  2153. insert(start, num_of_insert, den_of_insert);
  2154. }
  2155. //printf("time_sig::insert after 4/4 at start\n");
  2156. //show();
  2157. // insert time signatures from seq offset by start
  2158. for (i = 0; i < from.length() && from[i].beat < dur - ALG_EPS; i++) {
  2159. num_of_insert = from[i].num; // keep latest time signature info
  2160. den_of_insert = from[i].den;
  2161. beat_of_insert = from[i].beat;
  2162. insert(start + beat_of_insert, num_of_insert, den_of_insert);
  2163. }
  2164. //printf("time_sig::insert after pasting in sigs\n");
  2165. //show();
  2166. // now insert time signature at end of splice if necessary
  2167. // if the time signature changes, we need to insert a time signature
  2168. // immediately:
  2169. if (num_of_insert != num_after_splice &&
  2170. den_of_insert != den_after_splice) {
  2171. insert(start + dur, num_after_splice, den_after_splice);
  2172. num_of_insert = num_after_splice;
  2173. den_of_insert = den_after_splice;
  2174. beat_of_insert = start + dur;
  2175. }
  2176. // if the insert had a partial number of measures, we might need an
  2177. // additional time signature to realign the barlines after the insert
  2178. // To decide, we compare the beat of the first barline on or after
  2179. // start before the splice to the beat of the first barline on or
  2180. // after start + dur after the splice. In a sense, this is the "same"
  2181. // barline, so it should be shifted exactly by dur.
  2182. // First, compute the beat of the first barline on or after start:
  2183. double beats_per_measure = (num_after_splice * 4) / den_after_splice;
  2184. double measures = (start - beat_after_splice) / beats_per_measure;
  2185. // Measures might be slightly negative due to rounding. Use max()
  2186. // to eliminate any negative rounding error:
  2187. int imeasures = int(max(measures, 0.0));
  2188. double old_bar_loc = beat_after_splice + (imeasures * beats_per_measure);
  2189. if (old_bar_loc < start) old_bar_loc += beats_per_measure;
  2190. // now old_bar_loc is the original first bar position after start
  2191. // Do similar calculation for position after end after the insertion:
  2192. // beats_per_measure already calculated because signatures match
  2193. measures = (start + dur - beat_of_insert) / beats_per_measure;
  2194. imeasures = int(max(measures, 0.0));
  2195. double new_bar_loc = beat_of_insert + (imeasures * beats_per_measure);
  2196. if (new_bar_loc < start + dur) new_bar_loc += beats_per_measure;
  2197. // old_bar_loc should be shifted by dur:
  2198. old_bar_loc += dur;
  2199. // now the two bar locations should be equal, but due to rounding,
  2200. // they could be off by one measure
  2201. double diff = (new_bar_loc - old_bar_loc) + beats_per_measure;
  2202. double diff_in_measures = diff / beats_per_measure;
  2203. // if diff_in_measures is not (approximately) integer, we need to
  2204. // force a barline (time signature) after start + dur to maintain
  2205. // the relationship between barliness and notes
  2206. if (!within(diff_in_measures, ROUND(diff_in_measures), ALG_EPS)) {
  2207. // recall that old_bar_loc is shifted by dur
  2208. insert(old_bar_loc, num_after_splice, den_after_splice);
  2209. }
  2210. //printf("time_sig::insert after sig at end of splice\n");
  2211. //show();
  2212. }
  2213. void Alg_time_sigs::insert_beats(double start, double dur)
  2214. {
  2215. int i = find_beat(start);
  2216. // time_sigs[i] is after beat and needs to shift
  2217. // Compute the time of the first bar at or after beat so that
  2218. // a bar can be placed at bar_loc + dur
  2219. double tsnum = 4.0;
  2220. double tsden = 4.0;
  2221. double tsbeat = 0.0; // defaults
  2222. // three cases:
  2223. // 1) time sig at splice is at i-1
  2224. // for this, we must have len>0 & i>0
  2225. // two sub-cases:
  2226. // A) i < len && time_sig[i].beat > start
  2227. // B) i == len
  2228. // 2) time_sig at splice is at i
  2229. // for this, i < len && time_sig[i].beat ~= start
  2230. // 3) time_sig at splice is default 4/4
  2231. if (len > 0 && i > 0 &&
  2232. ((i < len && time_sigs[i].beat > start + ALG_EPS) ||
  2233. (i == len))) {
  2234. // no time_signature at i
  2235. tsnum = time_sigs[i-1].num;
  2236. tsden = time_sigs[i-1].den;
  2237. tsbeat = time_sigs[i-1].beat;
  2238. } else if (i < len && time_sigs[i].beat <= start + ALG_EPS) {
  2239. // time_signature at i is at "start" beats
  2240. tsnum = time_sigs[i].num;
  2241. tsden = time_sigs[i].den;
  2242. tsbeat = start;
  2243. i++; // we want i to be index of next time signature after start
  2244. }
  2245. // invariant: i is index of next time signature after start
  2246. // increase beat times from i to len - 1 by dur
  2247. for (int j = i; j < len; j++) {
  2248. time_sigs[j].beat += dur;
  2249. }
  2250. // insert a time signature to maintain bar positions if necessary
  2251. double beats_per_measure = (tsnum * 4) / tsden;
  2252. double measures = dur / beats_per_measure; // shift distance
  2253. int imeasures = ROUND(measures);
  2254. if (!within(measures, imeasures, ALG_EPS)) {
  2255. // shift is not a whole number of measures, so we may need to insert
  2256. // time signature after silence
  2257. // compute measures from time signature to next bar after time
  2258. measures = (start - tsbeat) / beats_per_measure;
  2259. // round up and add to tsbeat to get time of next bar
  2260. double bar_loc = tsbeat + beats_per_measure * (int(measures) + 1);
  2261. // translate bar_loc by len:
  2262. bar_loc += dur; // this is where we want a bar to be, but maybe
  2263. // there is a time signature change before bar, in which case we
  2264. // should not insert a new time signature
  2265. // The next time signature after start is at i if i < len
  2266. if (i < len && time_sigs[i].beat < bar_loc) {
  2267. /* do not insert */;
  2268. } else {
  2269. insert(bar_loc, tsnum, tsden);
  2270. }
  2271. }
  2272. }
  2273. double Alg_time_sigs::nearest_beat(double beat)
  2274. {
  2275. int i = find_beat(beat);
  2276. // i is where we would insert time signature at beat
  2277. // case 1: there is no time signature
  2278. if (i == 0 && len == 0) {
  2279. return ROUND(beat);
  2280. // case 2: beat falls approximately on time signature
  2281. } else if (i < len && within(time_sigs[i].beat, beat, ALG_EPS)) {
  2282. return time_sigs[i].beat;
  2283. // case 3: beat is after no time signature and before one
  2284. } else if (i == 0) {
  2285. double trial_beat = ROUND(beat);
  2286. // it is possible that we rounded up past a time signature
  2287. if (trial_beat > time_sigs[0].beat - ALG_EPS) {
  2288. return time_sigs[0].beat;
  2289. }
  2290. return trial_beat;
  2291. }
  2292. // case 4: beat is after some time signature
  2293. double trial_beat = time_sigs[i - 1].beat +
  2294. ROUND(beat - time_sigs[i - 1].beat);
  2295. // rounding may advance trial_beat past next time signature:
  2296. if (i < len && trial_beat > time_sigs[i].beat - ALG_EPS) {
  2297. return time_sigs[i].beat;
  2298. }
  2299. return trial_beat;
  2300. }
  2301. Alg_tracks::~Alg_tracks()
  2302. {
  2303. reset();
  2304. }
  2305. void Alg_tracks::expand_to(int new_max)
  2306. {
  2307. maxlen = new_max;
  2308. Alg_track_ptr *new_tracks = new Alg_track_ptr[maxlen];
  2309. // now do copy
  2310. memcpy(new_tracks, tracks, len * sizeof(Alg_track_ptr));
  2311. if (tracks) {
  2312. delete[] tracks;
  2313. }
  2314. tracks = new_tracks;
  2315. }
  2316. void Alg_tracks::expand()
  2317. {
  2318. maxlen = (maxlen + 5); // extra growth for small sizes
  2319. maxlen += (maxlen >> 2); // add 25%
  2320. expand_to(maxlen);
  2321. }
  2322. void Alg_tracks::append(Alg_track_ptr track)
  2323. {
  2324. if (maxlen <= len) {
  2325. expand();
  2326. }
  2327. tracks[len] = track;
  2328. len++;
  2329. }
  2330. void Alg_tracks::add_track(int track_num, Alg_time_map_ptr time_map,
  2331. bool seconds)
  2332. // Create a new track at index track_num.
  2333. // If track already exists, this call does nothing.
  2334. // If highest previous track is not at track_num-1, then
  2335. // create tracks at len, len+1, ..., track_num.
  2336. {
  2337. assert(track_num >= 0);
  2338. if (track_num == maxlen) {
  2339. // use eponential growth to insert tracks sequentially
  2340. expand();
  2341. } else if (track_num > maxlen) {
  2342. // grow to exact size for random inserts
  2343. expand_to(track_num + 1);
  2344. }
  2345. if (track_num < len) return; // don't add if already there
  2346. while (len <= track_num) {
  2347. tracks[len] = new Alg_track(time_map, seconds);
  2348. //printf("allocated track at %d (%x, this %x) = %x\n", len,
  2349. // &(tracks[len]), this, tracks[len]);
  2350. len++;
  2351. }
  2352. }
  2353. void Alg_tracks::reset()
  2354. {
  2355. // all track events are incorporated into the seq,
  2356. // so all we need to delete are the arrays of pointers
  2357. for (int i = 0; i < len; i++) {
  2358. // printf("deleting track at %d (%x, this %x) = %x\n", i, &(tracks[i]),
  2359. // this, tracks[i]);
  2360. delete tracks[i];
  2361. }
  2362. if (tracks) delete [] tracks;
  2363. tracks = NULL;
  2364. len = 0;
  2365. maxlen = 0;
  2366. }
  2367. void Alg_tracks::set_in_use(bool flag)
  2368. {
  2369. for (int i = 0; i < len; i++) {
  2370. tracks[i]->in_use = flag;
  2371. }
  2372. }
  2373. void Alg_iterator::expand_to(int new_max)
  2374. {
  2375. maxlen = new_max;
  2376. Alg_pending_event_ptr new_pending_events = new Alg_pending_event[maxlen];
  2377. // now do copy
  2378. memcpy(new_pending_events, pending_events,
  2379. len * sizeof(Alg_pending_event));
  2380. if (pending_events) {
  2381. delete[] pending_events;
  2382. }
  2383. pending_events = new_pending_events;
  2384. }
  2385. void Alg_iterator::expand()
  2386. {
  2387. maxlen = (maxlen + 5); // extra growth for small sizes
  2388. maxlen += (maxlen >> 2); // add 25%
  2389. expand_to(maxlen);
  2390. }
  2391. Alg_iterator::~Alg_iterator()
  2392. {
  2393. if (pending_events) {
  2394. delete[] pending_events;
  2395. }
  2396. }
  2397. /* in the heap, the children of N are (N+1)*2 and (N+1)*2-1, so
  2398. * the parent of N is (N+1)/2-1. This would be easier if arrays
  2399. * were 1-based instead of 0-based
  2400. */
  2401. #define HEAP_PARENT(loc) ((((loc) + 1) / 2) - 1)
  2402. #define FIRST_CHILD(loc) (((loc) * 2) + 1)
  2403. void Alg_iterator::show()
  2404. {
  2405. for (int i = 0; i < len; i++) {
  2406. Alg_pending_event_ptr p = &(pending_events[i]);
  2407. printf(" %d: %p[%ld]@%g on %d\n", i, p->events, p->index,
  2408. p->offset, p->note_on);
  2409. }
  2410. }
  2411. bool Alg_iterator::earlier(int i, int j)
  2412. // see if event i is earlier than event j
  2413. {
  2414. // note-offs are scheduled ALG_EPS early so that if a note-off is
  2415. // followed immediately with the same timestamp by a note-on (common
  2416. // in MIDI files), the note-off will be scheduled first
  2417. double t_i = pending_events[i].time;
  2418. double t_j = pending_events[j].time;
  2419. if (t_i < t_j) return true;
  2420. // not sure if this case really exists or this is the best rule, but
  2421. // we want to give precedence to note-off events
  2422. else if (t_i == t_j && pending_events[j].note_on) return true;
  2423. return false;
  2424. }
  2425. void Alg_iterator::insert(Alg_events_ptr events, long index,
  2426. bool note_on, void *cookie, double offset)
  2427. {
  2428. if (len == maxlen) expand();
  2429. pending_events[len].events = events;
  2430. pending_events[len].index = index;
  2431. pending_events[len].note_on = note_on;
  2432. pending_events[len].cookie = cookie;
  2433. pending_events[len].offset = offset;
  2434. Alg_event_ptr event = (*events)[index];
  2435. pending_events[len].time = (note_on ? event->time :
  2436. event->get_end_time() - ALG_EPS) + offset;
  2437. /* BEGIN DEBUG *
  2438. printf("insert %p=%p[%d] @ %g\n", event, events, index,
  2439. pending_events[len].time);
  2440. printf(" is_note %d note_on %d time %g dur %g end_time %g offset %g\n",
  2441. event->is_note(), note_on, event->time, event->get_duration(),
  2442. event->get_end_time(), offset);
  2443. }
  2444. * END DEBUG */
  2445. int loc = len;
  2446. int loc_parent = HEAP_PARENT(loc);
  2447. len++;
  2448. // sift up:
  2449. while (loc > 0 &&
  2450. earlier(loc, loc_parent)) {
  2451. // swap loc with loc_parent
  2452. Alg_pending_event temp = pending_events[loc];
  2453. pending_events[loc] = pending_events[loc_parent];
  2454. pending_events[loc_parent] = temp;
  2455. loc = loc_parent;
  2456. loc_parent = HEAP_PARENT(loc);
  2457. }
  2458. }
  2459. bool Alg_iterator::remove_next(Alg_events_ptr &events, long &index,
  2460. bool &note_on, void *&cookie,
  2461. double &offset, double &time)
  2462. {
  2463. if (len == 0) return false; // empty!
  2464. events = pending_events[0].events;
  2465. index = pending_events[0].index;
  2466. note_on = pending_events[0].note_on;
  2467. offset = pending_events[0].offset;
  2468. cookie = pending_events[0].cookie;
  2469. offset = pending_events[0].offset;
  2470. time = pending_events[0].time;
  2471. len--;
  2472. pending_events[0] = pending_events[len];
  2473. // sift down
  2474. long loc = 0;
  2475. long loc_child = FIRST_CHILD(loc);
  2476. while (loc_child < len) {
  2477. if (loc_child + 1 < len) {
  2478. if (earlier(loc_child + 1, loc_child)) {
  2479. loc_child++;
  2480. }
  2481. }
  2482. if (earlier(loc_child, loc)) {
  2483. Alg_pending_event temp = pending_events[loc];
  2484. pending_events[loc] = pending_events[loc_child];
  2485. pending_events[loc_child] = temp;
  2486. loc = loc_child;
  2487. loc_child = FIRST_CHILD(loc);
  2488. } else {
  2489. loc_child = len;
  2490. }
  2491. }
  2492. // printf("After remove:"); show();
  2493. return true;
  2494. }
  2495. Alg_seq::Alg_seq(const char *filename, bool smf, double *offset_ptr)
  2496. {
  2497. basic_initialization();
  2498. ifstream inf(filename, smf ? ios::binary | ios::in : ios::in);
  2499. if (inf.fail()) {
  2500. error = alg_error_open;
  2501. return;
  2502. }
  2503. if (smf) {
  2504. error = alg_smf_read(inf, this);
  2505. if (offset_ptr) *offset_ptr = 0.0;
  2506. } else {
  2507. error = alg_read(inf, this, offset_ptr);
  2508. }
  2509. inf.close();
  2510. }
  2511. Alg_seq::Alg_seq(istream &file, bool smf, double *offset_ptr)
  2512. {
  2513. basic_initialization();
  2514. if (smf) {
  2515. error = alg_smf_read(file, this);
  2516. if (offset_ptr) *offset_ptr = 0.0;
  2517. } else {
  2518. error = alg_read(file, this, offset_ptr);
  2519. }
  2520. }
  2521. void Alg_seq::seq_from_track(Alg_track_ref tr)
  2522. {
  2523. type = 's';
  2524. // copy everything
  2525. set_beat_dur(tr.get_beat_dur());
  2526. set_real_dur(tr.get_real_dur());
  2527. // copy time_map
  2528. set_time_map(new Alg_time_map(tr.get_time_map()));
  2529. units_are_seconds = tr.get_units_are_seconds();
  2530. if (tr.get_type() == 's') {
  2531. Alg_seq_ref s = *(tr.to_alg_seq());
  2532. channel_offset_per_track = s.channel_offset_per_track;
  2533. add_track(s.tracks() - 1);
  2534. // copy each track
  2535. for (int i = 0; i < tracks(); i++) {
  2536. Alg_track_ref from_track = *(s.track(i));
  2537. Alg_track_ref to_track = *(track(i));
  2538. to_track.set_beat_dur(from_track.get_beat_dur());
  2539. to_track.set_real_dur(from_track.get_real_dur());
  2540. if (from_track.get_units_are_seconds())
  2541. to_track.convert_to_seconds();
  2542. for (int j = 0; j < from_track.length(); j++) {
  2543. Alg_event_ptr event = copy_event(from_track[j]);
  2544. to_track.append(event);
  2545. }
  2546. }
  2547. } else if (tr.get_type() == 't') {
  2548. add_track(0);
  2549. channel_offset_per_track = 0;
  2550. Alg_track_ptr to_track = track(0);
  2551. to_track->set_beat_dur(tr.get_beat_dur());
  2552. to_track->set_real_dur(tr.get_real_dur());
  2553. for (int j = 0; j < tr.length(); j++) {
  2554. Alg_event_ptr event = copy_event(tr[j]);
  2555. to_track->append(event);
  2556. }
  2557. } else {
  2558. assert(false); // expected track or sequence
  2559. }
  2560. }
  2561. int Alg_seq::tracks()
  2562. {
  2563. return track_list.length();
  2564. }
  2565. Alg_track_ptr Alg_seq::track(int i)
  2566. {
  2567. assert(0 <= i && i < track_list.length());
  2568. return &(track_list[i]);
  2569. }
  2570. #pragma warning(disable: 4715) // ok not to return a value here
  2571. Alg_event_ptr &Alg_seq::operator[](int i)
  2572. {
  2573. int ntracks = track_list.length();
  2574. int tr = 0;
  2575. while (tr < ntracks) {
  2576. Alg_track *a_track = track(tr);
  2577. if (a_track && i < a_track->length()) {
  2578. return (*a_track)[i];
  2579. } else if (a_track) {
  2580. i -= a_track->length();
  2581. }
  2582. tr++;
  2583. }
  2584. assert(false); // out of bounds
  2585. }
  2586. #pragma warning(default: 4715)
  2587. void Alg_seq::convert_to_beats()
  2588. {
  2589. if (!units_are_seconds) return;
  2590. for (int i = 0; i < tracks(); i++) {
  2591. track(i)->convert_to_beats();
  2592. }
  2593. // note that the Alg_seq inherits units_are_seconds from an
  2594. // empty track. Each track also has a (redundant) field called
  2595. // units are seconds. These should always be consistent.
  2596. units_are_seconds = false;
  2597. }
  2598. void Alg_seq::convert_to_seconds()
  2599. {
  2600. if (units_are_seconds) return;
  2601. //printf("convert_to_seconds, tracks %d\n", tracks());
  2602. //printf("last_tempo of seq: %g on map %x\n",
  2603. // get_time_map()->last_tempo, get_time_map());
  2604. for (int i = 0; i < tracks(); i++) {
  2605. //printf("last_tempo of track %d: %g on %x\n", i,
  2606. // track(i)->get_time_map()->last_tempo,
  2607. // track(i)->get_time_map());
  2608. track(i)->convert_to_seconds();
  2609. }
  2610. // update our copy of last_note_off (which may or may not be valid)
  2611. last_note_off = time_map->beat_to_time(last_note_off);
  2612. // note that the Alg_seq inherits units_are_seconds from an
  2613. // empty track. Each track also has a (redundant) field called
  2614. // units are seconds. These should always be consistent.
  2615. units_are_seconds = true;
  2616. }
  2617. Alg_track_ptr Alg_seq::cut_from_track(int track_num, double start,
  2618. double dur, bool all)
  2619. {
  2620. assert(track_num >= 0 && track_num < tracks());
  2621. Alg_track_ptr tr = track(track_num);
  2622. return tr->cut(start, dur, all);
  2623. }
  2624. void Alg_seq::copy_time_sigs_to(Alg_seq *dest)
  2625. {
  2626. // copy time signatures
  2627. for (int i = 0; i < time_sig.length(); i++) {
  2628. dest->time_sig.insert(time_sig[i].beat, time_sig[i].num,
  2629. time_sig[i].den);
  2630. }
  2631. }
  2632. void Alg_seq::set_time_map(Alg_time_map *map)
  2633. {
  2634. Alg_track::set_time_map(map);
  2635. for (int i = 0; i < tracks(); i++) {
  2636. track(i)->set_time_map(map);
  2637. }
  2638. }
  2639. Alg_seq_ptr Alg_seq::cut(double start, double len, bool all)
  2640. // return sequence from start to start+len and modify this
  2641. // sequence by removing that time-span
  2642. {
  2643. double dur = get_dur();
  2644. // fix parameters to fall within existing sequence
  2645. if (start > dur) return NULL; // nothing to cut
  2646. if (start < 0) start = 0; // can't start before sequence starts
  2647. if (start + len > dur) // can't cut after end:
  2648. len = dur - start;
  2649. Alg_seq_ptr result = new Alg_seq();
  2650. Alg_time_map_ptr map = new Alg_time_map(get_time_map());
  2651. result->set_time_map(map);
  2652. copy_time_sigs_to(result);
  2653. result->units_are_seconds = units_are_seconds;
  2654. result->track_list.reset();
  2655. for (int i = 0; i < tracks(); i++) {
  2656. Alg_track_ptr cut_track = cut_from_track(i, start, len, all);
  2657. result->track_list.append(cut_track);
  2658. // initially, result->last_note_off is zero. We want to know the
  2659. // maximum over all cut_tracks, so compute that here:
  2660. result->last_note_off = MAX(result->last_note_off,
  2661. cut_track->last_note_off);
  2662. // since we're moving to a new sequence, change the track's time_map
  2663. result->track_list[i].set_time_map(map);
  2664. }
  2665. // put units in beats to match time_sig's. Note that we need
  2666. // two different end times. For result, we want the time of the
  2667. // last note off, but for cutting out the time signatures in this,
  2668. // we use len.
  2669. double ts_start = start;
  2670. double ts_end = start + len;
  2671. double ts_dur = dur;
  2672. double ts_last_note_off = start + result->last_note_off;
  2673. if (units_are_seconds) {
  2674. ts_start = time_map->time_to_beat(ts_start);
  2675. ts_end = time_map->time_to_beat(ts_end);
  2676. ts_last_note_off = time_map->time_to_beat(ts_last_note_off);
  2677. ts_dur = time_map->time_to_beat(ts_dur);
  2678. }
  2679. // result is shifted from start to 0 and has length len, but
  2680. // time_sig and time_map are copies from this. Adjust time_sig,
  2681. // time_map, and duration fields in result. The time_sig and
  2682. // time_map data is retained out to last_note_off so that we have
  2683. // information for the entire duration of all the notes, even though
  2684. // this might extend beyond the duration of the track. (Warning:
  2685. // no info is retained for notes with negative times.)
  2686. result->time_sig.trim(ts_start, ts_last_note_off);
  2687. result->time_map->trim(start, start + result->last_note_off,
  2688. result->units_are_seconds);
  2689. // even though there might be notes sticking out beyond len, the
  2690. // track duration is len, not last_note_off. (Warning: if all is
  2691. // true, there may also be notes at negative offsets. These times
  2692. // cannot be mapped between beat and time representations, so there
  2693. // may be subtle bugs or unexpected behaviors in that case.)
  2694. result->set_dur(len);
  2695. // we sliced out a portion of each track, so now we need to
  2696. // slice out the corresponding sections of time_sig and time_map
  2697. // as well as to adjust the duration.
  2698. time_sig.cut(ts_start, ts_end, ts_dur);
  2699. time_map->cut(start, len, units_are_seconds);
  2700. set_dur(dur - len);
  2701. return result;
  2702. }
  2703. void Alg_seq::insert_silence_in_track(int track_num, double t, double len)
  2704. {
  2705. Alg_track_ptr tr = track(track_num);
  2706. tr->insert_silence(t, len);
  2707. }
  2708. void Alg_seq::insert_silence(double t, double len)
  2709. {
  2710. for (int i = 0; i < tracks(); i++) {
  2711. insert_silence_in_track(i, t, len);
  2712. }
  2713. double t_beats = t;
  2714. double len_beats = len;
  2715. // insert into time_sig array; use time_sig_paste,
  2716. // which requires us to build a simple time_sig array
  2717. if (units_are_seconds) {
  2718. time_map->insert_time(t, len);
  2719. t_beats = time_map->time_to_beat(t);
  2720. len_beats = time_map->time_to_beat(t + len) - t_beats;
  2721. } else {
  2722. time_map->insert_beats(t_beats, len_beats);
  2723. }
  2724. time_sig.insert_beats(t_beats, len_beats);
  2725. // Final duration is defined to be t + len + whatever was
  2726. // in the sequence after t (if any). This translates to
  2727. // t + len + max(dur - t, 0)
  2728. set_dur(t + len + max(get_dur() - t, 0.0));
  2729. }
  2730. Alg_track_ptr Alg_seq::copy_track(int track_num, double t, double len, bool all)
  2731. {
  2732. return track_list[track_num].copy(t, len, all);
  2733. }
  2734. Alg_seq *Alg_seq::copy(double start, double len, bool all)
  2735. {
  2736. // fix parameters to fall within existing sequence
  2737. if (start > get_dur()) return NULL; // nothing to copy
  2738. if (start < 0) start = 0; // can't copy before sequence starts
  2739. if (start + len > get_dur()) // can't copy after end:
  2740. len = get_dur() - start;
  2741. // return (new) sequence from start to start + len
  2742. Alg_seq_ptr result = new Alg_seq();
  2743. Alg_time_map_ptr map = new Alg_time_map(get_time_map());
  2744. result->set_time_map(map);
  2745. copy_time_sigs_to(result);
  2746. result->units_are_seconds = units_are_seconds;
  2747. result->track_list.reset();
  2748. for (int i = 0; i < tracks(); i++) {
  2749. Alg_track_ptr copy = copy_track(i, start, len, all);
  2750. result->track_list.append(copy);
  2751. result->last_note_off = MAX(result->last_note_off,
  2752. copy->last_note_off);
  2753. // since we're copying to a new seq, change the track's time_map
  2754. result->track_list[i].set_time_map(map);
  2755. }
  2756. // put units in beats to match time_sig's. Note that we need
  2757. // two different end times. For result, we want the time of the
  2758. // last note off, but for cutting out the time signatures in this,
  2759. // we use len.
  2760. double ts_start = start;
  2761. double ts_end = start + len;
  2762. double ts_last_note_off = start + result->last_note_off;
  2763. if (units_are_seconds) {
  2764. ts_start = time_map->time_to_beat(ts_start);
  2765. ts_end = time_map->time_to_beat(ts_end);
  2766. ts_last_note_off = time_map->time_to_beat(ts_last_note_off);
  2767. }
  2768. result->time_sig.trim(ts_start, ts_last_note_off);
  2769. result->time_map->trim(start, start + result->last_note_off,
  2770. units_are_seconds);
  2771. result->set_dur(len);
  2772. return result;
  2773. }
  2774. void Alg_seq::paste(double start, Alg_seq *seq)
  2775. {
  2776. // Insert seq at time, opening up space for it.
  2777. // To manipulate time map, we need units as beats.
  2778. // Save original form so we can convert back if necessary.
  2779. bool units_should_be_seconds = units_are_seconds;
  2780. bool seq_units_should_be_seconds = seq->get_units_are_seconds();
  2781. if (units_are_seconds) {
  2782. start = time_map->time_to_beat(start);
  2783. convert_to_beats();
  2784. }
  2785. seq->convert_to_beats();
  2786. // do a paste on each track
  2787. int i;
  2788. for (i = 0; i < seq->tracks(); i++) {
  2789. if (i >= tracks()) {
  2790. add_track(i);
  2791. }
  2792. track(i)->paste(start, seq->track(i));
  2793. }
  2794. // make sure all tracks were opened up for an insert, even if
  2795. // there is nothing to insert
  2796. while (i < tracks()) {
  2797. track(i)->insert_silence(start, seq->get_dur());
  2798. i++;
  2799. }
  2800. // paste in tempo track
  2801. time_map->paste(start, seq);
  2802. // paste in time signatures
  2803. time_sig.paste(start, seq);
  2804. set_dur(get_beat_dur() + seq->get_dur());
  2805. assert(!seq->units_are_seconds && !units_are_seconds);
  2806. if (units_should_be_seconds) {
  2807. convert_to_seconds();
  2808. }
  2809. if (seq_units_should_be_seconds) {
  2810. seq->convert_to_seconds();
  2811. }
  2812. }
  2813. void Alg_seq::merge(double t, Alg_event_list_ptr seq)
  2814. {
  2815. // seq must be an Alg_seq:
  2816. assert(seq->get_type() == 's');
  2817. Alg_seq_ptr s = (Alg_seq_ptr) seq;
  2818. for (int i = 0; i < s->tracks(); i++) {
  2819. if (tracks() <= i) add_track(i);
  2820. track(i)->merge(t, s->track(i));
  2821. }
  2822. }
  2823. void Alg_seq::silence_track(int track_num, double start, double len, bool all)
  2824. {
  2825. // remove events in [time, time + len) and close gap
  2826. Alg_track_ptr tr = track(track_num);
  2827. tr->silence(start, len, all);
  2828. }
  2829. void Alg_seq::silence(double t, double len, bool all)
  2830. {
  2831. for (int i = 0; i < tracks(); i++) {
  2832. silence_track(i, t, len, all);
  2833. }
  2834. }
  2835. void Alg_seq::clear_track(int track_num, double start, double len, bool all)
  2836. {
  2837. // remove events in [time, time + len) and close gap
  2838. Alg_track_ptr tr = track(track_num);
  2839. tr->clear(start, len, all);
  2840. }
  2841. void Alg_seq::clear(double start, double len, bool all)
  2842. {
  2843. // Fix parameters to fall within existing sequence
  2844. double dur = get_dur();
  2845. if (start > dur) return; // nothing to cut
  2846. if (start < 0) start = 0; // can't start before sequence starts
  2847. if (start + len > dur) // can't cut after end:
  2848. len = dur - start;
  2849. for (int i = 0; i < tracks(); i++)
  2850. clear_track(i, start, len, all);
  2851. // Put units in beats to match time_sig's.
  2852. double ts_start = start;
  2853. double ts_end = start + len;
  2854. double ts_dur = dur;
  2855. if (units_are_seconds) {
  2856. ts_start = time_map->time_to_beat(ts_start);
  2857. ts_end = time_map->time_to_beat(ts_end);
  2858. ts_dur = time_map->time_to_beat(ts_dur);
  2859. }
  2860. // we sliced out a portion of each track, so now we need to
  2861. // slice out the corresponding sections of time_sig and time_map
  2862. // as well as to adjust the duration.
  2863. time_sig.cut(ts_start, ts_end, ts_dur);
  2864. time_map->cut(start, len, units_are_seconds);
  2865. set_dur(dur - len);
  2866. }
  2867. Alg_event_list_ptr Alg_seq::find_in_track(int track_num, double t, double len,
  2868. bool all, long channel_mask,
  2869. long event_type_mask)
  2870. {
  2871. return track(track_num)->find(t, len, all, channel_mask, event_type_mask);
  2872. }
  2873. Alg_seq::~Alg_seq()
  2874. {
  2875. int i, j;
  2876. // Tracks does not delete Alg_events elements
  2877. for (j = 0; j < track_list.length(); j++) {
  2878. Alg_track &notes = track_list[j];
  2879. // Alg_events does not delete notes
  2880. for (i = 0; i < notes.length(); i++) {
  2881. Alg_event_ptr event = notes[i];
  2882. delete event;
  2883. }
  2884. }
  2885. }
  2886. long Alg_seq::seek_time(double time, int track_num)
  2887. // find index of first score event after time
  2888. {
  2889. long i;
  2890. Alg_events &notes = track_list[track_num];
  2891. for (i = 0; i < notes.length(); i++) {
  2892. if (notes[i]->time > time) {
  2893. break;
  2894. }
  2895. }
  2896. return i;
  2897. }
  2898. bool Alg_seq::insert_beat(double time, double beat)
  2899. // insert a time,beat pair
  2900. // return true or false (false indicates an error, no update)
  2901. // it is an error to imply a negative tempo or to insert at
  2902. // a negative time
  2903. {
  2904. if (time < 0 || beat < 0) return false;
  2905. if (time == 0.0 && beat > 0)
  2906. time = 0.000001; // avoid infinite tempo, offset time by 1us
  2907. if (time == 0.0 && beat == 0.0)
  2908. return true; // (0,0) is already in the map!
  2909. convert_to_beats(); // beats are invariant when changing tempo
  2910. time_map->insert_beat(time, beat);
  2911. return true;
  2912. }
  2913. // input is time, return value is time
  2914. double Alg_seq::nearest_beat_time(double time, double *beat)
  2915. {
  2916. double b = time_map->time_to_beat(time);
  2917. b = time_sig.nearest_beat(b);
  2918. if (beat) *beat = b;
  2919. return time_map->beat_to_time(b);
  2920. }
  2921. bool Alg_seq::stretch_region(double b0, double b1, double dur)
  2922. {
  2923. bool units_should_be_seconds = units_are_seconds;
  2924. convert_to_beats();
  2925. bool result = time_map->stretch_region(b0, b1, dur);
  2926. if (units_should_be_seconds) convert_to_seconds();
  2927. return result;
  2928. }
  2929. bool Alg_seq::insert_tempo(double bpm, double beat)
  2930. {
  2931. double bps = bpm / 60.0; // convert to beats per second
  2932. // change the tempo at the given beat until the next beat event
  2933. if (beat < 0) return false;
  2934. convert_to_beats(); // beats are invariant when changing tempo
  2935. double time = time_map->beat_to_time(beat);
  2936. long i = time_map->locate_time(time);
  2937. if (i >= time_map->beats.len || !within(time_map->beats[i].time, time, 0.000001)) {
  2938. insert_beat(time, beat);
  2939. }
  2940. // now i is index of beat where tempo will change
  2941. if (i == time_map->beats.len - 1) {
  2942. time_map->last_tempo = bps;
  2943. time_map->last_tempo_flag = true;
  2944. } else { // adjust all future beats
  2945. // compute the difference in beats
  2946. double diff = time_map->beats[i + 1].beat - time_map->beats[i].beat;
  2947. // convert beat difference to seconds at new tempo
  2948. diff = diff / bps;
  2949. // figure out old time difference:
  2950. double old_diff = time_map->beats[i + 1].time - time;
  2951. // compute difference too
  2952. diff = diff - old_diff;
  2953. // apply new_diff to score and beats
  2954. while (i < time_map->beats.len) {
  2955. time_map->beats[i].time = time_map->beats[i].time + diff;
  2956. i++;
  2957. }
  2958. }
  2959. return true;
  2960. }
  2961. void Alg_seq::add_event(Alg_event_ptr event, int track_num)
  2962. // add_event puts an event in a given track (track_num).
  2963. // The track must exist. The time and duration of the
  2964. // event are interpreted according to whether the Alg_seq
  2965. // is currently in beats or seconds (see convert_to_beats())
  2966. {
  2967. track_list[track_num].insert(event);
  2968. /*
  2969. if (event->is_note()) {
  2970. Alg_note_ptr n = (Alg_note_ptr) event;
  2971. trace("note %d at %g for %g\n", n->get_identifier(), n->time, n->dur);
  2972. }
  2973. */
  2974. }
  2975. double Alg_seq::get_tempo(double beat)
  2976. {
  2977. return time_map->get_tempo(beat);
  2978. }
  2979. bool Alg_seq::set_tempo(double bpm, double start_beat, double end_beat)
  2980. // set tempo from start_beat to end_beat
  2981. {
  2982. // this is an optimization, the test is repeated in Alg_time_seq::set_tempo()
  2983. if (start_beat >= end_beat) return false;
  2984. bool units_should_be_seconds = units_are_seconds;
  2985. convert_to_beats();
  2986. double dur = get_dur();
  2987. bool result = time_map->set_tempo(bpm, start_beat, end_beat);
  2988. // preserve sequence duration in beats when tempo changes
  2989. set_dur(dur);
  2990. if (units_should_be_seconds) convert_to_seconds();
  2991. return result;
  2992. }
  2993. double Alg_seq::get_bar_len(double beat)
  2994. {
  2995. return time_sig.get_bar_len(beat);
  2996. }
  2997. void Alg_seq::set_time_sig(double beat, double num, double den)
  2998. {
  2999. time_sig.insert(beat, num, den);
  3000. }
  3001. void Alg_seq::beat_to_measure(double beat, long *measure, double *m_beat,
  3002. double *num, double *den)
  3003. {
  3004. // return [measure, beat, num, den]
  3005. double m = 0; // measure number
  3006. double bpm;
  3007. int tsx;
  3008. bpm = 4;
  3009. // assume 4/4 if no time signature
  3010. double prev_beat = 0;
  3011. double prev_num = 4;
  3012. double prev_den = 4;
  3013. if (beat < 0) beat = 0; // negative measures treated as zero
  3014. for (tsx = 0; tsx < time_sig.length(); tsx++) {
  3015. if (time_sig[tsx].beat <= beat) {
  3016. // round m up to an integer (but allow for a small
  3017. // numerical inaccuracy)
  3018. m = m + (long) (0.99 + (time_sig[tsx].beat - prev_beat) / bpm);
  3019. bpm = time_sig[tsx].num * 4 / time_sig[tsx].den;
  3020. prev_beat = time_sig[tsx].beat;
  3021. prev_num = time_sig[tsx].num;
  3022. prev_den = time_sig[tsx].den;
  3023. } else {
  3024. m = m + (beat - prev_beat) / bpm;
  3025. *measure = (long) m;
  3026. *m_beat = (m - *measure) * bpm;
  3027. *num = prev_num;
  3028. *den = prev_den;
  3029. return;
  3030. }
  3031. }
  3032. // if we didn't return yet, compute after last time signature
  3033. Alg_time_sig initial(0, 4, 4);
  3034. Alg_time_sig &prev = initial;
  3035. if (tsx > 0) { // use last time signature
  3036. prev = time_sig[time_sig.length() - 1];
  3037. }
  3038. bpm = prev.num * 4 / prev.den;
  3039. m = m + (beat - prev.beat) / bpm;
  3040. *measure = (long) m;
  3041. *m_beat = (m - *measure) * bpm;
  3042. *num = prev.num;
  3043. *den = prev.den;
  3044. }
  3045. /*
  3046. void Alg_seq::set_events(Alg_event_ptr *events, long len, long max)
  3047. {
  3048. convert_to_seconds(); // because notes are in seconds
  3049. notes.set_events(events, len, max);
  3050. }
  3051. */
  3052. void Alg_iterator::begin_seq(Alg_seq_ptr s, void *cookie, double offset)
  3053. {
  3054. // keep an array of indexes into tracks
  3055. // printf("new pending\n");
  3056. int i;
  3057. for (i = 0; i < s->track_list.length(); i++) {
  3058. if (s->track_list[i].length() > 0) {
  3059. insert(&(s->track_list[i]), 0, true, cookie, offset);
  3060. }
  3061. }
  3062. }
  3063. Alg_event_ptr Alg_iterator::next(bool *note_on, void **cookie_ptr,
  3064. double *offset_ptr, double end_time)
  3065. // return the next event in time from any track
  3066. {
  3067. bool on;
  3068. double when;
  3069. if (!remove_next(events_ptr, index, on, cookie, offset, when)) {
  3070. return NULL;
  3071. }
  3072. if (note_on) *note_on = on;
  3073. Alg_event_ptr event = (*events_ptr)[index];
  3074. if (on) {
  3075. if (note_off_flag && event->is_note() &&
  3076. (end_time == 0 ||
  3077. (*events_ptr)[index]->get_end_time() + offset < end_time)) {
  3078. // this was a note-on, so insert pending note-off
  3079. insert(events_ptr, index, false, cookie, offset);
  3080. }
  3081. // for both note-ons and updates, insert next event (at index + 1)
  3082. // DO NOT INCREMENT index: it must be preserved for request_note_off()
  3083. if (index + 1 < events_ptr->length() &&
  3084. (end_time == 0 || // zero means ignore end time
  3085. // stop iterating when end time is reached
  3086. (*events_ptr)[index + 1]->time + offset < end_time)) {
  3087. insert(events_ptr, index + 1, true, cookie, offset);
  3088. }
  3089. }
  3090. if (cookie_ptr) *cookie_ptr = cookie;
  3091. if (offset_ptr) *offset_ptr = offset;
  3092. return event;
  3093. }
  3094. void Alg_iterator::request_note_off()
  3095. {
  3096. assert(index >= 0 && index < events_ptr->length());
  3097. insert(events_ptr, index, false, cookie, offset);
  3098. }
  3099. void Alg_iterator::end()
  3100. {
  3101. }
  3102. void Alg_seq::merge_tracks()
  3103. {
  3104. long sum = 0;
  3105. long i;
  3106. for (i = 0; i < track_list.length(); i++) {
  3107. sum = sum + track(i)->length();
  3108. }
  3109. // preallocate array for efficiency:
  3110. Alg_event_ptr *notes = new Alg_event_ptr[sum];
  3111. Alg_iterator iterator(this, false);
  3112. iterator.begin();
  3113. long notes_index = 0;
  3114. Alg_event_ptr event;
  3115. while ((event = iterator.next())) {
  3116. notes[notes_index++] = event;
  3117. }
  3118. track_list.reset(); // don't need them any more
  3119. add_track(0);
  3120. track(0)->set_events(notes, sum, sum);
  3121. iterator.end();
  3122. }
  3123. void Alg_seq::set_in_use(bool flag)
  3124. {
  3125. Alg_track::set_in_use(flag);
  3126. track_list.set_in_use(flag);
  3127. }
  3128. // sr_letter_to_type = {"i": 'Integer', "r": 'Real', "s": 'String',
  3129. // "l": 'Logical', "a": 'Symbol'}