allegro.h 38 KB

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