Copyright (c) Hyperion Entertainment and contributors.

TRKR IFF Tracker Music Module

From AmigaOS Documentation Wiki
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: dschebek@outb.wimsey.bc.ca


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: dschebek@outb.wimsey.bc.ca