Copyright (c) Hyperion Entertainment and contributors.
TRKR IFF Tracker Music Module
Jump to navigation
Jump to search
TRKR
IFF FORM TRKR
Proposal for an IFF Tracker Song File Format
(revision 1.1, as of January 1, 1993)
Designed and written by Darren Schebek, Full Tilt Entertainment
Usenet: [email protected]
Since releasing my original draft, I have heard comments that an IFF tracker
module file format would "balloon" the original tracker module out with a lot
of header overhead. This is not so. In fact, this IFF TRKR file format
eliminates a *great deal* of unnecessary and redundant file data inherent in
typical module file formats (Noisetracker v2.0 being the worst I've seen so
far). Much of this space is used up in trailing note events at the end of
patterns (eg, for modules that only use the first 48 notes in a pattern),
duplication of patterns at the individual channel level (which Noisetracker
v2.0 is notorious for), and unnecessarily padding out the play sequence table
to a constant size, regardless of how many elements in the table are actually
used.
I have attempted to design this file format with the idea utmost in mind of
allowing as many possible tracker formats to be upward-compatible with it.
I have also decided to all but eliminate MIDI support, while still trying to
allow for MIDI extensions to the format. I do this partly in order to more
accurately define the essence of a tracker module, but also because I feel
unqualified to define an effective template for MIDI support. However, MIDI
extensions can always be added to the format later on.
On the other hand, I have deliberately designed this draft of the IFF TRKR
format to be much more powerful and flexible than a "standard" tracker module.
It is always easier to trim down a design than to expand it.
One of the major changes I have made is to never assume a specific size for a
given pattern of notes. With this draft, patterns can be any length at all.
There is a slight downside to this. Whereas with the old Noisetracker format,
all patterns were 64 notes in length (thus ensuring that new patterns for each
audio channel started simultaneously), my file format loses this convenience.
New patterns can start at any given time in any given audio channel without
regard to any new patterns in any other audio channel. As you may notice,
this plays havoc with repeat commands and other commands that reference to
specific points in the song.
To solve this problem, I came up with the idea of adding a "marker" chunk to
the file format. Each bookmark defines a specific poosition in the song for
each audio channel, recording (for each audio channel) pattern number and note
offset into that pattern. A player program can read in the song, read in the
bookmark chunk(s), then pre-calculate appropriate pointers for each bookmark
prior to playing the song. Any commands that refer to these bookmarks (eg, a
REPEAT command) will reference the bookmark by number in the same way that
instruments are referenced.
Another idea I came up with was a resolution to the timing problems
inherent with PAL/NTSC songs (since no such timing information is stored in
most tracker formats). Timing in my format is now specified in "note
events per minute". With this method of timing, calculations for CIA timer
frequency become trivial. It is, however, still up to the player program
to determine whether it is running on a PAL or NTSC Amiga and to compensate
for the slight difference in CIA clock frequency (most players that use the
CIA timers do not make this compensation). So a 60Hz playback frequency
now becomes 3600 note events per minute, and 50 Hz becomes 3000 note
events/minute. With this timing method, it is also possible to create a
new song command that allows you to change the playback frequency (and I have
done so.
The longword that comprises a "note event" has also been modified drastically,
and now contains a 13-bit operand field. This allows for greater resolution
for commands such as SAMPLE OFFSET. It also facilitates the command for
setting the number of note events per minute.
I'll start with a sort of visual summary of the format, and then explain the
various chunks and fields.
------------------------------
FORM size
TRKR
TRHD size
ubyte numsongs Number of TRSG chunks in this FORM TRKR.
ubyte numinsts Number of TINS chunks in this FORM TRKR.
uword numpatts Number of PATT chunks in this FORM TRKR.
[NAME] Optional NAME chunk.
[AUTH] Optional AUTH chunk.
[ANNO] Optional ANNO chunk.
[(c) ] Optional (c) chunk.
TRSG size Required chunk. May be more than one TRSG chunk.
SGHD size Required Song header chunk.
uword ticksperminute Number of "ticks" (interrupts) per minute.
ubyte tickspernote Number of "ticks" between successive note events.
ubyte iterations Default number of iterations to play this song.
ubyte numchannels Number of audio channels used by this song.
ubyte flags Various flags for this song.
FIXED volume Default global volume of this entire song.
char songname[] Title of this song.
CSEQ size Required channel sequence chunk. One per channel.
uword pattarray[] Word array of PATT #'s to play for channel #0.
CSEQ size
uword pattarray[] Word array of PATT #'s to play for channel #1.
.
.
.
CSEQ size
uword pattarray[] Array of PATT #'s to play for
channel #(numchannels-1).
[MRKR] size Opt. marker chunk for recording repeat points.
ulong noteoffset Offset in notes to marker's position in song.
ubyte register Register number for referencing this marker.
char markername[] Name of the marker (for referencing by name).
[MRKR] size There is no limit to the number of MRKR chunks.
etc.
TINS size Required instrument chunk.
TIHD size Required instrument header chunk.
ubyte register Register number of this instrument
ubyte type Type of instrument. 0 = 8SVX.
FIXED volume Default relative volume of this instrument.
ubyte data1 MIDI channel # if type = 1.
ubyte data2 MIDI preset # if type = 1.
char instname[] Name of this instrument (or filename).
[FORM size 8SVX...] Optional Instrument data for this instrument.
TINS size There can be up to 63 TINS chunks in the file.
TIHD size ...
[FORM size 8SVX...]
PATT size Required pattern data chunk.
ulong nevents[] Longword array of note events comprising pattern.
PATT size There can be up to 65536 PATT chunks in the FORM.
ulong nevents[] PATT chunks are the last chunks in the FORM TRKR.
.
.
.
------------------------------
Here now is an explanation of all chunks and their corresponding fields:
==============================
TRHD chunk - Required:
The TRHD chunk contains information global to the file. It contains the
following fields...
ubyte numsongs
Specifies how many TRSG chunks (ie, songs) are contained within the FORM
TRKR. There is no limit to the number of TRSG chunks that can exist,
although 256 of them should be a reasonable limit (or perhaps even less).
ubyte numinsts
Specifies how many TINS chunks (ie, instrument definitions) exist within
the FORM TRKR. There can be up to 63 TINS chunks in a FORM TRKR, since
the note event has enough bits allocated to support that many instruments.
Instruments are shared by all songs in the FORM TRKR.
uword numpatts
Specifies the number of PATT chunks (ie, patterns, or note event arrays)
that exist within the FORM TRKR. Like instruments, all patterns are
shared by all songs in the FORM. There can be up to 65536 PATT chunks in
a single FORM TRKR.
==============================
Optional "NAME", "AUTH", "ANNO", "(c) " chunks
These standard chunks are optional, and should appear immediately after
the TRHD chunk in the FORM TRKR.
==============================
TRSG chunk - Required
The TRSG chunk defines the parameters and patterns that comprise a single
song. There must be at least one TRSG chunk in the FORM TRKR, appearing
immediately after the TRHD chunk and any of the optional chunks mentioned
above (ie, "NAME", "AUTH", "ANNO", "(c) ").
This chunk is made up of several sub-chunks:
SGHD chunk - Required song header chunk.
This chunk contains parameters necessary for playing this particular song.
The fields are as follows:
uword ticksperminute
This field specifies the interrupt frequency of the player in "ticks"
per minute, where a "tick" refers to the occurrence of the player
interrupt (it is naturally assumed that the player interrupt will be
running as a CIA timer interrupt, and not a vertical blank interrupt).
This parameter, then, specifies the CIA interrupt frequency. For
example, a value of 3600 ticks/minute (60Hz interrupt frequency), would
result in a CIA timer value of 42954540/3600 = 11932 (approx.) for NTSC
Amiga platforms and 42562740/3600 = 11823 for PAL Amiga platforms.
Defining interrupt frequency in this way eliminates timing differences
between NTSC- and PAL-composed songs. The range for this parameter is
700-6000 inclusive. Slower tempos than 700 can be achieved through
subdividing the interrupt (see tickspernote below).
ubyte tickspernote
This field is an interrupt subdivider, and corresponds directly to the
SET TEMPO command on Noisetracker and other formats. This specifies
the number of "ticks" (interrupts) that must elapse after procesing a
note event before processing the next note event.
ubyte iterations
Specifies the default number of iterations to play thge song for. A
value of 0 means to repeat the song endlessly. This value can be
overridden by commands embedded in the note events (eg, a REPEAT
command at the end of the song with a repeat count of 0 (loop forever)
may cause the song to loop forever even though the iterations field
here says to play the song only once.
ubyte numchannels
This field indicates the number of audio channels this song uses. It
must have a value of 1 or greater. The value here also specifies the
number of CSEQ chunks (channel sequence arrays) that are defined in
this TRSG chunk.
ubyte flags
This flags field currently has no defined bits, but could have flags
indicating such things as fading the song out on the last iteration of
play (via reducing the global volume of the song), among other things.
FIXED volume
Specifies the global volume at which the piece is to be played.
Implementing this may require appropriately re-scaling the default
volumes of the intruments. This means that it is rather important to
keep track of the original instrument default volumes in their
unit-value forms (ie, FIXED format, 0..1).
char songname[]
This is the title of this song.
CSEQ chunk - Required
A CSEQ chunk is simply an array of pattern numbers to play for a given
audio channel. The first CSEQ chunk in a TRSG chunk corresponds to audio
channel #0, the next one corresponds to channel #1, etc. The number of
CSEQ chunks in the TRSG chunk must match the number specified by the
"numchannels" parameter in the SGHD (song header) chunk. These pattern
number arrays should be ordered such that the most important CSEQ's appear
first. This is because future Amiga platforms will support more than the
current 4 audio channels. FORM TRKR songs that take advantage of more
channels will still be able to be played on an older 4-channel platform,
with the extra CSEQ chunks being ignored.
The CSEQ chunk's array consists of any number of word elements. Each
element refers to a pattern array (see PATT chunk below) to play for a
given audio channel. Pattern numbers are derived from the order of PATT
chunks in the FORM TRKR (ie, the first PATT chunk in the file is pattern
#0, then next PATT chunk is pattern #1, etc).
MRKR chunk - Optional
The MRKR (ie, marker) chunk records a specific global position in the song.
It is used by any embedded song commands that cause a change in the
position of the song (eg, the REPEAT command). These position-control
commands specify the new position in the song by referring to one of these
markers. Since patterns can be any length at all, there is no gaurantee
that new patterns will start in all audio channels at the same time.
Rather, new patterns can start in any audio channel at any time.
Therefore, the MRKR chunks exist so that, prior to playing the song, a
player program can process each MRKR chunk and precalculate positions in
the song (since some markers may result in a position in the middle of an
arbitrary pattern).
The fields of the MRKR chunk are as follows:
ulong noteoffset
This specifies where in the song the marker lies as an offset in note
events from the beginning of the song. Calculating the exact position
of a marker involves examining (for each CSEQ chunk in the song) all
pattern numbers and the length in notes of those patterns. It is then
necessary to calculate an offset into the corresponding CSEQ array, as
well as an offset into the pattern to the precise position of the
marker. This must be done for each audio channel (each CSEQ chunk) that
will be used prior to playing a song. This is a rather tedious thing to
be doing on-the-fly, so pre-calculating these offsets is much more
desirable.
ubyte register
This is the register number of the marker. It is by this number that
all embedded song commands reference a given marker. Each marker in a
TRSG chunk must have a unique register number, but they can be re-used
in successive TRSG chunks in the FORM TRKR if so desired.
char markername[]
This is the name of the marker. Some music editors may wish to allow
users to reference markers by name rather than number (which may get
somewhat confusing with multiple songs in memory). It can be left out
if desired, since the name is only meaningful to an editor and not used
by a simple player program (a player program would reference markers by
their register number).
==============================
TINS chunk - Required
The TINS chunk (Tracker INStrument) defines the nature and parameters of an
instrument, and may optionally contain the actual instrument data (eg, it may
optionally include a FORM 8SVX).
If the actual instrument data is not contained within the TINS chunk, then
the IFF loader program will have to go to disk (or other medium) to acquire
the instrument data. I'm not sure if it's considered good form to embed a
FORM 8SVX within a TINS chunk. I suspect it's not, but I've done it anyway.
The TINS chunk contains the following required TIHD (Tracker Instrument
HeaDer) chunk:
TIHD chunk - Required
This header chunk desribes the parameters of an instrument. It contains
the following fields:
ubyte register
Contains the register number of this instrument. Instruments are
referenced from within the song by this number, and so each
instrument's register number must be unique, and in the range 1..63
inclusive.
ubyte type
This specifies the type of the instrument (ie, the nature of the
instrument's data). A type of 0 means that the instrument is an IFF
FORM 8SVX sample. A type of 1 means that the instrument is a MIDI
instrument. No extra values for the type field have been defined thus
far. A type not understood by a player should cause the player to
either ignore all references to that instrument, or the player could
have default instruments prepared to replace those that are defined but
not understood.
FIXED volume
This is the default volume of this instrument in FIXED format (ie, a
"unit-value" fixed-point integer in the range 0..1). It should be
scaled appropriately based on the global volume of any song that uses
it (eg, if global volume is 48, then this FIXED value represents a value
from 0..48, where unity is represented by 48).
ubyte data1
If the "type" field is 1, then this field contains the MIDI channel #
to be used for this intrument.
ubyte data2
If "type" = 1, then this field contains the MIDI preset # to be used
for this instrument.
char instname[]
This is the name of the instrument. If the instrument data itself (eg,
a FORM 8SVX) is not included in the TINS chunk, then this name field
can contain a filename to be used to search for the instrument data
elsewhere. Editors and player programs should have the facility to
search various user-defined paths for such instruments. No path should
*ever* be specified in the instname[] field. Only the filename of the
instrument data.
Optional instrument data chunk (eg, IFF 8SVX)
Optionally, the actual instrument data chunk can appear here as part of the
TINS chunk. The presence of instrument data can be determined by examining
the number of bytes in the TINS chunk less the size of the TIHD chunk
inside it (ie, the entire TIHD chunk, including ID field and size field).
My goals in creating this new IFF format have been:
- To resolve timing conflicts between PAL and NTSC Amiga systems by
standardizing tempo and timing.
- To redesign the note event format to allow greater flexibility and
expandability for future enhancements and extensions to the format.
- To provide a specification for support of IFF 8SVX samples that contain
data for up to three octaves.
- And finally, to try to combine the best features of many of the popular
module formats so that as many different formats as possible can be
converted to the new IFF tracker format.
NOTE EVENT DESIGN AND LAYOUT
----------------------------
I have redesigned the structure of a note event to allow for greater
flexibility and expandability. The note event no longer contains
Amiga-specific period values to represent note pitch, but has been changed to
a note number in the range 0..127. This is to facilitate support for MIDI
instruments in the future. Standard tracker module period values map into
this range as 1..36 inclusive (a note number of 0 means no note is to be
played). Players that support five-octave 8SVX instruments can extend the
range of notes to 1..60 (five octaves).
The note event allows specification of up to 63 different commands, with
as many as 12 bits of operand available for each command. Also, up to 63
instruments can be specified.
The note event is a longword value. Its bits are allocated as follows:
High word of note event:
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Bit #31 |n6|n5|n4|n3|n2|n1|n0|i5|i4|i3|i2|i1|i0|c5|c4|c3| Bit #16
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Low word of note event:
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Bit #15 |c2|c1|c0|oC|oB|oA|o9|o8|o7|o6|o5|o4|o3|o2|o1|o0| Bit #0
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Bit descriptions of the note event:
Bits n0-n7: Contains the note number to play, which is a value from 0..127
inclusive. For simple, one octave 8SVX instruments, only values
from 1..36 are used (1..60 for 5-octave 8SVX insts, and the entire
range can be used for future MIDI support. To determine the
octave at which to play the note (0, 1, or 2), simply subtract 1
and divide the result by 12. The remainder of this division gives
you the note to play relative to this octave. If the note number
field is 0, then no note is to be played.
Notes are allocated as follows (for 1-octave 8SVX):
Amiga
Octave Note Period value
0 C 856
0 C# 808
0 D 762
0 D# 720
0 E 678
0 F 640
0 F# 604
0 G 570
0 G# 538
0 A 508
0 A# 480
0 B 453
1 C 428
1 C# 404
1 D 381
1 D# 360
1 E 339
1 F 320
1 F# 302
1 G 285
1 G# 269
1 A 254
1 A# 240
1 B 226
2 C 214
2 C# 202
2 D 190
2 D# 180
2 E 170
2 F 160
2 F# 151
2 G 143
2 G# 135
2 A 127
2 A# 120
2 B 113
Bits i0-i5: Specifies a new instrument to use. If this value is 0, then no new
instrument is to be selected. Otherwise, it is an instrument
register number from 1..63 inclusive (instrument register numbers
start at 1, not 0) that specifies a new instrument to be selected.
Note that the new instrument is not to be actually played at this
time unless a note number has been specified, or if an included
command says otherwise.
Bits c0-c5: Specifies a command to be executed. A value of 0 means no command
is to be executed. A value of 1..63 specifies a command to be
executed (commands themselves are discussed further on).
Bits o0-oC: This is the operand field used by the various commands supported
by FORM "TRKR". Although this is a thirteen-bit field, some
commands may not use the entire twelve bits for their operand.
Also, other commands may partition the field if they require more
than a single input operand. Typically, signed operands use only
the lowest eight bits of the operand field, since it's a bit (pun
not intended) of a pain to have to sign-extend a thirteen-bit
field.
Command Specification for IFF FORM "TRKR"
-----------------------------------------
As a result of certain features of this file format, certain commands from
tracker-style module file formats have become obsolete. For example, the
"Pattern Break" command is no longer needed, as patterns can be any length at
all. "Pattern Break" was required in tracker-style formats because patterns
were always 64 note events long. If composing a song in 3/4 time (typically
using only the first 48 notes in a pattern) then the "Pattern Break" was
required to skip past the remaining unused note events in the 64-note pattern.
In order to fully describe the function of each command, it is necessary to
break down the commands into categories.
First of all, a "tick" refers to the occurrence of the player interrupt.
The player interrupt occurs on every tick, but it only processes the next note
event in the current pattern on every nth tick (where n is determined by the
current "ticks per note" setting).
The "tick" that occurs in which a new note event is fetched shall
henceforth be referred to as the "note tick".
Some commands are simply processed once on the note tick (ie, as soon as
they are fetched). A good example would be the "Set Channel Volume" command,
which modifies the current volume of an audio channel immediately. The
command is then finished.
Other commands stay active for longer periods of time. For example, the
"Arpeggio" command must play three notes cyclicly in an audio channel. It
starts playing these notes on the note tick that the command was found, and
plays a different note (of the three notes) on *every* tick after that, until
the next note tick.
I will do my best to explain how each command works in detail in this
section, including possible suggestions for implementation in a player
program.
First, a summary of the commands with a brief description of each, along
with each command's number:
Command Summary
Cmd # Name Description
0 No Command No command.
1 Arpeggio Play a three-note arpeggio.
2 Pitch Bend Raise/lower current note pitch on every tick.
3 One-Time Pitch Bend Raise/lower pitch by specified amount once only.
4 Portamento Slide from cur. pitch up/down to specified note.
5 Vibrato Apply vibrato on current note.
6 Portamento+Volume Bend Slide from cur. note to new note with volume bend.
7 Vibrato+Volume Bend Apply vibrato to current note with volume bend.
8 Tremolo Apply tremolo to current note.
9 Set Sample Offset Set data start offset for current instrument.
10 Volume Bend Bend current channel volume up or down.
11 One-Time Volume Bend Up Increase volume by specified amount.
12 One-Time Volume Bend Down Decrease volume by specified amount.
13 Set Volume Set this channel's volume to a specified value.
14 Set Filter Turn low-pass filter on/off.
15 Set Ticks Per Note Set new ticks/note (aka "Tempo").
16 Set Ticks Per Minute Set ticks/minute (range 700-6000, 3000 = 50Hz).
17 Restart Note Restart note n ticks from now.
18 Delay Note Delay playing this note for n ticks.
19 Cut-off Note Cut off current note n ticks from now.
20 Pause Suspend play at this position for n note events.
21 Repeat Repeat from specified marker n times.
22 Glissando Control Turn Glissando on/off for this channel.
23 Set Vibrato Waveform Select vibrato waveform type.
24 Set Tremolo Waveform Select tremolo waveform type.
I must thank you for taking the time to review what I have come up with so
far. I would greatly appreciate your opinion on the various design issues and
solutions I have raised throughout this document.
This is the IFF FORM "TRKR" documentation as it stands at the moment. The
next draft of this proposal will include detailed specs on each note-event
command, as well as a section concerning memory representation of an IFF TRKR
file.
Darren Schebek
Full Tilt Entertainment
5620 Sherwood Blvd.
Delta, B.C.
CANADA
V4L-2C5
usenet: [email protected]