allegro.h 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125
  1. // Portsmf (also known as Allegro):
  2. // music representation system, with
  3. // extensible in-memory sequence structure
  4. // upward compatible with MIDI
  5. // implementations in C++ and Serpent
  6. // external, text-based representation
  7. // compatible with Aura
  8. //
  9. // SERIALBUFFER CLASS
  10. //
  11. // The Serial_buffer class is defined to support serialization and
  12. // unserialization. A Serial_buffer is just a block of memory with
  13. // a length and a read/write pointer. When writing, it can expand.
  14. //
  15. // SERIALIZATION
  16. //
  17. // The Alg_track class has static members:
  18. // ser_buf -- a Serial_buffer
  19. // When objects are serialized, they are first written to
  20. // ser_buf, which is expanded whenever necessary. Then, when
  21. // the length is known, new memory is allocated and the data
  22. // is copied to a correctly-sized buffer and returned to caller.
  23. // The "external" (callable from outside the library)
  24. // serialization functions are:
  25. // Alg_track::serialize()
  26. // Alg_seq::serialize()
  27. // The "internal" serialization functions to be called from within
  28. // the library are:
  29. // Alg_track::serialize_track(bool text)
  30. // Alg_seq::serialize_seq(bool text)
  31. // Alg_track::serialize_parameter(
  32. // Alg_parameter *parm, bool text)
  33. // These internal serialize functions append data to ser_buf The text
  34. // flag says to write an ascii representation as opposed to binary.
  35. //
  36. // UNSERIALIZATION:
  37. //
  38. // The Alg_track class has a static member:
  39. // unserialize(char *buffer, long len)
  40. // that will unserialize anything -- an Alg_track or an Alg_seq.
  41. // No other function should be called from outside the library.
  42. // Internal unserialize functions are:
  43. // Alg_seq::unserialize_seq()
  44. // Alg_track::unserialize_track()
  45. // Alg_track::unserialize_parameter(Alg_parameter_ptr parm_ptr)
  46. // Just as serialization uses ser_buf for output, unserialization uses
  47. // unser_buf for reading. unser_buf is another static member of Alg_track.
  48. #ifndef ALLEGRO_H
  49. #define ALLEGRO_H
  50. #include <assert.h>
  51. #include <cstring>
  52. #include <istream>
  53. #include <ostream>
  54. #define ALG_EPS 0.000001 // epsilon
  55. #define ALG_DEFAULT_BPM 100.0 // default tempo
  56. // are d1 and d2 within epsilon of each other?
  57. bool within(double d1, double d2, double epsilon);
  58. char *heapify(const char *s); // put a string on the heap
  59. // Alg_attribute is an atom in the symbol table
  60. // with the special addition that the last
  61. // character is prefixed to the string; thus,
  62. // the attribute 'tempor' (a real) is stored
  63. // as 'rtempor'. To get the string name, just
  64. // use attribute+1.
  65. typedef const char *Alg_attribute;
  66. #define alg_attr_name(a) ((a) + 1)
  67. #define alg_attr_type(a) (*(a))
  68. // Alg_atoms is a symbol table of Alg_attributes and other
  69. // unique strings
  70. class Alg_atoms {
  71. public:
  72. Alg_atoms() {
  73. maxlen = len = 0;
  74. atoms = nullptr;
  75. }
  76. // Note: the code is possibly more correct and faster without the
  77. // following destructor, which will only run after the program takes
  78. // a normal exit. Cleaning up after the program exit slows down the exit,
  79. // and will cause problems if any other destructor tries to reference an
  80. // Alg_atom (which will now be freed). The advantage of this code is
  81. // that Alg_atoms will not be reported as memory leaks by automation
  82. // that doesn't know better. -RBD
  83. virtual ~Alg_atoms() {
  84. for (int i = 0; i < len; i++) {
  85. delete atoms[i];
  86. }
  87. if (atoms) delete [] atoms;
  88. }
  89. // insert/lookup an atttribute
  90. Alg_attribute insert_attribute(Alg_attribute attr);
  91. // insert/lookup attribute by name (without prefixed type)
  92. Alg_attribute insert_string(const char *name);
  93. private:
  94. long maxlen;
  95. long len;
  96. Alg_attribute *atoms;
  97. // insert an Attriubute not in table after moving attr to heap
  98. Alg_attribute insert_new(const char *name, char attr_type);
  99. void expand(); // make more space
  100. };
  101. extern Alg_atoms symbol_table;
  102. // an attribute/value pair. Since Alg_attribute names imply type,
  103. // we try to keep attributes and values packaged together as
  104. // Alg_parameter class
  105. typedef class Alg_parameter {
  106. public:
  107. // This constructor guarantees that an Alg_parameter can be
  108. // deleted safely without further initialization. It does not
  109. // do anything useful, so it is expected that the creator will
  110. // set attr and store a value in the appropriate union field.
  111. Alg_attribute attr;
  112. union {
  113. double r;// real
  114. const char *s; // string
  115. long i; // integer
  116. bool l; // logical
  117. const char *a; // symbol (atom)
  118. }; // anonymous union
  119. Alg_parameter() { attr = "i"; }
  120. ~Alg_parameter();
  121. void copy(Alg_parameter *); // copy from another parameter
  122. const char attr_type() { return alg_attr_type(attr); }
  123. const char *attr_name() { return alg_attr_name(attr); }
  124. void set_attr(Alg_attribute a) { attr = a; }
  125. void show();
  126. } *Alg_parameter_ptr;
  127. // a list of attribute/value pairs
  128. typedef class Alg_parameters {
  129. public:
  130. class Alg_parameters *next;
  131. Alg_parameter parm;
  132. Alg_parameters(Alg_parameters *list) {
  133. next = list;
  134. }
  135. //~Alg_parameters() { }
  136. // each of these routines takes address of pointer to the list
  137. // insertion is performed without checking whether or not a
  138. // parameter already exists with this attribute. See find() and
  139. // remove_key() to assist in checking for and removing existing
  140. // parameters.
  141. // Note also that these insert_* methods convert name to an
  142. // attribute. If you have already done the symbol table lookup/insert
  143. // you can do these operations faster (in which case we should add
  144. // another set of functions that take attributes as arguments.)
  145. static void insert_real(Alg_parameters **list, const char *name, double r);
  146. // insert string will copy string to heap
  147. static void insert_string(Alg_parameters **list, const char *name,
  148. const char *s);
  149. static void insert_integer(Alg_parameters **list, const char *name, long i);
  150. static void insert_logical(Alg_parameters **list, const char *name, bool l);
  151. static void insert_atom(Alg_parameters **list, const char *name,
  152. const char *s);
  153. static Alg_parameters *remove_key(Alg_parameters **list, const char *name);
  154. // find an attribute/value pair
  155. Alg_parameter_ptr find(Alg_attribute attr);
  156. } *Alg_parameters_ptr;
  157. // these are type codes associated with certain attributes
  158. // see Alg_track::find() where these are bit positions in event_type_mask
  159. #define ALG_NOTE 0 // This is a note, not an update
  160. #define ALG_GATE 1 // "gate"
  161. #define ALG_BEND 2 // "bend"
  162. #define ALG_CONTROL 3 // "control"
  163. #define ALG_PROGRAM 4 // "program"
  164. #define ALG_PRESSURE 5 // "pressure"
  165. #define ALG_KEYSIG 6 // "keysig"
  166. #define ALG_TIMESIG_NUM 7 // "timesig_num"
  167. #define ALG_TIMESIG_DEN 8 // "timesig_den"
  168. #define ALG_OTHER 9 // any other value
  169. // abstract superclass of Alg_note and Alg_update:
  170. typedef class Alg_event {
  171. protected:
  172. bool selected;
  173. char type; // 'e' event, 'n' note, 'u' update
  174. long key; // note identifier
  175. static const char* description; // static buffer for debugging (in Alg_event)
  176. public:
  177. double time;
  178. long chan;
  179. virtual void show() = 0;
  180. // Note: there is no Alg_event() because Alg_event is an abstract class.
  181. bool is_note() { return (type == 'n'); } // tell whether an Alg_event is a note
  182. bool is_update() { return (type == 'u'); } // tell whether an Alg_event is a parameter update
  183. char get_type() { return type; } // return 'n' for note, 'u' for update
  184. int get_type_code(); // 1 = volume change, 2 = pitch bend,
  185. // 3 = control change, 4 = program change,
  186. // 5 = pressure change, 6 = key signature,
  187. // 7 = time sig numerator, 8 = time sig denominator
  188. bool get_selected() { return selected; }
  189. void set_selected(bool b) { selected = b; }
  190. // Note: notes are identified by a (channel, identifier) pair.
  191. // For midi, the identifier is the key number (pitch). The identifier
  192. // does not have to represent pitch; it's main purpose is to identify
  193. // notes so that they can be named by subsequent update events.
  194. long get_identifier() { return key; } // get MIDI key or note identifier of note or update
  195. void set_identifier(long i) { key = i; } // set the identifier
  196. // In all of these set_ methods, strings are owned by the caller and
  197. // copied as necessary by the callee. For notes, an attribute/value
  198. // pair is added to the parameters list. For updates, the single
  199. // attribute/value parameter pair is overwritten. In all cases, the
  200. // attribute (first argument) must agree in type with the second arg.
  201. // The last letter of the attribute implies the type (see below).
  202. void set_parameter(Alg_parameter_ptr new_parameter);
  203. void set_string_value(const char *attr, const char *value);
  204. void set_real_value(const char *attr, double value);
  205. void set_logical_value(const char *attr, bool value);
  206. void set_integer_value(const char *attr, long value);
  207. void set_atom_value(const char *attr, const char *atom);
  208. // Some note methods. These fail (via assert()) if this is not a note:
  209. //
  210. float get_pitch();// get pitch in steps -- use this even for MIDI
  211. float get_loud(); // get loudness (MIDI velocity)
  212. // times are in seconds or beats, depending upon the units_are_seconds
  213. // flag in the containing sequence
  214. double get_start_time(); // get start time in seconds or beats
  215. double get_end_time(); // get end time in seconds or beats
  216. double get_duration(); // get duration in seconds or beats
  217. void set_pitch(float);
  218. void set_loud(float);
  219. void set_duration(double);
  220. // Notes have lists of attribute values. Attributes are converted
  221. // to/from strings in this API to avoid explicit use of Alg_attribute
  222. // types. Attribute names end with a type designation: 's', 'r', 'l',
  223. // 'i', or 'a'.
  224. //
  225. bool has_attribute(const char *attr); // test if note has attribute/value pair
  226. char get_attribute_type(const char *attr); // get the associated type:
  227. // 's' = string,
  228. // 'r' = real (double), 'l' = logical (bool), 'i' = integer (long),
  229. // 'a' = atom (char *), a unique string stored in Alg_seq
  230. // get the string value
  231. const char *get_string_value(const char *attr, const char *value = nullptr);
  232. // get the real value
  233. double get_real_value(const char *attr, double value = 0.0);
  234. // get the logical value
  235. bool get_logical_value(const char *attr, bool value = false);
  236. // get the integer value
  237. long get_integer_value(const char *attr, long value = 0);
  238. // get the atom value
  239. const char *get_atom_value(const char *attr, const char *value = nullptr);
  240. void delete_attribute(const char *attr); // delete an attribute/value pair
  241. // (ignore if no matching attribute/value pair exists)
  242. // Some attribute/value methods. These fail if this is not an update.
  243. // Attributes are converted to/from strings to avoid explicit use
  244. // of Alg_attribute types.
  245. //
  246. const char *get_attribute(); // get the update's attribute (string)
  247. char get_update_type(); // get the update's type: 's' = string,
  248. // 'r' = real (double), 'l' = logical (bool), 'i' = integer (long),
  249. // 'a' = atom (char *), a unique string stored in Alg_seq
  250. const char *get_string_value(); // get the update's string value
  251. // Notes: Caller does not own the return value. Do not modify.
  252. // Do not use after underlying Alg_seq is modified.
  253. double get_real_value(); // get the update's real value
  254. bool get_logical_value(); // get the update's logical value
  255. long get_integer_value(); // get the update's integer value
  256. const char *get_atom_value(); // get the update's atom value
  257. // Notes: Caller does not own the return value. Do not modify.
  258. // The return value's lifetime is forever.
  259. // Auxiliary function to aid in editing tracks
  260. // Returns true if the event overlaps the given region
  261. bool overlap(double t, double len, bool all);
  262. const char *GetDescription(); // computes a text description of this event
  263. // the result is in a static buffer, not thread-safe, just for debugging.
  264. Alg_event() { selected = false; }
  265. virtual ~Alg_event() {}
  266. } *Alg_event_ptr;
  267. typedef class Alg_note : public Alg_event {
  268. public:
  269. virtual ~Alg_note();
  270. Alg_note(Alg_note *); // copy constructor
  271. float pitch; // pitch in semitones (69 = A440)
  272. float loud; // dynamic corresponding to MIDI velocity
  273. double dur; // duration in seconds (normally to release point)
  274. Alg_parameters_ptr parameters; // attribute/value pair list
  275. Alg_note() { type = 'n'; parameters = nullptr; }
  276. void show();
  277. } *Alg_note_ptr;
  278. typedef class Alg_update : public Alg_event {
  279. public:
  280. virtual ~Alg_update() {};
  281. Alg_update(Alg_update *); // copy constructor
  282. Alg_parameter parameter; // an update contains one attr/value pair
  283. Alg_update() { type = 'u'; }
  284. void show();
  285. } *Alg_update_ptr;
  286. // a sequence of Alg_event objects
  287. typedef class Alg_events {
  288. private:
  289. long maxlen;
  290. void expand();
  291. protected:
  292. long len;
  293. Alg_event_ptr *events; // events is array of pointers
  294. public:
  295. // sometimes, it is nice to have the time of the last note-off.
  296. // In the current implementation,
  297. // this field is set by append to indicate the time of the
  298. // last note-off in the current unit, so it should be correct after
  299. // creating a new track and adding notes to it. It is *not*
  300. // updated after uninsert(), so use it with care.
  301. double last_note_off;
  302. // initially false, in_use can be used to mark "do not delete". If an
  303. // Alg_events instance is deleted while "in_use", an assertion will fail.
  304. bool in_use;
  305. virtual int length() { return len; }
  306. Alg_event_ptr &operator[](int i) {
  307. assert(i >= 0 && i < len);
  308. return events[i];
  309. }
  310. Alg_events() {
  311. maxlen = len = 0;
  312. events = nullptr;
  313. last_note_off = 0;
  314. in_use = false;
  315. }
  316. // destructor deletes the events array, but not the
  317. // events themselves
  318. virtual ~Alg_events();
  319. void set_events(Alg_event_ptr *e, long l, long m) {
  320. if (events) delete [] events;
  321. events = e; len = l; maxlen = m; }
  322. // for use by Alg_track and Alg_seq
  323. void insert(Alg_event_ptr event);
  324. void append(Alg_event_ptr event);
  325. Alg_event_ptr uninsert(long index);
  326. } *Alg_events_ptr;
  327. class Alg_track;
  328. typedef class Alg_event_list : public Alg_events {
  329. protected:
  330. char type; // 'e' Alg_event_list, 't' Alg_track, 's' Alg_seq
  331. static const char *last_error_message;
  332. Alg_track *events_owner; // if this is an Alg_event_list,
  333. // the events are owned by an Alg_track or an Alg_seq
  334. static int sequences; // to keep track of sequence numbers
  335. int sequence_number; // this sequence number is incremented
  336. // whenever an edit is performed on an Alg_track or Alg_seq.
  337. // When an Alg_event_list is created to contain pointers to
  338. // a subset of an Alg_track or Alg_seq (the events_owner),
  339. // the Alg_event_list gets a copy of the events_owner's
  340. // sequence_number. If the events_owner is edited, the pointers
  341. // in this Alg_event_list will become invalid. This is detected
  342. // (for debugging) as differing sequence_numbers.
  343. // every event list, track, and seq has a duration.
  344. // Usually the duration is set when the list is constructed, e.g.
  345. // when you extract from 10 to 15 seconds, the duration is 5 secs.
  346. // The duration does not tell you when is the last note-off.
  347. // duration is recorded in both beats and seconds:
  348. double beat_dur;
  349. double real_dur;
  350. public:
  351. // the client should not create one of these, but these are
  352. // returned from various track and seq operations. An
  353. // Alg_event_list "knows" the Alg_track or Alg_seq that "owns"
  354. // the events. All events in an Alg_event_list must belong
  355. // to the same Alg_track or Alg_seq structure.
  356. // When applied to an Alg_seq, events are enumerated track
  357. // by track with increasing indices. This operation is not
  358. // particularly fast on an Alg_seq.
  359. virtual Alg_event_ptr const &operator[](int i);
  360. Alg_event_list() { sequence_number = 0;
  361. beat_dur = 0.0; real_dur = 0.0; events_owner = nullptr; type = 'e'; }
  362. Alg_event_list(Alg_track *owner);
  363. char get_type() { return type; }
  364. Alg_track *get_owner() { return events_owner; }
  365. // The destructor does not free events because they are owned
  366. // by a track or seq structure.
  367. virtual ~Alg_event_list();
  368. // Returns the duration of the sequence in beats or seconds
  369. double get_beat_dur() { return beat_dur; }
  370. void set_beat_dur(double d) { beat_dur = d; }
  371. double get_real_dur() { return real_dur; }
  372. void set_real_dur(double d) { real_dur = d; }
  373. // Events are stored in time order, so when you change the time of
  374. // an event, you must adjust the position. When you call set_start_time
  375. // on an Alg_event_list, the Alg_event_list is not modified, but the
  376. // Alg_track that "owns" the event is modified. If the owner is an
  377. // Alg_seq, this may require searching the seq for the track containing
  378. // the event. This will mean a logN search of every track in the seq
  379. // (but if this turns out to be a problem, we can store each event's
  380. // track owner in the Alg_event_list.)
  381. virtual void set_start_time(Alg_event *event, double);
  382. // get text description of run-time errors detected, clear error
  383. const char *get_last_error_message() { return last_error_message; }
  384. // Implementation hint: keep a sequence number on each Alg_track that is
  385. // incremented anytime there is a structural change. (This behavior is
  386. // inherited by Alg_seq as well.) Copy the sequence number to any
  387. // Alg_event_list object when it is created. Whenever you access an
  388. // Alg_event_list, using operator[], assert that the Alg_event_list sequence
  389. // number matches the Alg_seq sequence number. This will guarantee that you
  390. // do not try to retain pointers to events beyond the point where the events
  391. // may no longer exist.
  392. } *Alg_event_list_ptr, &Alg_event_list_ref;
  393. // Alg_beat is used to contruct a tempo map
  394. typedef class Alg_beat {
  395. public:
  396. Alg_beat(double t, double b) {
  397. time = t; beat = b; }
  398. Alg_beat() {};
  399. double time;
  400. double beat;
  401. } *Alg_beat_ptr;
  402. // Alg_beats is a list of Alg_beat objects used in Alg_seq
  403. typedef class Alg_beats {
  404. private:
  405. long maxlen;
  406. void expand();
  407. public:
  408. long len;
  409. Alg_beat_ptr beats;
  410. Alg_beat &operator[](int i) {
  411. assert(i >= 0 && i < len);
  412. return beats[i];
  413. }
  414. Alg_beats() {
  415. maxlen = len = 0;
  416. beats = nullptr;
  417. expand();
  418. beats[0].time = 0;
  419. beats[0].beat = 0;
  420. len = 1;
  421. }
  422. ~Alg_beats() {
  423. if (beats) delete[] beats;
  424. }
  425. void insert(long i, Alg_beat_ptr beat);
  426. } *Alg_beats_ptr;
  427. typedef class Alg_time_map {
  428. private:
  429. int refcount;
  430. public:
  431. Alg_beats beats; // array of Alg_beat
  432. double last_tempo;
  433. bool last_tempo_flag;
  434. Alg_time_map() {
  435. last_tempo = ALG_DEFAULT_BPM / 60.0; // note: this value ignored until
  436. // last_tempo_flag is set; nevertheless, the default
  437. // tempo is 100.
  438. last_tempo_flag = true;
  439. refcount = 0;
  440. }
  441. Alg_time_map(Alg_time_map *map); // copy constructor
  442. long length() { return beats.len; }
  443. void show();
  444. long locate_time(double time);
  445. long locate_beat(double beat);
  446. double beat_to_time(double beat);
  447. double time_to_beat(double time);
  448. // Time map manipulations: it is prefered to call the corresponding
  449. // methods in Alg_seq. If you manipulate an Alg_time_map directly,
  450. // you should take care to convert all tracks that use the time map
  451. // to beats or seconds as appropriate: Normally if you insert a beat
  452. // you want tracks to be in time units and if you insert a tempo change
  453. // you want tracks to be in beat units.
  454. void insert_beat(double time, double beat); // add a point to the map
  455. bool insert_tempo(double tempo, double beat); // insert a tempo change
  456. // get the tempo starting at beat
  457. double get_tempo(double beat);
  458. // set the tempo over a region
  459. bool set_tempo(double tempo, double start_beat, double end_beat);
  460. bool stretch_region(double b0, double b1, double dur);
  461. void cut(double start, double len, bool units_are_seconds);
  462. void trim(double start, double end, bool units_are_seconds);
  463. void paste(double start, Alg_track *tr);
  464. // insert a span of time. If start is at a tempo change, then
  465. // the span of time runs at the changed tempo
  466. void insert_time(double start, double len);
  467. // insert a span of beats. If start is at a tempo change, the
  468. // tempo change takes effect before the inserted beats
  469. void insert_beats(double start, double len);
  470. void dereference() {
  471. if (--refcount <= 0) delete this;
  472. }
  473. void reference() {
  474. refcount++;
  475. }
  476. } *Alg_time_map_ptr;
  477. // Serial_buffer is an abstract class with common elements of
  478. // Serial_read_buffer and Serial_write_buffer
  479. class Serial_buffer {
  480. protected:
  481. char *buffer;
  482. char *ptr;
  483. long len;
  484. public:
  485. Serial_buffer() {
  486. buffer = nullptr;
  487. ptr = nullptr;
  488. len = 0;
  489. }
  490. virtual ~Serial_buffer() { }
  491. long get_posn() { return (long) (ptr - buffer); }
  492. long get_len() { return len; }
  493. };
  494. typedef class Serial_read_buffer : public Serial_buffer {
  495. public:
  496. // note that a Serial_read_buffer is initialized for reading by
  497. // setting buffer, but it is not the Serial_read_buffer's responsibility
  498. // to delete the buffer (owner might want to reuse it), so the destructor
  499. // does nothing.
  500. virtual ~Serial_read_buffer() { }
  501. #if defined(_WIN32)
  502. //#pragma warning(disable: 546) // cast to int is OK, we only want low 7 bits
  503. //#pragma warning(disable: 4311) // type cast pointer to long warning
  504. #endif
  505. void get_pad() { while ((intptr_t) ptr & 7) ptr++; }
  506. #if defined(_WIN32)
  507. //#pragma warning(default: 4311 546)
  508. #endif
  509. // Prepare to read n bytes from buf. The caller must manage buf: it is
  510. // valid until reading is finished, and it is caller's responsibility
  511. // to free buf when it is no longer needed.
  512. void init_for_read(void *buf, long n) {
  513. buffer = (char *) buf;
  514. ptr = (char *) buf;
  515. len = n;
  516. }
  517. char get_char() { return *ptr++; }
  518. void unget_chars(int n) { ptr -= n; } // undo n get_char() calls
  519. long get_int32() { long i = *((long *) ptr); ptr += 4; return i; }
  520. float get_float() { float f = *((float *) ptr); ptr += 4; return f; }
  521. double get_double() { double d = *((double *) ptr); ptr += sizeof(double);
  522. return d; }
  523. const char *get_string() { char *s = ptr; char *fence = buffer + len;
  524. assert(ptr < fence); (void)fence; // unused variable
  525. while (*ptr++) assert(ptr < fence);
  526. get_pad();
  527. return s; }
  528. void check_input_buffer(long needed) {
  529. assert(get_posn() + needed <= len); }
  530. } *Serial_read_buffer_ptr;
  531. typedef class Serial_write_buffer: public Serial_buffer {
  532. public:
  533. // Note: allegro.cpp declares one static instance of Serial_buffer to
  534. // reduce large memory (re)allocations when serializing tracks for UNDO.
  535. // This destructor will only run when the program exits, which will only
  536. // add overhead to the exit process, but it will eliminate an incorrect
  537. // report of memory leakage from automation that doesn't know better. -RBD
  538. virtual ~Serial_write_buffer() {
  539. if (buffer) delete [] buffer;
  540. }
  541. void init_for_write() { ptr = buffer; }
  542. // store_long writes a long at a given offset
  543. void store_long(long offset, long value) {
  544. assert(offset <= get_posn() - 4);
  545. long *loc = (long *) (buffer + offset);
  546. *loc = value;
  547. }
  548. void check_buffer(long needed);
  549. void set_string(const char *s) {
  550. char *fence = buffer + len;
  551. assert(ptr < fence); (void)fence; // unused variable
  552. // two brackets surpress a g++ warning, because this is an
  553. // assignment operator inside a test.
  554. while ((*ptr++ = *s++)) assert(ptr < fence);
  555. // 4311 is type cast pointer to long warning
  556. // 4312 is type cast long to pointer warning
  557. #if defined(_WIN32)
  558. //#pragma warning(disable: 4311 4312)
  559. #endif
  560. assert((char *)(((long long) (ptr + 7)) & ~7) <= fence);
  561. #if defined(_WIN32)
  562. //#pragma warning(default: 4311 4312)
  563. #endif
  564. pad(); }
  565. void set_int32(long v) { *((long *) ptr) = v; ptr += 4; }
  566. void set_double(double v) { *((double *) ptr) = v; ptr += 8; }
  567. void set_float(float v) { *((float *) ptr) = v; ptr += 4; }
  568. void set_char(char v) { *ptr++ = v; }
  569. #if defined(_WIN32)
  570. //#pragma warning(disable: 546) // cast to int is OK, we only want low 7 bits
  571. //#pragma warning(disable: 4311) // type cast pointer to long warning
  572. #endif
  573. void pad() { while ((intptr_t) ptr & 7) set_char(0); }
  574. #if defined(_WIN32)
  575. //#pragma warning(default: 4311 546)
  576. #endif
  577. void *to_heap(long *len) {
  578. *len = get_posn();
  579. char *newbuf = new char[*len];
  580. memcpy(newbuf, buffer, *len);
  581. return newbuf;
  582. }
  583. } *Serial_write_buffer_ptr;
  584. typedef class Alg_seq *Alg_seq_ptr;
  585. typedef class Alg_track : public Alg_event_list {
  586. protected:
  587. Alg_time_map *time_map;
  588. bool units_are_seconds;
  589. char *get_string(char **p, long *b);
  590. long get_int32(char **p, long *b);
  591. double get_double(char **p, long *b);
  592. float get_float(char **p, long *b);
  593. static Serial_read_buffer ser_read_buf;
  594. static Serial_write_buffer ser_write_buf;
  595. void serialize_parameter(Alg_parameter *parm);
  596. // *buffer_ptr points to binary data, bytes_ptr points to how many
  597. // bytes have been used so far, len is length of binary data
  598. void unserialize_parameter(Alg_parameter_ptr parm_ptr);
  599. public:
  600. void serialize_track();
  601. void unserialize_track();
  602. virtual Alg_event_ptr const &operator[](int i) {
  603. assert(i >= 0 && i < len);
  604. return events[i];
  605. }
  606. Alg_track() { units_are_seconds = false; time_map = nullptr;
  607. set_time_map(nullptr); type = 't'; }
  608. // initialize empty track with a time map
  609. Alg_track(Alg_time_map *map, bool seconds);
  610. Alg_event_ptr copy_event(Alg_event_ptr event); // make a complete copy
  611. Alg_track(Alg_track &track); // copy constructor, does not copy time_map
  612. // copy constructor: event_list is copied, map is installed and referenced
  613. Alg_track(Alg_event_list_ref event_list, Alg_time_map_ptr map,
  614. bool units_are_seconds);
  615. virtual ~Alg_track() { // note: do not call set_time_map(NULL)!
  616. if (time_map) time_map->dereference();
  617. time_map = nullptr; }
  618. // Returns a buffer containing a serialization of the
  619. // file. It will be an ASCII representation unless text is true.
  620. // *buffer gets a newly allocated buffer pointer. The caller must free it.
  621. // *len gets the length of the serialized track
  622. virtual void serialize(void **buffer, long *bytes);
  623. // Try to read from a memory buffer. Automatically guess
  624. // whether it's MIDI or text.
  625. static Alg_track *unserialize(void *buffer, long len);
  626. // If the track is really an Alg_seq and you need to access an
  627. // Alg_seq method, coerce to an Alg_seq with this function:
  628. Alg_seq_ptr to_alg_seq() {
  629. return (get_type() == 's' ? (Alg_seq_ptr) this : nullptr); }
  630. // Are we using beats or seconds?
  631. bool get_units_are_seconds() { return units_are_seconds; }
  632. // Change units
  633. virtual void convert_to_beats();
  634. virtual void convert_to_seconds();
  635. void set_dur(double dur);
  636. double get_dur() { return (units_are_seconds ? real_dur : beat_dur); }
  637. // Every Alg_track may have an associated time_map. If no map is
  638. // specified, or if you set_time_map(NULL), then the behavior
  639. // should be as if there is a constant tempo of 100 beats/minute
  640. // (this constant is determined by ALG_DEFAULT_BPM).
  641. // Recommendation: create a static global tempo map object. When
  642. // any operation that needs a tempo map gets NULL, use the global
  643. // tempo map. (Exception: any operation that would modify the
  644. // tempo map should raise an error -- you don't want to change the
  645. // default tempo map.)
  646. virtual void set_time_map(Alg_time_map *map);
  647. Alg_time_map *get_time_map() { return time_map; }
  648. // Methods to create events. The returned event is owned by the caller.
  649. // Use delete to get rid of it unless you call add() -- see below.
  650. //
  651. Alg_note *create_note(double time, int channel, int identifier,
  652. float pitch, float loudness, double duration);
  653. // Note: after create_update(), caller should use set_*_value() to
  654. // initialize the attribute/value pair:
  655. Alg_update *create_update(double time, int channel, int identifier);
  656. // Adds a new event - it is automatically inserted into the
  657. // correct order in the sequence based on its timestamp.
  658. // The ownership passes from the caller to this Alg_seq. The
  659. // event is not copied.
  660. virtual void add(Alg_event *event) { insert(event); }
  661. //
  662. // Editing regions
  663. //
  664. // Deletes the notes that start within the given region
  665. // and returns them in a new sequence. The start times
  666. // of the notes in the returned sequence are shifted
  667. // by -t. The notes after the region get shifted over
  668. // to fill the gap. In an Alg_seq, the tempo track is edited
  669. // in a similar way
  670. // and the cut tempo information is retained in the new seq.
  671. // ONLY NOTES THAT START WITHIN THE REGION ARE CUT unless
  672. // "all" is true in which case all notes that intersect
  673. // the region are copied. CUT NOTES
  674. // MAY EXTEND BEYOND THE DURATION OF THE RESULTING SEQ.
  675. // The return type is the same as this (may be Alg_seq).
  676. // All times including len are interpreted according to
  677. // units_are_seconds in the track.
  678. virtual Alg_track *cut(double t, double len, bool all);
  679. // Like cut() but doesn't remove the notes from the original
  680. // sequence. The Alg_events are copied, not shared. ONLY EVENTS
  681. // THAT START WITHIN THE REGION ARE COPIED unless "all" is true
  682. // in which case all notes that intersect the region are
  683. // copied. COPIED NOTES MAY
  684. // EXTEND BEYOND THE DURATION OF THE RESULTING SEQ.
  685. // The return type is the same as this (may be Alg_seq).
  686. virtual Alg_track *copy(double t, double len, bool all);
  687. // Inserts a sequence in the middle, shifting some notes
  688. // over by the duration of the seq, which is first converted
  689. // to the same units (seconds or beats) as this. (This makes
  690. // a differece because the pasted data may change the tempo,
  691. // and notes that overlap the borders will then experience
  692. // a tempo change.)
  693. // THE SEQ PARAMETER IS NOT MODIFIED, AND Alg_event's ARE
  694. // COPIED, NOT SHARED.
  695. // The type of seq must be Alg_seq if seq is an Alg_seq, or
  696. // Alg_track if seq is an Alg_track or an Alg_event_list.
  697. virtual void paste(double t, Alg_event_list *seq); // Shifts notes
  698. // Merges two sequences with a certain offset. The offset is
  699. // interpreted as either beats or seconds according to the
  700. // current units of this, and seq is converted to the same
  701. // units as this. Except for a possible conversion to beats
  702. // or seconds, the tempo track of seq (if any) is ignored.
  703. // (There is no way to merge tempo tracks.)
  704. // THE SEQ PARAMETER IS NOT MODIFIED, AND Alg_event's ARE
  705. // COPIED, NOT SHARED.
  706. // The type of seq must be Alg_seq if seq is an Alg_seq, or
  707. // Alg_track if seq is an Alg_track or an Alg_event_list.
  708. virtual void merge(double t, Alg_event_list_ptr seq);
  709. // Deletes and shifts notes to fill the gap. The tempo track
  710. // is also modified accordingly. ONLY EVENTS THAT START WITHIN
  711. // THE REGION ARE DELETED unless "all" is true, in which case
  712. // all notes that intersect the region are cleared.
  713. // NOTES THAT EXTEND FROM BEFORE THE
  714. // REGION INTO THE REGION RETAIN THEIR DURATION IN EITHER
  715. // BEATS OR SECONDS ACCORDING TO THE CURRENT UNITS OF this.
  716. virtual void clear(double t, double len, bool all);
  717. // Deletes notes but doesn't shift. If the "all" argument
  718. // is true, deletes all notes that intersect the range at all,
  719. // not just those that start within it. The tempo track is
  720. // not affected.
  721. virtual void silence(double t, double len, bool all);
  722. // Simply shifts notes past time t over by len, which is given
  723. // in either beats or seconds according to the units of this.
  724. // The resulting interveal (t, t+len) may in fact contain notes
  725. // that begin before t. The durations of notes are not changed.
  726. // If this is an Alg_seq, the tempo track is expanded at t also.
  727. virtual void insert_silence(double t, double len);
  728. //
  729. // Accessing for screen display
  730. //
  731. // A useful generic function to retrieve only certain
  732. // types of events. The masks should be bit-masks defined
  733. // somewhere else. Part of the mask allows us to search for
  734. // selected events. If this is an Alg_seq, search all tracks
  735. // (otherwise, call track[i].find())
  736. // If channel_mask == 0, accept ALL channels
  737. virtual Alg_event_list *find(double t, double len, bool all,
  738. long channel_mask, long event_type_mask);
  739. virtual void set_in_use(bool flag) { in_use = flag; }
  740. //
  741. // MIDI playback
  742. //
  743. // See Alg_iterator
  744. } *Alg_track_ptr, &Alg_track_ref;
  745. // Alg_time_sig represents a single time signature;
  746. // although not recommended, time_signatures may have arbitrary
  747. // floating point values, e.g. 4.5 beats per measure
  748. typedef class Alg_time_sig {
  749. public:
  750. double beat; // when does this take effect?
  751. double num; // what is the "numerator" (top number?)
  752. double den; // what is the "denominator" (bottom number?)
  753. Alg_time_sig(double b, double n, double d) {
  754. beat = b; num = n; den = d;
  755. }
  756. Alg_time_sig() {
  757. beat = 0; num = 0; den = 0;
  758. }
  759. void beat_to_measure(double beat, double *measure, double *m_beat,
  760. double *num, double *den);
  761. } *Alg_time_sig_ptr;
  762. // Alg_time_sigs is a dynamic array of time signatures
  763. //
  764. // The default (empty) time_sigs has 4/4 time at beat 0.
  765. // Each time_sig object in time_sigs represents the beginning
  766. // of a measure. If there is a beat missing, e.g. in the first
  767. // measure, you can represent this by inserting another
  768. // time_sig at the next measure beginning. Each time_sig implies
  769. // an infinite sequence of full measures until the next time_sig.
  770. // If you insert a time_sig and one already exist near the same
  771. // beat, the old one is replaced, thus re-barring every measure
  772. // until the next time_sig.
  773. class Alg_time_sigs {
  774. private:
  775. long maxlen;
  776. void expand(); // make more space
  777. long len;
  778. Alg_time_sig_ptr time_sigs;
  779. public:
  780. Alg_time_sigs() {
  781. maxlen = len = 0;
  782. time_sigs = nullptr;
  783. }
  784. Alg_time_sig &operator[](int i) { // fetch a time signature
  785. assert(i >= 0 && i < len);
  786. return time_sigs[i];
  787. }
  788. ~Alg_time_sigs() {
  789. if (time_sigs) delete[] time_sigs;
  790. }
  791. void show();
  792. long length() { return len; }
  793. int find_beat(double beat);
  794. // get the number of beats per measure starting at beat
  795. double get_bar_len(double beat);
  796. void insert(double beat, double num, double den, bool force = false);
  797. void cut(double start, double end, double dur); // remove from start to end
  798. void trim(double start, double end); // retain just start to end
  799. void paste(double start, Alg_seq *seq);
  800. void insert_beats(double beat, double len); // insert len beats at beat
  801. // find the nearest beat (see Alg_seq::nearest_beat) to beat
  802. double nearest_beat(double beat);
  803. };
  804. // a sequence of Alg_events objects
  805. typedef class Alg_tracks {
  806. private:
  807. long maxlen;
  808. void expand();
  809. void expand_to(int new_max);
  810. long len;
  811. public:
  812. Alg_track_ptr *tracks; // tracks is array of pointers
  813. Alg_track &operator[](int i) {
  814. assert(i >= 0 && i < len);
  815. return *tracks[i];
  816. }
  817. long length() { return len; }
  818. Alg_tracks() {
  819. maxlen = len = 0;
  820. tracks = nullptr;
  821. }
  822. ~Alg_tracks();
  823. // Append a track to tracks. This Alg_tracks becomes the owner of track.
  824. void append(Alg_track_ptr track);
  825. void add_track(int track_num, Alg_time_map_ptr time_map, bool seconds);
  826. void reset();
  827. void set_in_use(bool flag); // handy to set in_use flag on all tracks
  828. } *Alg_tracks_ptr;
  829. typedef enum {
  830. alg_no_error = 0, // no error reading Allegro or MIDI file
  831. alg_error_open = -800, // could not open Allegro or MIDI file
  832. alg_error_syntax // something found in the file that could not be parsed;
  833. // generally you should ignore syntax errors or look at the printed error
  834. // messages because there are some things in standard midi files that we do
  835. // not handle; (maybe we should only set alg_error_syntax when there is a
  836. // real problem with the file as opposed to when there is some warning
  837. // message for the user)
  838. } Alg_error;
  839. typedef struct Alg_pending_event {
  840. void *cookie; // client-provided sequence identifier
  841. Alg_events *events; // the array of events
  842. long index; // offset of this event
  843. bool note_on; // is this a note-on or a note-off (if applicable)?
  844. double offset; // time offset for events
  845. double time; // time for this event
  846. } *Alg_pending_event_ptr;
  847. typedef class Alg_iterator {
  848. private:
  849. long maxlen;
  850. void expand();
  851. void expand_to(int new_max);
  852. long len;
  853. Alg_seq_ptr seq;
  854. Alg_pending_event *pending_events;
  855. // the next four fields are mainly for request_note_off()
  856. Alg_events_ptr events_ptr; // remembers events containing current event
  857. long index; // remembers index of current event
  858. void *cookie; // remembers the cookie associated with next event
  859. double offset;
  860. void show();
  861. bool earlier(int i, int j);
  862. void insert(Alg_events_ptr events, long index, bool note_on,
  863. void *cookie, double offset);
  864. // returns the info on the next pending event in the priority queue
  865. bool remove_next(Alg_events_ptr &events, long &index, bool &note_on,
  866. void *&cookie, double &offset, double &time);
  867. public:
  868. bool note_off_flag; // remembers if we are iterating over note-off
  869. // events as well as note-on and update events
  870. long length() { return len; }
  871. Alg_iterator(Alg_seq_ptr s, bool note_off) {
  872. seq = s;
  873. note_off_flag = note_off;
  874. maxlen = len = 0;
  875. pending_events = nullptr;
  876. }
  877. // Normally, iteration is over the events in the one sequence used
  878. // to instatiate the iterator (see above), but with this method, you
  879. // can add more sequences to the iteration. Events are returned in
  880. // time order, so effectively sequence events are merged.
  881. // The optional offset is added to each event time of sequence s
  882. // before merging/sorting. You should call begin_seq() for each
  883. // sequence to be included in the iteration unless you call begin()
  884. // (see below).
  885. void begin_seq(Alg_seq_ptr s, void *cookie = nullptr, double offset = 0.0);
  886. ~Alg_iterator();
  887. // Prepare to enumerate events in order. If note_off_flag is true, then
  888. // iteration_next will merge note-off events into the sequence. If you
  889. // call begin(), you should not normally call begin_seq(). See above.
  890. void begin(void *cookie = nullptr) { begin_seq(seq, cookie); }
  891. // return next event (or NULL). If iteration_begin was called with
  892. // note_off_flag = true, and if note_on is not NULL, then *note_on
  893. // is set to true when the result value represents a note-on or update.
  894. // (With note_off_flag, each Alg_note event is returned twice, once
  895. // at the note-on time, with *note_on == true, and once at the note-off
  896. // time, with *note_on == false. If a cookie_ptr is passed, then the
  897. // cookie corresponding to the event is stored at that address
  898. // If end_time is 0, iterate through the entire sequence, but if
  899. // end_time is non_zero, stop iterating at the last event before end_time
  900. Alg_event_ptr next(bool *note_on = nullptr, void **cookie_ptr = nullptr,
  901. double *offset_ptr = nullptr, double end_time = 0);
  902. // Sometimes, the caller wants to receive note-off events for a subset
  903. // of the notes, typically the notes that are played and need to be
  904. // turned off. In this case, when a note is turned on, the client
  905. // should call request_note_off(). This will insert a note-off into
  906. // the queue for the most recent note returned by next().
  907. void request_note_off();
  908. void end(); // clean up after enumerating events
  909. } *Alg_iterator_ptr;
  910. // An Alg_seq is an array of Alg_events, each a sequence of Alg_event,
  911. // with a tempo map and a sequence of time signatures
  912. //
  913. typedef class Alg_seq : public Alg_track {
  914. protected:
  915. Alg_iterator_ptr pending; // iterator used internally by Alg_seq methods
  916. void serialize_seq();
  917. Alg_error error; // error code set by file readers
  918. // an internal function used for writing Allegro track names
  919. Alg_event_ptr write_track_name(std::ostream &file, int n,
  920. Alg_events &events);
  921. public:
  922. int channel_offset_per_track; // used to encode track_num into channel
  923. Alg_tracks track_list; // array of Alg_events
  924. Alg_time_sigs time_sig;
  925. int beat_x;
  926. void basic_initialization() {
  927. error = alg_no_error;
  928. units_are_seconds = true; type = 's';
  929. channel_offset_per_track = 0;
  930. add_track(0); // default is one empty track
  931. }
  932. Alg_seq() {
  933. basic_initialization();
  934. }
  935. // copy constructor -- if track is an Alg_seq, make a copy; if
  936. // track is just an Alg_track, the track becomes track 0
  937. Alg_seq(Alg_track_ref track) { seq_from_track(track); }
  938. Alg_seq(Alg_track_ptr track) { seq_from_track(*track); }
  939. void seq_from_track(Alg_track_ref tr);
  940. // create from file:
  941. Alg_seq(std::istream &file, bool smf, double *offset_ptr = nullptr);
  942. // create from filename
  943. Alg_seq(const char *filename, bool smf, double *offset_ptr = nullptr);
  944. virtual ~Alg_seq();
  945. int get_read_error() { return error; }
  946. void serialize(void **buffer, long *bytes);
  947. void copy_time_sigs_to(Alg_seq *dest); // a utility function
  948. void set_time_map(Alg_time_map *map);
  949. // encode sequence structure into contiguous, moveable memory block
  950. // address of newly allocated memory is assigned to *buffer, which must
  951. // be freed by caller; the length of data is assigned to *len
  952. void unserialize_seq();
  953. // write an ascii representation to file
  954. void write(std::ostream &file, bool in_secs, double offset = 0.0);
  955. // returns true on success
  956. bool write(const char *filename, double offset = 0.0);
  957. void smf_write(std::ostream &file);
  958. bool smf_write(const char *filename);
  959. // Returns the number of tracks
  960. int tracks();
  961. // create a track
  962. void add_track(int track_num) {
  963. track_list.add_track(track_num, get_time_map(), units_are_seconds);
  964. }
  965. // Return a particular track. This Alg_seq owns the track, so the
  966. // caller must not delete the result.
  967. Alg_track_ptr track(int);
  968. virtual Alg_event_ptr const &operator[](int i);
  969. virtual void convert_to_seconds();
  970. virtual void convert_to_beats();
  971. Alg_track_ptr cut_from_track(int track_num, double start, double dur,
  972. bool all);
  973. Alg_seq *cut(double t, double len, bool all);
  974. void insert_silence_in_track(int track_num, double t, double len);
  975. void insert_silence(double t, double len);
  976. Alg_track_ptr copy_track(int track_num, double t, double len, bool all);
  977. Alg_seq *copy(double start, double len, bool all);
  978. void paste(double start, Alg_seq *seq);
  979. virtual void clear(double t, double len, bool all);
  980. virtual void merge(double t, Alg_event_list_ptr seq);
  981. virtual void silence(double t, double len, bool all);
  982. void clear_track(int track_num, double start, double len, bool all);
  983. void silence_track(int track_num, double start, double len, bool all);
  984. Alg_event_list_ptr find_in_track(int track_num, double t, double len,
  985. bool all, long channel_mask,
  986. long event_type_mask);
  987. // find index of first score event after time
  988. long seek_time(double time, int track_num);
  989. bool insert_beat(double time, double beat);
  990. // return the time of the beat nearest to time, also returns beat
  991. // number through beat. This will correspond to an integer number
  992. // of beats from the nearest previous time signature or 0.0, but
  993. // since time signatures need not be on integer beat boundaries
  994. // the beat location may not be on an integer beat (beat locations
  995. // are measured from the beginning which is beat 0.
  996. double nearest_beat_time(double time, double *beat);
  997. // warning: insert_tempo may change representation from seconds to beats
  998. bool insert_tempo(double bpm, double beat);
  999. // change the duration from b0 to b1 (beats) to dur (seconds) by
  1000. // scaling the intervening tempos
  1001. bool stretch_region(double b0, double b1, double dur);
  1002. // add_event takes a pointer to an event on the heap. The event is not
  1003. // copied, and this Alg_seq becomes the owner and freer of the event.
  1004. void add_event(Alg_event_ptr event, int track_num);
  1005. void add(Alg_event_ptr event) { assert(false); } // call add_event instead
  1006. // get the tempo starting at beat
  1007. double get_tempo(double beat);
  1008. bool set_tempo(double bpm, double start_beat, double end_beat);
  1009. // get the bar length in beats starting at beat
  1010. double get_bar_len(double beat);
  1011. void set_time_sig(double beat, double num, double den);
  1012. void beat_to_measure(double beat, long *measure, double *m_beat,
  1013. double *num, double *den);
  1014. // void set_events(Alg_event_ptr *events, long len, long max);
  1015. void merge_tracks(); // move all track data into one track
  1016. void set_in_use(bool flag); // set in_use flag on all tracks
  1017. } *Alg_seq_ptr, &Alg_seq_ref;
  1018. // see Alg_seq::Alg_seq() constructors that read from files
  1019. // the following are for internal library implementation and are
  1020. // moved to *_internal.h header files.
  1021. //Alg_seq_ptr alg_read(std::istream &file, Alg_seq_ptr new_seq);
  1022. //Alg_seq_ptr alg_smf_read(std::istream &file, Alg_seq_ptr new_seq);
  1023. #endif