-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathallegro.htm
executable file
·828 lines (828 loc) · 29 KB
/
allegro.htm
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
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
<!DOCTYPE html PUBLIC "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<title>Allegro Music Representation Language</title>
</head>
<body>
<center>
<h1>Allegro Music Representation Language</h1>
</center>
Allegro is a simple, declarative, text-based language for music
representation.
Allegro is very similar to Adagio, but it is extended somewhat to make
the representation of beats and attributes simpler and more uniform.
Allegro
is also intended to represent Standard MIDI files, and there are
standard
attribute names and encodings in Allegro for metadata found in Standard
MIDI
files.
<p>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).
</p>
<h2>Basic Concepts</h2>
Allegro represents notes, attribute/value pairs (typically updates to
notes),
and timing information in the form of tempo and beats. Allegro is a
free-form
ascii text language similar to Adagio (a notation introduced in the CMU
MIDI Toolkit). In its simplest usage, every line of text represents a
note.
Every note is a set of attributes separated by white space and ending
with
a newline. For example, the following indicates a quarter note at
middle C:
<blockquote>
<pre>Q C4</pre>
</blockquote>
Allegro allows each note to be tagged so that the note can be
referenced
by updates at a later time.
<h2>Standard Attributes and MIDI Data</h2>
Notes have a set of fields that correspond more-or-less to MIDI data.
The fields are:
<ul>
<li>key - the key number or tag for this note. In MIDI, the key
indicates
the pitch,
but in Allegro, the key can be any number. For example, key can be a
sequence
number so every note can have a unique name. </li>
<li>chan - the MIDI channel. In Allegro, the channel can be any
integer.
This creates
a two-dimentional name space for notes: <chan, key> </li>
<li>time - the starting time of the note. This can be in beats or
seconds.
The Allegro
data structure can convert from seconds to beats and back. </li>
<li>pitch - the pitch of a note, expressed in the same units as MIDI,
but
this is a float rather than an integer so that precise tuning can be
expressed. Note that in MIDI, pitch is implied by the key, but in
Allegro, the key is just a name or a way to refer to a particular
sound. The pitch can be specified separately. (If you are working with
MIDI, you will probably want to specify pitch symbolically, e.g. C4, or
as an integer, e.g. P60. The key number will default to the pitch.) </li>
<li>loud - a parameter corresponding to MIDI velocity, but this is a
float rather than
an integer. </li>
</ul>
In addition, notes can have attribute/value pairs. In Allegro, the last
letter
of the attribute conveys the type of its value. For example,
"bendr" should be read as attribute "bend" of type "r"eal. An "r"
suffix
is for "r"eal values (double precision floats). When used with Aura,
notes attributes
are represented by a sequence of messages, each generally
conveying an attribute/value
pair along with the <chan, key> note name. If an update applies
to all notes
on a channel, the key value is specified as -1. Some standard
attributes are listed below:
<center>
<table style="width: 75%;" border="1">
<tbody>
<tr>
<td align="left" height="13" width="50%"><b>MIDI Message Type</b></td>
<td align="left" height="13" width="50%"><b>Allegro attribute</b></td>
</tr>
<tr>
<td align="left" height="19" width="50%">pressure (polyphonic
aftertouch)</td>
<td align="left" height="19" width="50%">pressurer (keyi set to
key number)</td>
</tr>
<tr>
<td align="left" height="19" width="50%">control change</td>
<td align="left" height="19" width="50%">control0r, control1r,
control2r,
... control127r (note: values are normalized to the range [0..1])</td>
</tr>
<tr>
<td align="left" height="19" width="50%">program change</td>
<td align="left" height="19" width="50%">programi</td>
</tr>
<tr>
<td align="left" height="19" width="50%">channel pressure
(aftertouch)</td>
<td align="left" height="19" width="50%">pressurer (keyi is -1)</td>
</tr>
<tr>
<td align="left" height="19" width="50%">pitchbend</td>
<td align="left" height="19" width="50%">bendr (normalized to the
range [-1..1]</td>
</tr>
<tr>
<td align="left" height="19" width="50%">key signature</td>
<td align="left" height="19" width="50%">keysigi (number of
sharps, negative
of number of flats) and modea ('majora' for major, 'minora' for
minor)</td>
</tr>
<tr>
<td style="width: 50%; height: 19px; text-align: left;">time
signature</td>
<td align="left" height="19" width="50%">timesig_numr (the
numerator) and
timesig_denr (the denominator)</td>
</tr>
<tr>
<td style="vertical-align: top;">system exclusive<br>
</td>
<td style="vertical-align: top;">sysexs (message encoded as hex
string)<br>
</td>
</tr>
</tbody>
</table>
<br>
</center>
<p>Standard MIDI File metadata is also encoded into allegro attributes
as shown below:<br>
</p>
<center>
<table style="text-align: left; width: 75%;" border="1">
<tbody>
<tr>
<td style="vertical-align: top;" width="30%"><span
style="font-weight: bold;">Metadata
Type</span><br>
</td>
<td style="vertical-align: top;" width="70%"><span
style="font-weight: bold;">Allegro
attribute</span><br>
</td>
</tr>
<tr>
<td style="vertical-align: top;">text (0x01)<br>
</td>
<td style="vertical-align: top;">texts (note that the "s" suffix
indicates a string value)<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;">copyright (0x02)<br>
</td>
<td style="vertical-align: top;">copyrights<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;">instrument (0x04)<br>
</td>
<td style="vertical-align: top;">instruments<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;">lyric (0x05)<br>
</td>
<td style="vertical-align: top;">lyrics<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;">marker (0x06)<br>
</td>
<td style="vertical-align: top;">markers<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;">cue (0x07)<br>
</td>
<td style="vertical-align: top;">cues<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;">misc (0x08)<br>
</td>
<td style="vertical-align: top;">miscs<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;">smpte offset (0x54)<br>
</td>
<td style="vertical-align: top;">smpteoffsets (SMPTE offset is
encoded in a string as follows: <span style="font-style: italic;">dd</span>fps:<span
style="font-style: italic;">dd</span>h:<span
style="font-style: italic;">dd</span>m:<span
style="font-style: italic;">dd</span>s:<span
style="font-style: italic;">dd.dd</span>f, where <span
style="font-style: italic;">dd</span> 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")<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;">MIDI Channel Prefix (0x20)<br>
</td>
<td style="vertical-align: top;">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".<br>
</td>
</tr>
<tr>
<td style="vertical-align: top;">sequencer specific (0x7F)<br>
</td>
<td style="vertical-align: top;">sqspecifics (data encoded as a
hex string)</td>
</tr>
<tr>
<td style="vertical-align: top;">sequence name (0x03)<br>
</td>
<td style="vertical-align: top;">
<table style="width: 75%;" border="1">
<tbody>
<tr>
<td style="vertical-align: top;">seqnames (in Allegro
files, sequence
name is written after #track 0, but internally data is stored as if one
had written, e.g. -seqnames:"Jordu")<br>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td style="vertical-align: top;">track name (0x03)<br>
</td>
<td style="vertical-align: top;">tracknames (in Allegro files,
track name is written after #track <span style="font-style: italic;">n</span>
where <span style="font-style: italic;">n </span>> 0, but
internally data is stored as if one had written, e.g.
-tracknames:"Bass")</td>
</tr>
</tbody>
</table>
</center>
<p><br>
</p>
<h3>MIDI Track Data</h3>
<p>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.
</p>
<p>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 <i>n</i>", where <i>n</i>
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:
<br>
track_number * 100 + midi_channel,
<br>
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.
</p>
<h2>Allegro Syntax</h2>
Because Allegro has no nested expressions or complicated syntax, I will
not present a detailed formal grammar. The previous section outlined
the
semantics of attributes. This section describes the syntax to denote an
attribute. Additional syntax and semantics for tempo and beats is given
in the next section.
<p>Comments are indicated by the "#" character that is not part of a
quoted string. The "#" and everything that follows to the end of the line
are ignored.
<p>Allegro notes and updates are denoted by a line of text containing a
set of attributes. If a line begins with the character
"#",
the line is <i>not</i> interpreted as a note or update but merely a
full line comment, with two special exceptions:
<ol>
<li>A line beginning with "#track" denotes
the beginning of a new track. The "new track" syntax is:
<br>
#track <i>track_number</i> "<i>track_name</i>"
<br>
where <i>track_number</i> is a decimal integer and <i>track_name</i>
is any string of characters.</li>
<li>A line beginning with "#offset" denotes a score offset. The
"offset" syntax is:
<br>
#offset <i>number</i>
<br>
where <i>number</i> is a float. The offset is stored in the sequence
data structure, but has no specific interpretation.
</li>
</ol>
Other metacommands beginning with "#" may
be introduced in the future, so it is strongly recommended that
comments beginning in column 1 follow the "#" with a space.
</p>
<p>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.
</p>
<p>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 <i>n</i> indicates a
decimal
integer, e.g. "7", and an italic <i>r</i> indicates a decimal floating
point number, e.g. "7.34".
</p>
<p>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.)
<br>
<table border="1" width="100%">
<tbody>
<tr>
<td width="50%">
<center><b><font size="+1">Allegro Field or Attribute</font></b></center>
</td>
<td width="50%">
<center><b><font size="+1">Allegro Syntax</font></b></center>
</td>
</tr>
<tr>
<td width="50%">chan</td>
<td width="50%">V<i>n</i></td>
</tr>
<tr>
<td width="50%">key</td>
<td width="50%">K<i>n</i>, Af<i>n</i>, A<i>n</i>, As<i>n</i>,
..., Gf<i>n</i>,
G<i>n</i>, Gs<i>n</i></td>
</tr>
<tr>
<td width="50%">loud</td>
<td width="50%">L<i>r</i>, Lppp, ..., Lfff</td>
</tr>
<tr>
<td width="50%">pitch</td>
<td width="50%">P<i>r</i>, Af<i>n</i>, A<i>n</i>, As<i>n</i>,
..., Gf<i>n</i>,
G<i>n</i>, Gs<i>n</i></td>
</tr>
<tr>
<td width="50%">dur</td>
<td width="50%">U<i>r</i>, S, I, Q, H, W, etc.</td>
</tr>
<tr>
<td width="50%">time</td>
<td width="50%">T<i>r</i>, TS, ..., TW, etc.</td>
</tr>
<tr>
<td width="50%">(next time is not an Aura attribute)</td>
<td width="50%">N<i>r</i>, NS, ..., NW, etc.</td>
</tr>
<tr>
<td width="50%">(syntax for additional attributes/value pairs)</td>
<td width="50%">-<i>attribute</i>:<i>value</i></td>
</tr>
</tbody>
</table>
</p>
<h3>Notes vs. Updates</h3>
A new note or sound object is created by the appearance of a field with
any of the following initial letters: P, A, B, C, D, E, F, G (pitches),
or U (duration). If neither an explicit pitch or duration appears, then
an update is generated. In terms of Aura streams, an update means that
no "gater" attribute will be generated, and no sound resource will be
allocated.
It is assumed (but not checked) that an update applies to an existing
resource
and merely modifies some of its attributes.
<p>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.
</p>
<h3>Sticky Attributes</h3>
Most attribute values need not be specified if they do not change from
their lexically previous value. However, a blank line does not mean
"repeat
the last note;" at least one attribute must be present to signify
anything
at all. Only if a note is specified using at least a pitch or duration
will certain default values be used. For example, default pitch is
ignored
if only pitch bend is updated.
<p>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.
</p>
<p>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.
</p>
<p>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)."
</p>
<p>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. <i>In other words, there is an
implicit
"K-1" attribute on all non-note attribute specifications. </i>Thus,
keyi
is not a "sticky" attribute.
</p>
<p>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.
</p>
<h3>Pitch Specification</h3>
Pitches in Allegro are the same as in Adagio. The letters "A" through
"G"
are followed optionally by one or more "S" (sharps) or "F" (flats), and
then by an octave designation (an integer). C4 is middle C. Octaves run
from C to B, so B4 is higher in pitch than C4, as musicians would
expect.
Sharps and flats are added after the octave is computed, so for
example,
Cf5 is the same as B4, even though the octave numbers are different.
<p>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.
</p>
<p>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.
</p>
<p>Although not recommended, "P" may also be followed by a "non-P"
pitch
specification starting with "A" through "G".
</p>
<h3>Duration Specification</h3>
Durations are the most complicated attributes in Allegro and Adagio.
The
duration letters S, I, Q, H, and W designate Sixteenth, eIghth,
Quarter,
Half, and Whole notes. These letters may be followed by any combination
of "." (dots) and "T" (triplets). A dot multiplies the duration by 1.5.
Two dots multiply the duration by 1.75, etc. A triplet multiplies the
duration
by 2/3. The end of the specification is an optional multiplier (an
integer)
followed by an optional divisor ("/" followed by an integer.)
<p>Durations may be combined using "+", which has lower precedence than
any other duration operators.
</p>
<p>Some examples follow:
</p>
<blockquote>
<table border="1">
<tbody>
<tr>
<td width="30%">
<pre>Q3</pre>
</td>
<td width="70%">3 beats</td>
</tr>
<tr>
<td width="30%">
<pre>H.</pre>
</td>
<td width="70%">3 beats</td>
</tr>
<tr>
<td width="30%">
<pre>HT</pre>
</td>
<td width="70%">4/3 beats (half note triplet)</td>
</tr>
<tr>
<td width="30%">
<pre>IT.</pre>
</td>
<td width="70%">1/4 beats (a dotted sixteenth triplet)</td>
</tr>
<tr>
<td width="30%">
<pre>HTT</pre>
</td>
<td width="70%">8/9 beats</td>
</tr>
<tr>
<td width="30%">
<pre>Q/5</pre>
</td>
<td width="70%">1/5 beats</td>
</tr>
<tr>
<td width="30%">
<pre>W3/23</pre>
</td>
<td width="70%">12/23 beats</td>
</tr>
<tr>
<td width="30%">
<pre>Q..</pre>
</td>
<td width="70%">7/4 beats (doubly dotted quarter)</td>
</tr>
<tr>
<td width="30%">
<pre>Q+I</pre>
</td>
<td width="70%">3/2 beats (quarter tied to eighth)</td>
</tr>
<tr>
<td width="30%">
<pre>IT+Q5</pre>
</td>
<td width="70%">5 and 1/3 beats (eight triplet tied to 5
quarters)</td>
</tr>
</tbody>
</table>
</blockquote>
Durations may also be specified by the letter U followed by a number of
milliseconds. A decimal point is allowed, e.g. <tt>U23.25</tt>.
<h3>Loudness Specification</h3>
Loudness is specified by "L" followed by "ppp", "pp", "p", "mp", "mf",
"f", "ff", "fff", or by a floating point number. The normal
loudness
range is that of MIDI velocity, from 0 (silent) to 127 (maximum). The
interpretation
of dynamic markings and the numerical values is to be determined.
<h3>Time Specification</h3>
Times are specified just like durations, except that a leading "T"
indicates
this is a time. If the "T" is followed by a digit, then the time is
specified
numerically as milliseconds. For example, "TW5" means 5 whole notes or
20 beats, while "T20" or "T20.0" means 20 milliseconds.
<h3>Next Time Specification</h3>
The default time of the next note, sound or update can be specified
just
like durations, except that a leading "N" is given. If "N" is followed
by a digit, then the value is specified numerically as
milliseconds.
For example, "NQ" means the next event should take place a beat after
this
event. This specifies a default which may be overridden by an explicit
time specification in the next event.
<h2>Tempo Maps</h2>
The goal of tempo specification in Allegro is to allow flexibility
without
getting overly complex. There is one and only one tempo map per score.
This is a limitation, but it is certainly possible to have multiple
score
objects when multiple tempo maps are required. Tempo maps can be
specified
by entering beats or by entering tempo changes. Internally, a tempo map
is a sequence of pairs indicating time and beat. Tempo is assumed to be
constant between any two adjacent points in the tempo map. In a stream
of Aura events, tempo map events are translated into two attributes:
beatr
and tempor. The beatr attribute gives the current beat, and the tempor
attribute gives the tempo change. The use of tempor allows the receiver
to respond to tempo changes without waiting for the next beat.
<p>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.
</p>
<p>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.
</p>
<p>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.
</p>
<h3>Avoiding Numerical Problems</h3>
Instantaneous changes in beat position (infinite tempo) are not
allowed,
nor are zero tempos allowed. However, attempts to create an infinite or
zero tempo are automatically approximated by shifting beats or times in
the time map by one microsecond or one microbeat. For example, if the
tempo
at some beat position <i>b</i> is set to zero, the next entry in the
time
map is changed to have a beat position <i>b</i> + 0.000001. There is
no
way in Allegro to specify an infinite tempo: if you specify a second
beat
position at at given time, the entry in the time map is simply edited
to
contain the new beat position. One exception to this is at the
beginning
of the score. Beat 0 occurs at time 0, so if you insert, say, beat 5 at
time 0, you imply an infinite tempo. The score object will
automatically
change this to beat 5 at time 0.000001 seconds.
<h3>Specifying Beat Times</h3>
Beat encoding might be used to synchronize external MIDI sequences or
to
generate a MIDI file for use in a sequencer or music notation package
where
beat information is necessary. The following example specifies beat 25
at time 10.542 seconds:
<blockquote>
<pre>-beatr:25.0 T10542</pre>
</blockquote>
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.)
<p>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
<i>t</i>
in seconds. Then, the entry (<i>t</i>, 10) is inserted into the tempo
map.
Now, what used to be at beat 15 (or time <i>t</i>) is now at beat 10.
Normally,
one would only specify beats at absolute times as shown in the example
above.
</p>
<h3>Specifying Tempo</h3>
For text based notation and composition, we usually want to specify
notes
in terms of beats and specify the tempo of different sections of the
score.
The following example specifies tempo changes:
<blockquote>
<pre>TQ50 -tempor:80.0<br>...<br>TQ100 -tempor:100.0<br>...</pre>
</blockquote>
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.
<p>Times and durations expressed directly in milliseconds require
special
care in combination with tempo specifications. When tempo is changed, <i>every</i>
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.
</p>
<p>To freely mix time and beat specifications, it is recommended to
specify
a complete time map before any score events.
</p>
<h3>Time Representation</h3>
Internally, score events are associated with timestamps in units of
seconds.
An auxiliary structure contains a sequence of timestamped beat
positions.
For example, the structure might contain ((0, 0), (10, 10), (20, 30)),
which indicates that at time zero, we are at beat zero. At time 10, we
are at beat 10, so the tempo for the first 10 seconds is 60 beats per
minute.
At time 20, we are at beat 30, so the tempo from 10 to 20 is 120 beats
per minute (20 beats in 10 seconds). The structure may also contain a
final
tempo, indicating the mapping from time to beats after the last beat
position
entry. If no final tempo is indicated, tempo and beats are extrapolated
from the last two points in the map. Initially, the map has just one
point,
(0, 0), and tempo100.
<p>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.
</p>
<h3>Time Manipulation</h3>
An important aspect of this design is to support editing and
manipulation
of data. Operations include:
<ul>
<li>insert a beat position at a time position: this operation
modifies the
data structure by inserting a (time, beat) pair. No times are altered
if
the new beat position is not at the end of the structure. If at the
end,
times are adjusted between the previous last time position and this new
time position.</li>
<li>insert a tempo at a time position: this inserts a (time, beat)
pair and
adjusts the times of everything that follows so that the tempo is
achieved
to the next beat. If the time position corresponds to the last time in
the structure, the tempo is used in place of extrapolation.</li>
<li>maintain a tempo over a region: this inserts a (time, beat) pair
for
the
beginning and ending of the region, and removes all pairs in the
region.
Times after the region are adjusted.</li>
</ul>
<h2>
Internal Representation</h2>
In Serpent, the representation is a class called Seq, containing the
fields
Notes and Map. Notes is a sequence of Events, and Map is a sequence of
time/beat pairs.
<p>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.
</p>
<p>In C++, the allegro.h header documents (to some extent) the data
structures.
</p>
</body>
</html>