1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
|
// Allegro: music representation system, with
// extensible in-memory sequence structure
// upward compatible with MIDI
// implementations in C++ and Serpent
// external, text-based representation
// compatible with Aura
#ifndef __ALLEGRO__
#define __ALLEGRO__
#include <assert.h>
#ifdef NEED_BOOL
#define bool unsigned char
#define true 1
#define false 0
#endif
// are d1 and d2 within epsilon of each other?
bool within(double d1, double d2, double epsilon);
// abstract superclass of Allegro_note and Allegro_update:
typedef class Allegro_event {
public:
char type; // 'e' event, 'n' note, 'u' update
double time;
long chan;
virtual ~Allegro_event() {}
} *Allegro_event_ptr;
// a sequence of Event objects
typedef class Events {
private:
long max;
void expand();
public:
long len;
Allegro_event_ptr *events; // events is array of pointers
Allegro_event_ptr &operator[](int i) {
/* assert(i >= 0 && i < len); dmazzoni */
if (i<0) i=0;
if (i>=len) i=len-1;
return events[i];
}
Events() {
max = 0;
len = 0;
events = NULL;
}
~Events();
void insert(Allegro_event_ptr event);
void append(Allegro_event_ptr event);
void set_events(Allegro_event_ptr *e, long l, long m) {
if (events) delete [] events;
events = e; len = l; max = m; }
} *Events_ptr;
// Attribute is an atom in the symbol table
// with the special addition that the last
// character is prefixed to the string; thus,
// the attribute 'tempor' (a real) is stored
// as 'rtempor'. To get the string name, just
// use attribute+1.
typedef char *Attribute;
// Atoms is a symbol table of Attributes
class Atoms {
public:
Atoms() {
max = len = 0;
atoms = NULL;
}
// insert/lookup an atttribute
Attribute insert_attribute(Attribute attr);
// insert/lookup attribute by name (without prefixed type)
Attribute insert_string(const char *name);
private:
long max;
long len;
char **atoms;
// insert an Attriubute not in table after moving attr to heap
Attribute insert_new(const char *name, char attr_type);
void expand(); // make more space
};
extern Atoms symbol_table;
// an attribute/value pair. Since Attribute names imply type,
// we try to keep attributes and values packaged together as
// Parameter class
typedef class Parameter {
private:
Attribute attr;
public:
virtual ~Parameter();
union {
double r;// real
char *s; // string
long i; // integer
bool l; // logical
char *a; // symbol (atom)
}; // anonymous union
char attr_type() { return attr[0]; }
char *attr_name() { return attr + 1; }
void set_attr(Attribute a) { attr = a; }
} *Parameter_ptr;
// a list of attribute/value pairs
typedef class Parameters {
public:
class Parameters *next;
Parameter parm;
Parameters(Parameters *list) {
next = list;
}
// each of these routines takes address of pointer to the list
static void insert_real(Parameters **list, char *name, double r);
// insert string will copy string to heap
static void insert_string(Parameters **list, char *name, char *s);
static void insert_integer(Parameters **list, char *name, long i);
static void insert_logical(Parameters **list, char *name, bool l);
static void insert_atom(Parameters **list, char *name, char *s);
static Parameters *remove_key(Parameters **list, char *name);
} *Parameters_ptr;
typedef class Allegro_note: public Allegro_event {
public:
virtual ~Allegro_note();
long key; // note identifier
double pitch; // pitch in semitones (69 = A440)
double dur; // duration in seconds (normally to release point)
double loud; // dynamic corresponding to MIDI velocity
Parameters_ptr parameters; // attribute/value pair list
Allegro_note() { type = 'n'; parameters = NULL; }
} *Allegro_note_ptr;
typedef class Allegro_update: public Allegro_event {
public:
virtual ~Allegro_update() {};
long key; // note identifier (what sound is to be updated?)
Parameter parameter; // an update contains one attr/value pair
Allegro_update() { type = 'u'; }
} *Allegro_update_ptr;
// Beat is used to contruct a tempo map
typedef class Beat {
public:
double time;
double beat;
} *Beat_ptr;
// Beats is a list of Beat objects used in Seq
typedef class Beats {
private:
long max;
void expand();
public:
long len;
Beat_ptr beats;
Beat &operator[](int i) {
if (i<0) i=0;
if (i>=len) i=len-1;
/* assert(i >= 0 && i < len); dmazzoni*/
return beats[i];
}
Beats() {
max = len = 0;
beats = NULL;
expand();
beats[0].time = 0;
beats[0].beat = 0;
len = 1;
}
~Beats() {
if (beats) delete[] beats;
}
void insert(long i, Beat_ptr beat);
} *Beats_ptr;
class Time_map {
public:
Beats beats; // array of Beat
double last_tempo;
bool last_tempo_flag;
Time_map() {
last_tempo = 1.0;
last_tempo_flag = false;
};
long locate_time(double time);
long locate_beat(double beat);
double beat_to_time(double beat);
double time_to_beat(double time);
};
// Time_sig represents a single time signature;
// although not recommended, time_signatures may have arbitrary
// floating point values, e.g. 4.5 beats per measure
typedef class Time_sig {
public:
double beat; // when does this take effect?
double num; // what is the "numerator" (top number?)
double den; // what is the "denominator" (bottom number?)
Time_sig(double b, double n, double d) {
beat = b; num = n; den = d;
}
Time_sig() {
beat = 0; num = 0; den = 0;
}
void beat_to_measure(double beat, double *measure, double *m_beat,
double *num, double *den);
} *Time_sig_ptr;
// Time_sigs is a dynamic array of time signatures
class Time_sigs {
private:
long max;
void expand(); // make more space
public:
long len;
Time_sig_ptr time_sigs;
Time_sigs() {
max = len = 0;
time_sigs = NULL;
}
Time_sig &operator[](int i) {
assert(i >= 0 && i < len);
return time_sigs[i];
}
~Time_sigs() {
if (time_sigs) delete[] time_sigs;
}
void insert(double beat, double num, double den);
};
// A Seq is a sequence of Event, with a tempo map and
// a sequence of time signatures
//
typedef class Seq {
public:
Events notes; // array of Event
Time_map map;
Time_sigs time_sig;
int beat_x;
bool units_are_seconds;
Seq() {
units_are_seconds = true;
}
~Seq();
long seek_time(double time);
void convert_to_beats();
void convert_to_seconds();
bool insert_beat(double time, double beat);
bool insert_tempo(double tempo, double beat);
void add_event(Allegro_event_ptr event);
bool set_tempo(double tempo, double start_beat, double end_beat);
void set_time_sig(double beat, double num, double den);
void beat_to_measure(double beat, long *measure, double *m_beat,
double *num, double *den);
void set_events(Allegro_event_ptr *events, long len, long max);
} *Seq_ptr;
char *heapify(char *s); // put a string on the heap
#endif
|