-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmusic.doc
More file actions
792 lines (593 loc) · 27.7 KB
/
music.doc
File metadata and controls
792 lines (593 loc) · 27.7 KB
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
=== Usage ===
The "sz0music" program accepts the text format on stdin, and writes the
binary format to stdout. By convention, the input should use ".mml" file
name suffix and the output should use ".bgm" file name suffix. You can
then use "har" to create a Hamster archive and "superzz0 -er" to add it
into the world file.
The example "music.sz0" world will play the MUSIC.BGM lump. This lump is
not present in the world file; you can use the "extra_lump_name" and
"extra_lump_file" configuration settings to load it from an external file,
which may be useful to test the music playback.
(You might also write your own program to make the same binary output
format; it is not necessarily required to use this text input format.
For example, a program might be made for converting other formats.)
=== Syntax ===
Where a integer is expected, it can be decimal or hexadecimal; put $ at
first for hexadecimal. Where a real number is expected, it uses the same
format of the "strtod" function in C, but "$" has the same meaning as "0x"
at the beginning (you can use either one).
These commands are global and apply to all songs:
#DIVISIONS number
Set the number of divisions of a whole note. The shortest possible note
will be this number; e.g. 64 means that a 64th note is the shortest note.
#DEUTSCH
Same as #GERMAN.
#ENGLISH
Equivalent to "#SCALE c.d.ef.g.a.b" and is the default setting.
#EX-soundcard
Selects a sound card to use. See below for the list of sound cards, and
which tracks are assigned to that sound card. You cannot have more than
one command like this, and normal instruments cannot be used on the
tracks that are assigned to the sound card. (Not implemented yet)
#GERMAN
Equivalent to "#SCALE c.d.ef.g.abh".
#NOTE-DURATION numbers
Can specify any number of numbers, which are assumed to be the note
duration (in frames) which are used most commonly, since they will be
encoded more efficiently. This is not required; if it is not specified
then it will decide them automatically.
#OMIT-STANDARD
Causes the standard VM codes and other things to be omitted. This is only
useful if you are writing your own VM codes to use instead. If this is
used, then the labels named !0 !2 !4 !6 are short call addresses.
#SCALE text
Define the scale. Use the letters "a" to "j", and "." to mark a note that
is not given its own letter name.
#TEMPERAMENT number number
The first number is the frequency multiplication per octave (normally 2),
and the second number is the number of divisions of an octave (normally
12). You cannot combine #TEMPERAMENT with #TUNING.
#TEMPO-RATIO numerator denominator
Set the tempo ratio. This is specified as a fractional number of seconds
that tempo 1 corresponds to.
#TUNING ...
You can specify the custom tuning of each note individually. Specify a
list of numbers, which are the frequency of each note; you are allowed
to have / to make fractions, if desired. The first number must be the
frequency multiplication of one octave (normally two). (You can use this
command for making just intonation.)
@number = "filename"
Define a instrument from a file in the DER format explained below. The
instrument number can be in range 1 to 255.
@number = "filename" bits frequency loopstart loopend
Define a instrument from a raw file. The bits can be one of: "u8",
"u16le", "u16be", "s8", "s16le", "s16be". (Use "s8" for Amiga sounds.)
The frequency is a positive real number. The loop start and loop end
are both optional (although the loop start must be included if the loop
end is included).
@number = @number
Define a instrument as a copy of an existing instrument. This is only
valid for delay-line-based instruments (which, in the current version
of this software, cannot be defined directly and must use an external
file in DER format to be defined).
@v number = kind { numbers }
Define a envelope. See the below section about syntax of envelopes.
These commands apply to a specific song:
#NEXT number
Specify the next song number for the current song. If not specified,
then the next song number is the same as the current song number.
#SONG number
Beginning of a new song with a specified number. If this command does not
occur before the specification of any tracks/notes, then it will start
song 0 automatically; otherwise, this must be the first command within a
song, before any other commands that apply to the specific song.
#TEMPO number
Set the initial tempo of this song.
ABC...
Put one or more track letters A to Z followed by a space and then the
notes for that track. If multiple tracks are specified, then those notes
will apply to all of those tracks.
These commands are independent of songs:
;
Make a comment; you can put anything else on the same line, and it will
be ignored and is not written into the output file.
*
Defines a text macro. The second byte must be the character which is
used for this text macro, and then the rest is the definition of that
text macro. You can use * and the same character within the notes of
a channel to substitute the definition of the macro in its place. The
macro must be defined before it is used.
#CHDIR directory
Change directory; this can be used in case you want to read multiple
instruments from one directory.
#INCLUDE filename
Include the contents of another file as though it is included here.
List of sound cards:
MIDI A-P (MIDI)
MT32 A-I (Roland MT-32)
OPL2 A-I (Yamaha OPL2; AdLib, Sound Blaster)
OPL3 A-R (Yamaha OPL3; AdLib Gold, Sound Blaster Pro)
(Note that the use of emulated sound cards does not work yet)
Within a track, you can use the commands:
a b c d e f g h i j
Play a note. You can use + for sharp, - for flat, ' for one octave
higher; it is possible to have multiples and/or combinations of any
of these suffixes. You can also optionally follow it by the duration.
(The notes "h" and "i" and "j" are not valid unless you define a custom
scale by the use of the #SCALE or #GERMAN command.)
k
Key off, like r (and can have an optional duration) but will not cut
the note immediately
l
Set the duration. This must be followed by the number which specifies
the duration, which the number of divisions is divided by, and/or any
number of . afterward to each add half of the previous value; or, you
can alternatively use # and the number of frames. This format is also
valid anywhere that a note duration can be used (and is optional).
n
Specify a note number directly. If the duration is included, then you
must put a comma between the note number and duration.
o
Set the octave number. The lowest octave number is zero.
r
Make a rest; can have an optional duration.
t
Set the tempo; must be followed by a number. The number has the same
meaning as the #TEMPO command. This affects all tracks; you cannot
modify the tempo of each track individually.
w
Waits for the note duration (which can be specified or implied).
^
Follow by the optional duration, which extends the duration of the
previous note by this amount. (This must come after a note, rest, key
off, or wait.)
<
Low octave.
>
High octave.
@
Select the instrument.
@v
Select first envelope. (Zero means disable envelope.)
@u
Select second envelope. (Zero means disable envelope.)
v
Set the volume, which is a real number.
[ | ]
Make a local loop. You must specify the number of times to repeat after
the ending bracket (1 means it does not repeat). The | is optional; if
it is present, then the part between | and ] will be skipped during the
last time it is played. Nesting is allowed.
|: \ :|
Like [ | ] but this one will save space in the output file, and it is
not allowed to be nested.
K
Follow by a signed integer, which will set the transpose amount. If the
transpose amount is set to zero, then the transpose is cancelled.
L
Set the global loop start. When it reaches the end, it will continue
from the global loop start. This can be individually per track.
!
Causes the rest of this track to be ignored.
!!
Causes all data in the track before this command to not result in any
notes or delays, although any other command is still used. If !! is
after L then the part between L and !! will be played after it reaches
the end but not immediately.
%
Follow by a decimal or hexadecimal integer, which is pushed to the
stack at run time, as a literal value.
%%
Follow by any even number of hex digits without spaces in between (and
without $). This will cause the raw data to be included in the output.
%:
Follow by either a decimal or hexadecimal integer (but + and - is not
allowed) or by two ASCII characters, which cannot start with a space
or $ or a digit. This makes a label. Labels have a single namespace
shared by all tracks and all songs. Label names starting with ! have
built-in meanings, and should not normally be redefined.
%=
Has the format like %: but writes the raw 16-bit address to output,
instead of defining a label. This can occur before or after the label,
and can occur more than once for a label. (You will still need to use
commands such as %%A8 preceding it to make a jump instruction.) (The
target does not have to be in the same track; you can jump to a label
that is defined in any track.)
=== Syntax of envelopes ===
The syntax of a envelope is @v and a number and then = and then one of
the following variables to be affected:
A Amplitude (real)
F Frequency (real)
I Instrument (integer)
O Offset (integer)
R Resample offset (real)
After the variable selection you can use any combination of:
+ Envelope values are relative
! Continue after note release
$ Continue after note cut
Put {} with numbers in between, and optionally | for the loop start.
For a relative envelope, the first number can optionally have = at first
to make the first number absolute instead of relative; if it is absolute
already then the = is ignored.
For real relative envelopes, any number can optionally have * at first
(you cannot combine this with = at first) to multiply instead of add.
You can have | in the envelope after the loop start to indicate the loop
end; it will stop repeating after the note is release or cut (unless you
tell it to continue in that case), and will continue after the loop end.
=== Binary file format ===
If it is a wrapped file format, then it is universal type 75 and contains
two or three items as follows:
* A set, which must include the OID which identifies this file format,
which is: 2.25.196954517921581521497869385664052876310.6.1. It may also
include other things, such as a object descriptor which says "Super ZZ
Zero BG Music".
* The same as the unwrapped format.
* An optional key/value list for storing general-purpose metadata which
is not directly related to the music format (e.g. author's name).
The first and third field of the wrapped format use absolute OIDs, and do
not use OIDs relative to the Super ZZ Zero base OID like the other stuff
in Super ZZ Zero uses.
The unwrapped format is a sequence with fields:
* The sequence of songs (with zero-based numbering).
* The tempo ratio, which is a rational number, measured in hertz. When the
tempo is set, it is interpreted as a multiple of this number.
* The sequence of instruments (with one-based numbering).
* The sequence of channels (with one-based numbering). You cannot have more
than sixty-four channels.
* The short call addresses, which is a sequence with up to four unsigned
16-bit integers. If there is only one, it is used for all of 0x00 to 0x7F;
if two, the first for 0x00 to 0x3F and second for 0x40 to 0x7F; if three,
the first for 0x00 to 0x1F, second for 0x20 to 0x3F, and third for 0x40 to
to 0x7F; if four, then like with three but the third is 0x40 to 0x5F and
the fourth is for 0x60 to 0x7F. If this sequence is empty then all of the
short call addresses are zero.
* The sequence of real constants (the first one is numbered 16).
* The program, which is a octet string. The maximum length is 0xFFFE bytes.
More fields might be added in future; if so, the new ones are optional,
and if one is omitted but later ones are present, then null should be
present in place of the omitted fields.
Each song is specified as either null (if that song number is not used), or
a sequence with fields:
* Optional Graphic string or TRON string with the name of the song.
* Unsigned 16-bit integer being the initial tempo.
* Optional integer indicating the next song number; if omitted, then the
next song number is the same as this song number.
* One or more thread definitions, each of which is a type 0 implicit
sequence; the first field of that sequence is a integer telling the
starting instruction address, and optionally there can be a second field
which is a signed or unsigned 16-bit integer which is the initial value
of the A register (if not specified, then the default value is zero). The
channel number of the thread is one plus the (zero-based) thread number;
if that channel is not valid then the channel number is zero.
A instrument is null (if that number is not used) or a implicit typed
sequence according to the kind of instrument:
* Type 1 = Sampled instrument.
* Type 2 = Sampled with delay line and special effects. This instrument
cannot be used multiple times at once (but see type 3 below).
* Type 3 = Copy of a type 2 instrument. The only field is the instrument
number to copy from, which must be a number of a type 2 instrument which
has already been defined before this one.
The fields of a sampled instrument are:
* Optional Graphic string or TRON string with the name of the instrument.
* Base frequency, which is a real number.
* Codec, which is enumerated. The values are the same as the codec numbers
of the .SND lump.
* Wave data, which is a octet string, according to the codec. This is not
allowed to be empty; it must have at least one byte.
* An optional bit string, which must be empty if it is present. It has no
meaning, but in future might be used for flags.
* An optional integer specifying the starting loop point, in samples from
the beginning (zero means the beginning). Null or omitted disables looping.
* If the starting loop point is present, an optional ending loop point; if
it is present, then releasing the note will cause the sound to continue to
play until it reaches the end, without looping. (If the starting loop point
is omitted, then this one is also omitted and cannot be null instead.)
The fields of a sampled instrument with a delay line are:
* Optional name of the instrument.
* Sample rate of delay line, which is a real number.
* Frequency multiplier, which is a real number. This is multiplied by the
sample rate of the delay line to make the base frequency of the instrument.
* Log2 of the length of the delay line. This value must be between 2 and 16
inclusive; i.e. it cannot be longer than 65535 samples.
* Codec, which is enumerated.
* Wave data, which is a octet string, according to the codec.
* An integer specifying the starting loop point, or null for no loop. (You
cannot specify a ending loop point.)
* Key/value list of feedback; the keys are integers which is the offset
(which can be positive or negative or zero), and the values are the real
numbers meaning the amount of feedback at that offset. The maximum number
of pairs is currently eight (this may be increased in future).
* Real number being the amplitude multiplier of the wave data per filling
the delay line (it is reset to 1 on a new note).
* A sequence defining the LFO, or omitted to disable LFO. The four fields
of this sequence are: usage (enumerated 1 to 5), shape (enumerated 0 to 9),
epsilon (real), depth (real). The epsilon should be less than 1 and greater
than zero (it should normally be close to zero; numbers that are closer to
zero will result in a lower frequency oscillation), and the depth should
normally not exceed 1 (but is allowed to exceed 1; in some cases it makes
sense to be negative).
* A integer specifying how much of the delay line will be used for output;
omitted means to use the full delay line.
* A real number being a filter coefficient; omitted is the same as zero.
* A bit string with additional options. This can be omitted, which is the
same as a empty bit string.
Each channel is a implicit typed sequence according to the kind of channel:
* Type 0 = A ordinary mono channel; has no fields.
* Type 1 = A channel with stereo panning, if stereo is enabled, or
otherwise it acts the same like type 0. There are two fields, being real
numbers to multiply the amplitude for left and right output.
* Type 2 = Like type 1 but disabled if the audio output is mono.
* Type 3 = Sound card or emulated sound card (such as OPL3 or MPU-401).
There are three fields: first the OID (which may be relative) of the type
of sound card to emulate, second is a real number indicating the frequency
multiplier (which is optional and defaults to +1.0), and third is the
sequence of parameters for the plugin (which is optional, and the default
is an empty sequence).
* Type 4 = Same as type 3 but intended for use of MIDI, so that it may be
possible to use MIDI mapping with it. If MIDI mapping is not used, then it
is the same as type 3.
A real constant can be a real number, or it can be a implicit typed
sequence for one of the following operations; the number in parentheses
tells how many parameters it has, and + means it can optionally have more
than that many parameters.
0(0): Sample rate (Hz)
1(1+): Addition
2(1+): Multiplication
3(2): Subtraction
4(2): Division
5(1): Square root
6(1): Sine
7(1): Cosine
8(2): Power
9(0): Sequence number (zero-based)
10: Sequence; see below
11(0): pi
12(0): tau
The "sequence" real constant is only allowed as the last item in the
sequence of real constants, and contains two things, first being a
integer with how many further real constants to specify, and the second
being in the same format as the real constants but implicit type 9 can
be used to represent the sequence number, from zero up to one less than
how many are being specified in this way.
=== VM code ===
Each thread has registers:
A (16-bits)
B (16-bits)
C (8-bits) (Channel)
L (16-bits) (Repeat start address)
M (16-bits) (Repeat end address)
N (8-bits) (Repeat counter)
P (16-bits) (Program address)
R (16-bits) (Return address)
T (3-bits) (Stack pointer)
W (8-bits) (Wait)
X (real)
Y (real)
Each thread also has a stack with eight 16-bit integers. The bottom and
secondly from bottom values of these stacks are called I and J.
Note: Writing the number of an unsupported channel to the C register will
set the value of the C register to zero. (You can use this to check if a
channel is valid.)
There are also global registers shared by all threads:
G (16-bits)
Z (real)
The VM code instructions are:
[00-7F] A short call operator. The next instruction address is stored in
the R register, and the opcode is pushed to the stack.
[80-8F] Binary operations. These take two operands from the stack (the
second operand is on top), and pushes the result to the stack.
[90-97] Push registers: A B C G I J N R
[98-9F] Pop registers: A B C G I J N R
[A0-A7] Jump to relative signed 8-bits by conditions
[A8-AF] Jump to absolute 16-bits by conditions
[B0-B3] Push constant 0 to 3
[B4] Push immediate 8-bits
[B5] Push immediate 16-bits
[B6] Increment value at top of stack
[B7] Decrement value at top of stack
[B8] Read special integer register; the next byte specifies which one to
read, and the result is pushed to the stack.
[B9] Write special integer register; the next byte specified which one to
write, and the value to write is popped from the stack.
[BA] Like 0xB9 but adds the value to the register.
[BB] Like 0xB9 but subtracts the value from the register.
[BC] Read a special real register. The next byte has the low 7-bits to
specify which register to read and the high bit is clear to copy the value
to the X register or set for the Y register.
[BD] Write a special real register, like 0xBC but copies the other way.
[BE] Check a feature. The next byte tells the feature to check. The result
is pushed to the stack.
[BF] Like 0xBE but also pops a value from the stack to use as the parameter
for the feature to check; this is a separate set than the 0xBE instruction.
[C0-C7] Real operations. The second byte has the low 7-bits specifying the
value to use for "v" and the high bit is set for negative.
[C8] Unary real operations. The low 3-bits select the operation to do, and
the high 2-bits select the register (X, Y, or Z; setting both high bits is
not valid). Bit3 is set to multiply the input by tau, bit4 multiplies the
input by -1, and bit5 multiplies the output by -1.
[C9] Follow by one more byte; it is added to the number popped from the
stack and then the low 7-bits are used to find the real number index which
will overwrite the value of the X register.
[CA] Stop current thread
[CB] Exchange top two values of stack
[CC] Discard top of stack
[CD] Duplicate top of stack
[CE] Copy second from top of stack
[CF] Copy third from top of stack
[D0] Pop a length from the stack, and then pop a address; the contents of
the buffer at that address and length is sent as a MIDI message (see 0xF9
for more details about MIDI).
[D1] Pop a address from the stack, and push the value of the corresponding
emulation port for this channel to the stack. If this is not a emulation
channel or if there is no such port (or if that port is not readable), then
the result is unspecified.
[D2-D3] Pop address and then pop value, and write it into the music VM
memory. The change might or might not persist when changing to a different
song in the same file, but never persists if a different .BGM lump is
loaded. The code 0xD2 is 8-bit data and 0xD3 is 16-bit data. You cannot
write beyond the initial size of the loaded program.
[D4] Pop address of a sequence of emulation writes from the stack, and then
pop a number which is used to adjust the port number. The format of the
data is one flag byte, one count byte, and then the data. The bit0 of the
flag byte is set for 16-bit data or clear for 8-bit data, the bit1 of the
flag byte is set for explicit addresses for each data item or clear to be
implicit (starting from zero), and bit2 is set for 16-bit addresses or
clear for 8-bit addresses. If addresses are present, each item consists of
the address and then the data.
[E0-EF] Same as 0xF0 to 0xFF but before doing that, also pop a number to
set the wait time.
[F0] Return to R
[F1] Pop return address from stack and return
[F2] Set L to address of next instruction, and then pop from stack and
store the popped number in N register.
[F3] If N is zero, jump to M.
[F4] Set M to address of next instruction. If N is nonzero, decrement N and
jump to L.
[F5] Start a note. The frequency of the channel is set to the value of the
X register, unless X is zero or negative in which case it is unchanged. It
will also retrigger the instrument and envelopes.
[F6] Release a note. This will release the loop of the instrument if it is
set, and it will possibly release loops of envelopes as well.
[F7] Cut a note, which will cancel the instrument loop and all envelopes,
and suppresses the sound on this channel until another note is on.
[F8] Pop the address and then the value from the stack, and write to the
specified emulation port for this channel. This has no effect on any
channel other than an emulation channel. (Note that, for emulation
channels, the commands 0xF5, 0xF6, and 0xF7 only affect the envelopes;
you must use this command to actually play notes.)
[F9] Pop a 8-bit number from the stack and send it using MIDI. This only
works if the current channel is an emulation channel that supports MIDI;
not all channels do.
[FA] Like 0xF9 but pop two numbers; the bottom one is first and the top
one is second.
[FB] Like 0xFA but three numbers instead of only two.
[FF] No operation
If a 16-bit number is required as an operand, it is in small-endian format.
The binary operations are:
0 +
1 -
2 *
3 / (unsigned)
4 / (signed)
5 % (unsigned)
6 <<
7 >> (unsigned)
8 >> (signed)
9 &
A |
B ^
C Min (unsigned)
D Max (unsigned)
E Peek 8-bits
F Peek 16-bits
Conditions:
0 Always
1 Pop value; jump if zero
2 Pop value; jump if nonzero
3 Pop two values; jump if first is less than second (unsigned)
4 Pop two values; jump if equal
5 Pop two values; jump if unequal
6 Call subroutine; store return address in R register
7 Call subroutine; push return address to stack
The special integer registers are (*read-only):
(Global)
00 Current thread (zero-based) *
01 Tempo
02 Tempo accumulator
03 Value from host system (to implement dynamic music) *
7F Debug output
(Channel)
80 Instrument
81 Offset
82 Flags (partially read-only)
90 First envelope address + 1 (0=none)
91 First envelope position
92 Second envelope address + 1 (0=none)
93 Second envelope position
(Instrument)
C0 Delay line usage amount
Trying to select an unsupported instrument (or an instrument number that
is out of range) will set the instrument to zero instead of the instrument
number that you intended to set; you can read it back to check if this
instrument is valid.
Channel flags are:
01 If this channel exists *
02 The note has started and not finished or cut
04 The note has started and not released
08 If this is an emulation channel *
40 First envelope is on
80 Second envelope is on
The special real registers are (*read-only):
(Channel)
40 Frequency multiplier
41 Amplitude
42 Direct frequency
43 Resample offset
(Instrument)
60 Delay line usage amount
61 Filter coefficient
62 LFO depth
Changing the values (integer or real) of instruments is not reset when a
new note is played, and is not necessarily reset when a new song is played
either (although in some cases it is).
The binary real operations are:
0 X=v
1 Y=v
2 X+=v
3 X*=v
4 X/=v
5 X=pow(X,v)
6 X=fmod(X,v)
7 X=fmin(X,v)
The unary real operations are:
0 v=X
1 Exchange v with X
2 v=fabs(v)
3 v=sqrt(v)
4 v=sin(v)
5 v=cos(v)
6 v=floor(v)
7 (reserved)
Built-in real values:
0 Zero
1 One
2 Two
3 Half
4 X
5 Y
6 Z
7 (reserved)
8 A
9 B
10 G
11 N
12 (reserved)
13 (reserved)
14 (reserved)
15 (reserved)
The format of a envelope is: the flag byte, the special register to be
affected (0x40 to 0x7F are real and 0x80 to 0xFF are integers), the loop
start (0 means the first element), the loop end (0 means the first
element), and then the elements of the envelope list (one byte each).
The flags are:
* bit0 = Set for relative operation or clear for absolute. For integers,
relative values are treated as signed and absolute values are treated as
unsigned. For reals, if it is relative then the high bit of each value
will be set for multiplication or clear for addition.
* bit1 = Reset when a new note is started.
* bit2 = Continue when the note is released.
* bit3 = Continue when the note is cut.
* bit4 = Treat the first value as absolute even if it is relative.
* bit5 = If the note is not on, and bit2 or bit3 is not set, then it will
continue without looping, until a number 0 or 128 is found at which point
the envelope stops; it will use the 0 or 128 to set the value, too. If it
is absolute or integer (or both), then 128 does not set the value; if it
is real relative than 128 does set the value (to zero). This will affect
any 0 or 128 found in the envelope and not only the last one.
* bit6 = (reserved)
* bit7 = Set if this envelope controls a emulator register, which only
works if the current channel is a emulator channel. If this is set, then
bit0 instead specifies bit8 of the register number, and it is always an
absolute integer register. (Not implemented yet)
Setting the loop start of a envelope to 255 means that it will stop the
envelope when the loop end is reached.