Allegro is designed for use with Aura, and there is a mapping from Allegro to messages in Aura. There is an internal, object representation of Allegro as well, which is implemented in both C++ and Serpent (the Aura scripting language).
Allegro allows each note to be tagged so that the note can be referenced by updates at a later time.Q C4
MIDI Message Type | Allegro attribute |
pressure (polyphonic aftertouch) | pressurer (keyi set to key number) |
control change | control0r, control1r, control2r, ... control127r (note: values are normalized to the range [0..1]) |
program change | programi |
channel pressure (aftertouch) | pressurer (keyi is -1) |
pitchbend | bendr (normalized to the range [-1..1] |
key signature | keysigi (number of sharps, negative of number of flats) and modea ('majora' for major, 'minora' for minor) |
time signature | timesig_numr (the numerator) and timesig_denr (the denominator) |
system exclusive |
sysexs (message encoded as hex
string) |
Standard MIDI File metadata is also encoded into allegro attributes
as shown below:
Metadata
Type |
Allegro
attribute |
|
text (0x01) |
texts (note that the "s" suffix
indicates a string value) |
|
copyright (0x02) |
copyrights |
|
instrument (0x04) |
instruments |
|
lyric (0x05) |
lyrics |
|
marker (0x06) |
markers |
|
cue (0x07) |
cues |
|
misc (0x08) |
miscs |
|
smpte offset (0x54) |
smpteoffsets (SMPTE offset is
encoded in a string as follows: ddfps:ddh:ddm:dds:dd.ddf, where dd is a two-digit decimal number.
The one exception is that 30fps drop frame times are designated by
"29.97fps:...". Examples: "24fps:00h:00m:00s:00.00f",
"29.97fps:00h:01m:40s:00.01f") |
|
MIDI Channel Prefix (0x20) |
MIDI Channel Prefix is used to
assign a channel to a meta-event. In Allegro, this channel becomes a
key specification, e.g. "K4 -cues:"cue15". |
|
sequencer specific (0x7F) |
sqspecifics (data encoded as a hex string) | |
sequence name (0x03) |
|
|
track name (0x03) |
tracknames (in Allegro files, track name is written after #track n where n > 0, but internally data is stored as if one had written, e.g. -tracknames:"Bass") |
A few attributes, such as beatr and tempor, key signature information, and time signature information apply to all channels. The chani attribute can be set to -1 to indicate all channels.
Tracks from Standard MIDI Files are represented in the internal
Allegro
data structure. By default, all data goes to track zero (0), but a new
track can be designated using the syntax "#track n", where n
is an integer track number. All notes and updates following this track
specification (until the next one) go into the designated track.
From the programming API, track numbers can be encoded using the
channel; for
example, if the Allegro channel is:
track_number * 100 + midi_channel,
then channel 1207 (decimal) will indicate track 12, midi channel 7.
To preserve track association, the Allegro memory structures store each
track separately. Per-track metadata is stored with the associated
track with
a channel value of -1.
Allegro notes and updates are denoted by a line of text containing a
set of attributes. In addition, if a line begins with the characterrs
"#",
the line is not interpreted as a note or update. If the line begins
with
"# " (hash, space) the line is a comment. The characters "#track"
denote
the beginning of a new track. The "new track" syntax is:
#track track_number "track_name"
where track_number is a decimal integer and track_name
is any string of characters. Other metacommands beginning with "#" may
be introduced in the future.
All strings are quoted with double (") quotes. To enclose quotes and other special characters in strings, use backslash ("\") as the escape character. You must type two backslashes to enter one backslash in a string, e.g. the string "\\" has a length of one.
Allegro is case-insensitive, that is, upper and lower case letters are treated as the same, except that full attribute names, when spelled out, are case-sensitive. By convention, attributes are lower case for uniformity and simplicity. In the following, an italic n indicates a decimal integer, e.g. "7", and an italic r indicates a decimal floating point number, e.g. "7.34".
Allegro events always carry a channel number, but some data is not
channel-specific.
These events use channel number -1. Similarly, some updates apply to
every
note on a channel and are therefore not key-specific. These updates use
key number -1. Purely for aesthetic reasons, there is a special syntax
for -1, namely, channel -1 can be indicated "V-" and key -1 can be
indicated
"K-". (In common cases, "K-" can be omitted.)
|
|
chan | Vn |
key | Kn, Afn, An, Asn, ..., Gfn, Gn, Gsn |
loud | Lr, Lppp, ..., Lfff |
pitch | Pr, Afn, An, Asn, ..., Gfn, Gn, Gsn |
dur | Ur, S, I, Q, H, W, etc. |
time | Tr, TS, ..., TW, etc. |
(next time is not an Aura attribute) | Nr, NS, ..., NW, etc. |
(syntax for additional attributes/value pairs) | -attribute:value |
Since a pitch specification indicates a new note, use something like "-pitchr:60" to update pitch. Consider using "bendr" instead, or generate notes anyway and send them to a synthesizer that implements something like MIDI "mono" mode.
To get MIDI-like semantics, the keyi (K) attribute should not be specified at all. If you specify pitch using P or A through G, then the key will be implied by the pitch, and notes will therefore be identified as in MIDI. For example, a MIDI note-off message uses key number (not pitch, which may depend upon pitch-bend, etc.) to say which note to turn off.
If the key (K) is specified and less than 128, and no pitch is specified, then the pitch will default to the the key number. Thus K60 (with no P60 or C4 pitch specifications) is equivalent to P60 or C4.
If keyi (K) is not specified, control changes will have no keyi and therefore apply to the channel as a whole. This also corresponds to MIDI. The one exception to this is that pressure (polyphonic aftertouch) MIDI messages need a key number. If you specify pitch along with the control change, a new note will be generated. Therefore, to issue a polyphonic aftertouch message without a new note, you should use something like "V5 KG4 -pressurer:50", which says "on channel 5, pressure 50 on key 67 (g above middle c)."
To get more general semantics, every note can have an identifier. This allows multiple notes with the same pitch or for pitches of notes to change without ambiguity. Identifiers are specified by the keyi (K) attribute, for example "V5 K279 G4" creates a note (g above middle c) and labels it with the identifier 279. With this style, all updates should normally have a keyi (K) attribute, for example "V5 K279 -pressurer:50" sends a pressure changes to note 279. If "K" is omitted from a control change specification, then the control change applies to the channel, just as with the "MIDI style" in the previous paragraph. In other words, there is an implicit "K-1" attribute on all non-note attribute specifications. Thus, keyi is not a "sticky" attribute.
The initial default time is zero. The default time for the next event is computed as follows: Set the default time to the time of the current event. If a "N"ext attribute is given, the default time is incremented by the value of the "N"ext attribute. Otherwise, if the current event is a note, increment the default time by the duration of the note. This results in a new default, which may be overridden by a "T" attribute in the next event.
Octave numbers may be omitted, in which case the octave is chosen such that the pitch will be closest to the lexically previous pitch (in any voice). If the previous pitch is 6 half-steps (a tritone) away, then the current pitch will be higher than the previous pitch. When in doubt, specify the octave explicitly.
Pitch may also be specified as "P" followed by a number. P60 is middle C, P61 is a half step higher, equivalent to Cs4, and P60.5 is a quarter tone sharper than P60.
Although not recommended, "P" may also be followed by a "non-P" pitch specification starting with "A" through "G".
Durations may be combined using "+", which has lower precedence than any other duration operators.
Some examples follow:
Durations may also be specified by the letter U followed by a number of milliseconds. A decimal point is allowed, e.g. U23.25.
Q33 beats H.3 beats HT4/3 beats (half note triplet) IT.1/4 beats (a dotted sixteenth triplet) HTT8/9 beats Q/51/5 beats W3/2312/23 beats Q..7/4 beats (doubly dotted quarter) Q+I3/2 beats (quarter tied to eighth) IT+Q55 and 1/3 beats (eight triplet tied to 5 quarters)
When the tempo map is manipulated, either the time or the beat position must change. In Allegro, changes to the tempo map also change event times so that their beat positions remain unchanged.
On the other hand, when beats are specified, the tempo map is manipulated but event times are not changed. This effectively changes the beat positions of events. This is useful if performance data is captured and then beat information is added after the fact.
The entries in the tempo map are in non-decreasing time order and non-decreasing in beat order. Any attempt to specify an illegal tempo map in Allegro generates an error. This would most likely occur in Allegro as the result of inserting a beat at a position that conflicts with other beats.
Unlike normal attribute/value pairs, which are stored as events in the score, the beatr attribute generates an entry in the tempo map. It is an error to try to insert a beat such that the implied tempo would be negative. (Beats in the tempo map must be non-decreasing.)-beatr:25.0 T10542
When a beat is inserted into the time map, events in the score retain their times. This can cause very strange behavior if the time is specified in beats, because you are saying something like "insert beat 10 at beat 15." This has a well-defined interpretation: beat 15 is mapped to time t in seconds. Then, the entry (t, 10) is inserted into the tempo map. Now, what used to be at beat 15 (or time t) is now at beat 10. Normally, one would only specify beats at absolute times as shown in the example above.
These insert tempo changes to 80 and 100 beats per minute at beats 50 and 100, respectively. Notice the use of "Q" to specify units of beats instead of milliseconds. Tempo changes can be specified at any time. Event times throughout the score are adjusted according to the new tempo.TQ50 -tempor:80.0
...
TQ100 -tempor:100.0
...
Times and durations expressed directly in milliseconds require special care in combination with tempo specifications. When tempo is changed, every score event is remapped according to the new tempo. If a duration is specified as 100ms and then later in the score, tempo in that region is doubled, the actual duration will be 50ms. If the duration had been specified as a sixteenth note, it would still be a sixteenth note after the tempo change. Thus, all times and durations are treated as if they are beats when tempo is altered.
To freely mix time and beat specifications, it is recommended to specify a complete time map before any score events.
There is a danger that the extrapolated tempo may not correctly predict the next beat specification. This is not an error, and it just means that the tempo over some time interval must be recomputed based on the new beat information. The problem, however, is that any events that occur within that interval should probably be adjusted in time according to the new tempo. To avoid this problem, it is best to specify timing using tempo specifications rather than beat locations. In addition, the data structure does adjust times according to the beat information. Finally, when event data is generated, both beat positions and tempo changes are sent, avoiding the need to extrapolate tempo from previous beat positions.
An Event has fields time, key, and channel. Subclasses of Event include Note and Update. A Note has fields dur, pitch, loud, and attributes (attributes is a dictionary of attribute:value pairs). An Update has additional fields attribute, and value.
In C++, the allegro.h header documents (to some extent) the data structures.