-----------------------------------------------------------------------------
        MED/OctaMED MMD0 and MMD1 file formats
        written by Teijo Kinnunen (25.4.1992)
        Revision 1
-----------------------------------------------------------------------------

Background
----------
A  couple of years ago, when programming MED V2.1, I needed a file format for
MED  modules.   The  only  "module"  format  in  MED V2.0 was the Sng+samples
format.  Although it produced compact files, it was very difficult and tricky
to  read  in.  Therefore, I designed a new file format, that would be easy to
use  in  module  player programs etc.  This file format was named 'MMD0' (Med
MoDule  0).   The  limitations in MMD0 block format forced me to create a new
file format for OctaMED Professional, this format is 'MMD1'.  It's mostly the
same  as  MMD0, except the block structure is different.  At the time of this
writing  (when  OctaMED  Pro is not even released yet), MMD0's are absolutely
more common than MMD1's.

Design concepts
---------------
One  of  the  main  goals  was  to  make MMD's (MED modules) as extensible as
possible.   This  would  have  been  easy to implement with IFF-style chunks.
However, this method is obviously not the best for play-routine use.

Therefore, MMD's are implemented in quite an extraordinary way.  They consist
of  structures  (similar  to  C  structs),  and  pointers.  In a module file,
pointers  are defined as offsets from the beginning of the module.  This way,
a  particular  structure  can be read just by Seek()'ing using the pointer as
the  offset from the beginning of the file.  When a module has been read into
memory,  it has to be relocated before it can be used (the relocation is done
simply by adding the address of the module to the pointers).

As  with  the  Amiga  OS,  a  MMD  file  does not contain absolute addresses.
There's  a  module  header  structure  at  the  beginning  of the file.  This
structure contains pointers to different parts of the module.  And you *MUST*
use  these pointers.  You may NOT expect that the song structure is at offset
$00000034,  for  example.   Although it usually is, this may change in future
releases.   In  addition,  it's  possible that a structure even doesn't exist
(the  structure  pointer is NULL).  Therefore, you *MUST* check the structure
pointer  before  accessing  the  structure.   Finally, when writing MMD's you
*MUST*  set  undefined/reserved  fields  to  zeros.  More finally, you *MUST*
align  all  structures  to  even  boundaries!  (I forgot the alignment in MED
V3.00 save routine, resulting Guruing modules under some conditions :-(

The module header
-----------------
This  structure must exist at the beginning of each MED module file.  Each of
the structure members are described below.

In  multi-modules,  there  are header structs for each song.  (The subsequent
header  pointers  can  be found from expdata structure.  Multi-modules should
have  the  same  smplarr  pointer  in  every  header.) Older MEDs which don't
recognize  multi-modules  consider a multi-module as an ordinary module (only
the first song is loaded).

The numbers enclosed in /* */ at the beginning of each line are (decimal)
offsets of each member (for assembly programmers).

-----------------------------------------------------------------------------
struct MMD0 {
/* 0 */     ULONG   id;
/* 4 */     ULONG   modlen;
/* 8 */     struct MMD0song *song;
/* 12 */    ULONG   reserved0;
/* 16 */    struct MMD0Block **blockarr;
/* 20 */    ULONG   reserved1;
/* 24 */    struct InstrHdr **smplarr;
/* 28 */    ULONG   reserved2;
/* 32 */    struct MMD0exp *expdata;
/* 36 */    ULONG   reserved3;
/* 40 */    UWORD   pstate;  /* some data for the player routine */
/* 42 */    UWORD   pblock;
/* 44 */    UWORD   pline;
/* 46 */    UWORD   pseqnum;
/* 48 */    WORD    actplayline;
/* 50 */    UBYTE   counter;
/* 51 */    UBYTE   extra_songs; /* number of songs - 1 */
}; /* length = 52 bytes */

-----------------------------------------------------------------------------
id
--
This longword is used to identify the MMD and its version.  Currently defined
MMD  types are MMD0 (0x4D4D4430) and MMD1 (0x4D4D4431).  MMD2 and upwards are
reserved for future versions.

In  multi-modules,  the  following  modules usually contain id MCNT, or MCN1.
The first module always has MMD0 or MMD1 as an id.

modlen
------
This longword contains the length of the entire module.

song
----
Pointer to a MMD0song structure. This structure MUST ALWAYS EXIST!

blockarr
--------
Pointer to a table of block pointers. For example:
    blockarr:  $00003000
            block 0 ptr block 1 ptr block 2 ptr
offset  $00003000:  $00002000,  $00002400,  $00002800 ....

offset  $00002000: block 0 data...
offset  $00002400: block 1 data...
..
The size of the table is MMD0song.numblocks longwords.

smplarr
-------
Pointer to a table of instrument pointers. The size of the table is
MMD0song.songlen longwords. This pointer is zero in OctaMED Pro MMD1 songs.
In this case, OctaMED Pro loads the instruments from disk(s).

expdata
-------
Pointer to an expansion structure.  The expansion structure contains a lot of
extra  information.   The  exp.   structure does not exist in all MMD's.  (Be
sure to check the pointer before using it.)

pstate, pblock, pline, pseqnum, actplayline, counter
----------------------------------------------------
These  are  variables for the play routine.  You can read these fields to get
the  current  song  position  (not all versions of the play routine use these
fields,  however).   When writing a MMD, you should leave all fields to zero,
except the 'actplayline', which ought to be -1 ($FFFF).

extra_songs
-----------
This  field  contains  the  number  of  songs  in  the  current  module.  For
non-multi-modules,  this  is 0.  If there are two songs, extra_songs contains
1, and so on.

reserved0,1,2,3
---------------
Not currently defined. Set to zero.


The song structure (MMD0song)
-----------------------------
This  structure contains the basic information about the song.  It must exist
on every module file.

-----------------------------------------------------------------------------
struct MMD0song {
    struct MMD0sample sample[63];   /* 63 * 8 bytes = 504 bytes */
    UWORD   numblocks;      /* offs: 504 */
    UWORD   songlen;        /* offs: 506 */
    UBYTE   playseq[256];       /* offs: 508 */
    UWORD   deftempo;       /* offs: 764 */
    BYTE    playtransp;     /* offs: 766 */
    UBYTE   flags;          /* offs: 767 */
    UBYTE   flags2;         /* offs: 768 */
    UBYTE   tempo2;         /* offs: 769 */
    UBYTE   trkvol[16];     /* offs: 770 */
    UBYTE   mastervol;      /* offs: 786 */
    UBYTE   numsamples;     /* offs: 787 */
}; /* length = 788 bytes */

-----------------------------------------------------------------------------
sample
------
Contains some basic info about each sample. The structure looks like this:

-----------------------------------------------------------------------------
    struct MMD0sample {
        UWORD rep,replen;   /* offs: 0(s), 2(s) */
        UBYTE midich;       /* offs: 4(s) */
        UBYTE midipreset;   /* offs: 5(s) */
        UBYTE svol;     /* offs: 6(s) */
        BYTE strans;        /* offs: 7(s) */
    };

-----------------------------------------------------------------------------
    rep     repeat start offset, shifted right one bit (as in
            Protracker).
    replen      repeat length, shifted right one bit.
    midich      MIDI channel for current instrument, 0 if not MIDI.
    midipreset  MIDI preset number for current instrument, 0 if no
            preset.
    svol        default volume for current instrument (0 - 64).
    strans      instrument transpose value.

More information is defined in expdata structure.

numblocks
---------
Number  of  blocks  in current song.  This field also indicates the length of
the blockarr table in longwords.

songlen
-------
Song length (number of sequence numbers in the play sequence list).

playseq
-------
This is the play sequence list.

deftempo
--------
Default  song  tempo (the leftmost tempo slider in MED/OctaMED).  If BPM mode
is on, this value indicates BPM.

playtransp
----------
The global play transpose value for current song.

flags
-----
Contains many single-bit flags:
    FLAG_FILTERON   0x1 the hardware audio filter is on
    FLAG_JUMPINGON  0x2 mouse pointer jumping on (not in OctaMED Pro)
    FLAG_JUMP8TH    0x4 jump every 8th line (not in OctaMED Pro)
    FLAG_INSTRSATT  0x8     sng+samples indicator (not useful in MMD's)
    FLAG_VOLHEX 0x10    volumes are HEX
    FLAG_STSLIDE    0x20    use ST/NT/PT compatible sliding
    FLAG_8CHANNEL   0x40    this is OctaMED 5-8 channel song

    (bit 0x80 is not defined, and must be set to zero)

flags2
------
More flags, currently only BPM stuff:
    FLAG2_BMASK 0x1F (bits 0-4)     BPM beat length (in lines)
                        0 = 1 line, $1F = 32 lines.
                    (The rightmost slider in OctaMED Pro
                     BPM mode.)
    FLAG2_BPM   0x20    BPM mode on

    (bits 0x40 and 0x80 are not defined, and must be set to zero)

tempo2
------
This is the "secondary tempo" (the rightmost MED/OctaMED tempo slider),
indicating the number of timing pulses per line.

trkvol[16]
----------
The relative track volumes (1 - 64) for each track.

mastervol
---------
The relative master volume (1 - 64).

numsamples
----------
Number  of instruments (samples/synthsounds) in current song.  Also indicates
the size of the smplarr table in longwords.


The block format
----------------
As  described above, MMD0 header structure contains a pointer (blockarr) to a
table of block pointers.  These block pointers point to the actual block data
structures.  The format of these data structures differ in MMD0 and MMD1 file
formats.

MMD0 block format
-----------------
At the beginning of each block, there's a small header:

-----------------------------------------------------------------------------
    struct MMD0Block {
        UBYTE numtracks,lines;
    };

-----------------------------------------------------------------------------
    numtracks   number of tracks (4, 8, 12 or 16) on this block
    lines       number of lines on this block; 0 = 1 line,
            255 = 256 lines

Following  this  header,  there is the actual note data, consisting of 3-byte
structures  containing  a  note  and  its  command.   The  data  is  arranged
sequentially a line at a time, i.e. in the following order:
    line 0 track 0
    line 0 track 1
    line 0 track 2
    line 0 track 3
    line 1 track 0
    line 1 track 1
    ...
The 3-byte structure looks like this (each letter corresponds to one bit):

    xynnnnnn iiiicccc dddddddd

    n = note number (0 - $3F). 0 = ---, 1 = C-1, 2 = C#1...
    i = the low 4 bits of the instrument number
    x = the 5th bit (#4) of the instrument number
    y = the 6th bit (#5) of the instrument number
    c = command number (0 - $F)
    d = databyte ($00 - $FF)

MMD1 block format
-----------------
MMD1  block format can contain a lot more information than MMD0's.  The block
header looks like this:

-----------------------------------------------------------------------------
    struct MMD1Block {
        UWORD numtracks;
        UWORD lines;
        struct BlockInfo *info;
    };

-----------------------------------------------------------------------------
    numtracks   Number of tracks in this block (4, 8, 12, or 16).
    lines       Number of lines in this block (0 = 1 line etc.).
            OctaMED Pro can handle upto 3200 lines/block, so
            this is obviously the practical upper limit.
    info        Pointer to structure containing extra information.
            (Can be NULL, if no BlockInfo struct exists).

    The BlockInfo structure is:

-----------------------------------------------------------------------------
    struct BlockInfo {
        ULONG   *hlmask;
        UBYTE   *blockname;
        ULONG   blocknamelen;
        ULONG   reserved[6];
    };

-----------------------------------------------------------------------------
    hlmask      Pointer to an array of longwords, containing info
            about line highlighting (TAB key on MED). The number
            of longwords depend on the number of lines on the
            block. (E.g: 1 line -> 1 longword, 32 lines -> 1 lw,
            33 lines -> 2 lws, 256 lines -> 4 lws)
            The bits in the longwords are arranged in reversed
            order (e.g. bit #0 = line 0, bit #31 = line 31).

    blockname   Pointer to the name of the block. Must be null-
            terminated.

    blocknamelen    Length of the block name, including the terminating
            zero. OctaMED Pro currently has the maximum length of
            41 chars (+ zero). However, this may change in the
            future. Don't read blocknames longer than you are
            able to handle!

    reserved[6] These are reserved for future extensions. Must be set
            to zero.

    The note structures, which are 4 bytes long in MMD1 modules, are
    arranged exactly as in MMD0 modules.

        xnnnnnnn xxiiiiii cccccccc dddddddd

    n = note number (0 - $7F, 0 = ---, 1 = C-1...)
    i = instrument number (0 - $3F)
    c = command ($00 - $FF)
    d = databyte ($00 - $FF)
    x = undefined, reserved for future expansion. MUST BE SET TO ZERO,
        AND MASKED OUT WHEN READING THE NOTE OR INSTRUMENT NUMBER.


The instrument format
---------------------
The  MMD0  header  structure  contains  a  pointer  (smplarr)  to  a table of
instrument  pointers.   These  pointers  point  to the actual instrument data
structures.   If an instrument pointer is zero, there's no instrument in that
slot.

Every  instrument  has a six-byte header structure, which is the same for all
instrument types (sample/synth/hybrid).

-----------------------------------------------------------------------------
    struct InstrHdr {
        ULONG   length;
        WORD    type;
        /* Followed by actual data */
    };

-----------------------------------------------------------------------------
    length      indicates the length of the instrument (the six byte
            header data length is not included)
    type        instrument type - currently the following types are
            defined:

        HYBRID      -2
        SYNTHETIC   -1
        SAMPLE      0   (an ordinary 1-octave sample)
        IFF5OCT     1   (5 octaves)
        IFF3OCT     2   (3 octaves)
        (The following ones are recognized by OctaMED Pro only)
        IFF2OCT     3   (2 octaves)
        IFF4OCT     4   (4 octaves)
        IFF6OCT     5   (6 octaves)
        IFF7OCT     6   (7 octaves)

The sample-type instruments (>= 0) contain the actual sample data straight
after the header structure.

Synthetic instruments
---------------------
Synthsounds  have  a  special  structure  of  their  own.   They also contain
waveforms and pointers to them.  Therefore, relocation is required.  However,
there's  an  important  difference:  pointers are expressed as an offset from
the  beginning  of  the  synthsound,  NOT  the  beginning of the module.  The
'reloc.a' routine provided with MED/OctaMED automatically handles this.

The synthsound structure is as follows (note that this structure contains the
header structure):

-----------------------------------------------------------------------------
    struct SynthInstr {
        ULONG   length;     /* length of this struct */
        WORD    type;       /* -1 or -2 (offs: 4) */
        UBYTE   defaultdecay;
        UBYTE   reserved[3];
        UWORD   rep;
        UWORD   replen;
        UWORD   voltbllen;  /* offs: 14 */
        UWORD   wftbllen;   /* offs: 16 */
        UBYTE   volspeed;   /* offs: 18 */
        UBYTE   wfspeed;    /* offs: 19 */
        UWORD   wforms;     /* offs: 20 */
        UBYTE   voltbl[128];    /* offs: 22 */
        UBYTE   wftbl[128]; /* offs: 150 */
        struct  SynthWF *wf[64]; /* offs: 278 */
    };

-----------------------------------------------------------------------------
    defaultdecay    = the default decay of the current synthsound. This
              is NOT used in modules. It's significant only when
              saving a single synthsound.

    reserved[3] = set to zero.

    rep, replen = repeat/rep. length for hybrid sounds. Used only
              when saving a single hybrid sound.

    voltbllen   = the length of the volume sequence table.

    wftbllen    = the length of the waveform sequence table.

    volspeed    = the initial volume table execution speed.

    wfspeed     = the initial waveform table execution speed.

    wforms      = the number of waveforms in the current synthsound.

    voltbl      = the actual volume sequence table. Values $00-$7F
              are volumes or command arguments. Values >= $80 are
              commands. The following commands are currently
              defined:
                $FF END     $F4 EN1
                $FE JMP     $F3 CHU
                $FB HLT     $F2 CHD
                $FA JWS     $F1 WAI
                $F6 EST     $F0 SPD
                $F5 EN2

    wftbl       = the actual waveform sequence table. Values $00-$7F
              are waveform numbers  or command arguments. Values
              >= $80 are commands. The following commands are
              currently defined:
                $FF END     $F6 RES
                $FE JMP     $F5 VBS
                $FD ARE     $F4 VBD
                $FC ARP     $F3 CHU
                $FB HLT     $F2 CHD
                $FA JVS     $F1 WAI
                $F7 VWF     $F0 SPD

    wf      = pointers to waveforms. (Once again: relative to the
              beginning of the synthsound!) A waveform structure
              is as follows:

                struct SynthWF {
                    UWORD length;   /* length in words */
                    BYTE  wfdata[xx]; /* the waveform */
                };

                (where xx = length in bytes)

              In hybrid sounds, however, wf[0] is different.

Hybrid instruments
------------------
Hybrid  sounds  use  the same structure as synthsounds, except that the first
waveform  (wf[0])  pointer  points to a sample.  (The sample header structure
exists, as usual.)


MMD0exp - the key to future expansions
--------------------------------------
For  possible  future  expansions,  I  designed  a structure for carrying the
miscellaneous things that were added to MED/OctaMED now and then.  (MED V3.00
was the first version, which wrote this structure.) Most of its fields are in
use  now,  but it's possible to even expand this structure (things will get a
bit more tricky, though).

In multi-modules, you should extract all data from the expansion structure of
the  first  song.   The  only  exceptions  are  currently  the  'nextmod' and
'songname' fields, which are song-specific.

Also,  there  has  been  need  for  extending the MMD0sample structure.  Both
InstrExt  and  MMDInstrInfo  provide extra information about the instruments.
These  are  defined as structure arrays (exp_smp and iinfo point to the first
structure).  The extension structures don't have a constant size, instead you
have  to  read s_ext_entrsz or i_ext_entrsz to get the structure sizes.  When
reading,  you  have to check the entrsz fields to see which structure members
do exist.

The  difference  between  InstrExt and MMDInstrInfo is that InstrExt contains
information the play-routine is interested in (e.g.  finetune).  MMDInstrInfo
contains  "secondary"  information,  which is of no use to the player routine
(e.g.  instrument name).

The expansion structure follows:

-----------------------------------------------------------------------------
    struct MMD0exp {
        struct MMD0 *nextmod;
        struct InstrExt *exp_smp;
        UWORD  s_ext_entries;
        UWORD  s_ext_entrsz;
        UBYTE  *annotxt;
        ULONG  annolen;
        struct MMDInstrInfo *iinfo;
        UWORD  i_ext_entries;
        UWORD  i_ext_entrsz;
        ULONG  jumpmask;
        UWORD  *rgbtable;
        UBYTE  channelsplit[4];
        struct NotationInfo *n_info;
        UBYTE  *songname;
        ULONG  songnamelen;
        struct MMDDumpData *dumps;
        ULONG  reserved2[7];
    };

-----------------------------------------------------------------------------
    nextmod     = pointer to the next module (or zero). (Only used in
              multi-modules!)

    exp_smp     = pointer to InstrExt. Currently the first four bytes
              of InstrExt have been defined:

                struct InstrExt {
                    UBYTE hold;
                    UBYTE decay;
                    UBYTE suppress_midi_off;
                    BYTE  finetune;
                };

                hold, decay = hold/decay values of the
                          instrument

                suppress_midi_off = 0 (FALSE) or not (TRUE)

                finetune    = instrument finetune (-8-+7)

    s_ext_entries   = the size of InstrExt structure array (i.e. the
              number of InstrExt structures).

    s_ext_entrsz    = the size of each InstrExt structure (in bytes).

    annotxt     = pointer to the annotation text (null-terminated).

    annolen     = length of 'annotxt', including the terminating \0.

    iinfo       = pointer to MMDInstrInfo. Currently the first forty
              bytes have been defined:

                struct MMDInstrInfo {
                    UBYTE   name[40];
                };

                name = null-terminated instrument name

    i_ext_entries   = the size of the MMDInstrInfo struct array (i.e. the
              number of MMDInstrInfo structures).

    i_ext_entrsz    = the size of each MMDInstrInfo struct in bytes.

    jumpmask    = a mask controlling which instruments cause the
              mouse pointer to jump. E.g. bit #1 = instr. #1.
              This field has become obsolete in OctaMED Pro.

    rgbtable    = pointer to eight UWORDs (screen colors) to be
              passed to LoadRGB4() routine.

    channelsplit    = this longword is divided to four boolean bytes,
              controlling channel splitting in OctaMED 5 - 8 chnl
              modes. (A non-zero byte means that the channel is
              NOT splitted.) Currently only the following
              combinations should be used:

              0x00000000 (8 channels (or normal 4 channel mode))
              0x000000FF (7 channels)
              0x0000FFFF (6 channels)
              0x00FFFFFF (5 channels)

    n_info      = pointer to NotationInfo structure (used only in
              OctaMED V2.0 and later). It contains some info for
              the notation editor.

                struct NotationInfo {
                    UBYTE n_of_sharps;
                    UBYTE flags;
                    WORD  trksel[5];
                    UBYTE trkshow[16];
                    UBYTE trkghost[16];
                    BYTE  notetr[63];
                    UBYTE pad;
                };

              n_of_sharps   = number of sharps or flats (0 - 6)
              flags     = misc. bits, these are defined:
                        NFLG_FLAT   1
                    (= use flats instead of sharps)
                        NFLG_3_4    2
                    (= display 12 lines instead of 16)

              trksel    = the number of the selected track,
                      for each display preset
                        (-1 = no track selected)

              trkshow   = tracks shown (five bits used in
                      each byte, bit #0 = preset 1, etc.)

              trkghost  = tracks ghosted (as in 'trkshow')

              notetr    = note transpose value for each
                      instrument (-24 - +24). If bit 6 is
                      negated, the instrument is hidden.

              pad       = possibly holding info about struct
                      expansions in the future. Don't
                      touch!

    songname    = song name of the current song (0-terminated).
              Each song of a multi-module can have a different
              name.

    songnamelen = song name length (including the terminating zero).

    dumps       = MIDI dump data (created using OctaMED Pro MIDI
              message editor). The 'dumps' field points to the
              following struct:

                struct MMDDumpData {
                    UWORD   numdumps;
                    UWORD   reserved[3];
                };

              Immediately after this struct, there are 'numdumps'
              pointers to the following struct:

                struct MMDDump {
                    ULONG   length;
                    UBYTE   *data;
                    UWORD   ext_len;
                    /* if ext_len >= 20: */
                    UBYTE   name[20];
                };

              length    = length of the MIDI message dump.

              data      = pointer to the actual MIDI dump
                      data.

              ext_len   = MMDDump struct extension length.
                      For flexible future expansion.

              (if ext_len >= 20, the following fields exist)

              name      = name of the dump.

    reserved2   = future expansion fields, that MUST be zero now.

-----------------------------------------------------------------------------
Finally, here is a collection of the most important rules you should obey
when handling MMD's:

    * ALWAYS USE POINTERS, NOT ABSOLUTE OFFSETS.

    * CHECK THAT A POINTER IS NONZERO BEFORE ACCESSING ANYTHING IT
      POINTS TO.

    * WHEN WRITING, SET UNDEFINED/RESERVED BITS AND BYTES TO ZERO.
      WHEN READING, MASK OUT UNDEFINED BITS, AND DON'T USE UNDEFINED
      FIELDS.

    * WHEN WRITING, ALWAYS ALIGN EVERYTHING TO EVEN BOUNDARIES.

    * WHEN WRITING, ALWAYS WRITE THE SONG STRUCTURE.

    * REMEMBER TO HANDLE ERROR SITUATIONS CORRECTLY (IN ALL PROGRAMS,
      NOT ONLY WHEN HANDLING MMDs ;^)

If  you  don't  understand  some  part  of this file completely, try saving a
module using MED, and then examine the file with a file editor.  This way you
can learn easily about the file format of MED/OctaMED.

-----------------------------------------------------------------------------

I  hope this document will help programmers who wish to be able to handle
modules  in  their  programs.   NOTE! This text file is PUBLIC DOMAIN. All
distribution of this file,via the pd is strongly encouraged.  Thank you!

    Teijo Kinnunen
    Oksantie 19
    SF-86300  OULAINEN
    FINLAND

----------------------------------------------------------------------------


+-------------------------------------------------------------------+
|+-----------------------------------------------------------------+|
||             MED V3.2 player commands/effects                    ||
|+-----------------------------------------------------------------+|
+-------------------------------------------------------------------+

This  section  gives  information  about  commands/effects.  They are events
which affect the playing and they are handled by the MED player routine.

         C - 2  1 2 3 4
                  | \ |
     command number  \|
                      data byte

You insert the commands usually by hand (turn editing on, move cursor on the
command  numbers  and type the numbers).  It may be a bit easier if you turn
off automatic-advance with Ctrl-A.

Here are the descriptions of each of the currently recognized commands:


+---------------------------------------------------+
| Command 0:  ARPEGGIO       MIDI: controller value |
+---------------------------------------------------+

This command changes the pitch of the note quickly (6 times during 1 note).
It can be used to create "chords" or special effects. If you've listened
to music made with the C-64, you MUST have heard arpeggios. The pitch is
changed between 3 different pitches during one note:
         the 1st pitch is the pitch of the original note
         the 2nd pitch is the pitch of the original note + the 1st number
                of databyte halfsteps up
         the 3rd pitch is the pitch of the original note + the 2nd number
                of databyte halfsteps up

Note: 3rd pitch | 2nd pitch | 1st pitch | 3rd pitch | 2nd pitch | 1st pitch
      changed 6 times during note

It may be a bit difficult to understand, so here's an example:
You want to make an arpeggio which sounds like C-major chord.

The lowest pitch is C (C-2 in this example).
The second is E-2 (4 halfsteps higher than C-2).
The third is G-2 (7 halfsteps higher than C-2).

4 halfsteps from C-2 -+ 7 halfsteps from C-2
                      |/
That produces:  C-2 1047
                --- 0047
                --- 0047 and so on...

Data byte for a minor chord would be 37.

The arpeggios sound better with some instruments than others.

MIDI: See command 5 for a description.

+---------------------------------------------------+
| Command 1:  SLIDE UP       MIDI: pitchbender up   |
+---------------------------------------------------+

This command slides up the pitch of the current track.

With Amiga samples:
         Decreases the period of the note the amount of databyte on each
         timing pulse. Sounds rather technical?? Yes... The instructions for
         previous (before 2.10) versions of MED contained detailed
         instructions for making good-sounding slides with this command.
         Because this version now contains the easy automatic slide making
         (Amiga-T), I felt that these instructions are not necessary any more.
         If you use this function for special effects (not real slides) then
         you can experiment with the values for the databyte.
         Example:
                A-1 1000
                --- 0000
                --- 010F <- slide up a bit

With MIDI:
         This commands works very differently with MIDI. It actually
         "turns" the pitchbender 8 * databyte steps up on each timing pulse.
         Because the actual range of the pitchbender may be different with
         different MIDI-devices, you must find the right value by
         experimenting. There's also one thing you should know: when a new
         note is played, the pitchbender is not resetted automatically. To
         reset the pitchbender, you use this command with databyte zero.
         Example:
                G-2 L1FF <-turn it up very quick
                --- 0000
                --- 0100 <- then reset the pitchbender


+---------------------------------------------------+
| Command 2:  SLIDE DOWN     MIDI: pitchbender down |
+---------------------------------------------------+

Not much about this command. It's just like command 1 except it slides
down.


+---------------------------------------------------+
| Command 3:  PORTAMENTO     MIDI: set pitchbender  |
+---------------------------------------------------+

This is another slide command (on some old MED versions (2.00) this
was a vibrato command, see command 5 now). It can be used to
make perfect slides more easily. First an example:

         C-2 5000 <- played note C
         --- 0000
         E-2 5305 <- this note is not played!! Instead, slide target is set
         --- 0300    to G-2 and slide speed is 5
         --- 0300 <- when speed is zero, use the previous speed
         --- 0306 <- the speed can be changed, of course

This example would slide from C-2 to E-2, but the slide stops EXACTLY
when E-2 is reached. The remaining 3's have no effect. This command
is easier to handle with automatic slide making (see Edit/S1 above).

MIDI: By using this command, you can set the pitchbender to an absolute
value, instead of sliding as commands 1 and 2 do. The data byte is the
pitchbender value, expressed as a signed hexadecimal digit (a nightmare
to non-programmers!).
        00 = center position
        80 (-7F) = smallest value
        7F = largest value

Example:
        C-2 3000
        --- 037F <- pitchbender to max. value
        --- 0300 <- reset


+---------------------------------------------------+
| Command 4:  VIBRATO        MIDI: modulation wheel |
+---------------------------------------------------+

The first number of the data byte is vibrato speed, the second is
vibrato depth. If the numbers are zeros, the previous speed and depth
is used.

Example: F-215000
         --- 0000
         --- 0433 <- slow, not much depth
         --- 0437 <- more depth
         --- 043F <- full depth
         --- 0482 <- fast, not very deep

MIDI: This command affects the modulation wheel of the current channel.
      The data byte can be 00 - 7F. 00 = no modulation, 7F = maximum.
      Values 80 - FF are reserved for future expansion (and won't work).


+---------------------------------------------------+
| Command 5:  OLD VIBRATO    MIDI: controller number|
+---------------------------------------------------+

This is the old vibrato command (previously it was 3). The command 3 is
automatically converted to 5 when loading old MED songs. The pitch of
the note is changed between two values, databyte is the depth.

Example: A#1 J502
         --- 0507 increasing depth
         --- 0517 v
         --- 0527
         --- 0537

MIDI: Command 5 in conjunction with command 0 allows you to change any
controller of MIDI (command $Bx cc vv, where cc = controller number,
vv = value).

First you set the number of controller you want to change with command
5. Then you can select the value with command 0. Subsequent uses of
command 0 will affect the controller previously set with command 5.
Each channel has its own controller number. If the controller value is
$00, you can't use '00', because the command '000' means 'do nothing'.
Instead, you type '80'. Acceptable controller numbers and values are
$00 - $7F.

For example: (assuming instrument 3 is set to MIDI channel 1)
        C-2 3000
        --- 0507 <- controller $07, volume, according to MIDI standard
        D-2 307F <- set max. volume ($7F), command $B0 $07 $7F is sent
        --- 0000
        F-3 3001 <- small volume ($01)
        --- 055C <- select controller $5C (tremolo depth)
        G-4 3080 <- set to 0 (note: $80 = $00)

+---------------------------------------------------+
| Command 8:  SET HOLD/DECAY MIDI: set hold only    |
+---------------------------------------------------+

This command must be located on the same line with a note. The command
assigns the hold and decay values for the note (see above for description
about hold/decay).

                hold value
decay----------+|
               ||
Example: C-3 3824
         -|- 3000
         -|- 3000
         --- 0000

+---------------------------------------------------+
| Command 9:  SEC. TEMPO     MIDI: no action        |
+---------------------------------------------------+

This command sets the secondary tempo (the number of timing pulses/note).
The argument must be 01 - 20.

Example: --- 0903 <= double tempo
         --- 0000

+---------------------------------------------------+
| Command A:  VOLUME SLIDE   MIDI: polyph aftertouch|
+---------------------------------------------------+

This is the same as command D (for Noise/Protracker compatibility).
However, please use D instead of this. If I some day find that there
are no free commands, I'll use this!!

MIDI: Command A changes the polyphonic aftertouch of the most recent note.
The value should be $00 - $7F.
Example:
        C-3 4000
        --- 0A30 <- aftertouch $30
        --- 0000
        --- 0A00 <- aftertouch $00

+---------------------------------------------------+
| Command B:  POSITION JUMP  MIDI: position jump    |
+---------------------------------------------------+

This command lets you make songs that have beginning which is played
only once and then some part which is looped forever. Position jump
causes the jump to playsequence number pointed by the data byte. If the
data byte is 0, then the playseq jumps to the first entry.

Example:	--- 0B02 <- start playing from playsequence number 3

+---------------------------------------------------+
| Command C:  SET VOLUME     MIDI: set volume       |
+---------------------------------------------------+

You can override the default volume of the instrument with this command.
Example:
         A-3 4C20 <- played with volume 20

There are 65 volume levels (0 - 64), 0 = no sound, 64 = maximum. The
data byte of command C can be 00 - 64 or 00 - 40 (decimal or hex).
Non-programmers will probably want to use the decimal numbers. See
(Play/[Dec/Hex]). If you want the playroutine to have maximum performance,
then use hex values.

It is also possible to change the volume of already played note. Note
that it doesn't work with MIDI-instruments.

Example:
         A-3 4000
         --- 0000
         --- 0C10 <- volume to 10

It's possible to change the default volume of an instrument (MED V2 and
later). The value must be between 80 and C0 (always hex!). Value $80 = volume
0, and $C0 = 64. Note: This can cause trouble in multi-modules, because the
set of instruments (and their default volumes) are common. I recommend that
you change the default volume only on non-multi-modules.

+---------------------------------------------------+
| Command D:  VOLUME SLIDE   MIDI: channel pressure |
+---------------------------------------------------+

You can increase/decrease volume smoothly with this command. The data
byte is divided in two parts:

         C-3 3D01
               ||
               |+- Amount of decresdendo
               +-- Amount of crescendo

If crescendo is zero, then the decrescendo is performed. Otherwise only
crescendo is performed.

Example:
         C-2 3C40
         --- 0D01 <- a bit more quiet
         --- 0D01 <- even more
         --- 0D20 <- and crescendo back to original

One unit in these commands means six actual volume units, so this example
would look like this, when using the C-command (except that it doesn't
sound so smooth):
         C-2 3C40 (volumes are decimal in this example)
         --- 0C34 <- -6
         --- 0C28 <- -6
         --- 0C40 <- +12

MIDI: This command sends a channel pressure (channel aftertouch) message
using the channel in which the most recent note was sent. The databyte
should be $00 - $7F.
         D#5 J000
         --- 0D40 <- channel aftertouch $40
         --- 0D00 <- to $00

+---------------------------------------------------+
| Command E:  SYNTH/JMP      MIDI: pan control      |
+---------------------------------------------------+

When used with synth/hybrid instruments, this command triggers a jump
in the waveform command sequence. The databyte is the jump destination
(line number).

Example: C-4 4000 <- this should be synth/hybrid instrument
         --- 0000
         --- 0E05 <- cause a jump to line # 5

With MIDI-instruments, this command controls the stereo location of the
sound. The data byte can be 00 - 7F.

        left           mid            right
         |              |               |
        00             3F               7F

If you've used MED V2.00/V2.01 or Noise/SoundTracker, you may remember
that this command controlled the low-pass filter. I think that it was
unnecessary to spend the command E only for controlling only a single
switch. See command F.

+---------------------------------------------------+
| Command F:  TEMPO/MISC.    MIDI: tempo/misc.      |
+---------------------------------------------------+

Command F has many different actions depending on the data byte.

If the data byte is zero (00), this command causes the immediate jumping
to the next block on the playing sequence (or to the beginning of this
block if you're only playing the block). This function is better to
implement by making the block shorter (takes less memory).

Example:
         C-2 4F00 <- this is the last note of this block

When the data byte if 01 - F0, the command changes the tempo. This is the
primary tempo (length of the pause between timing pulses).

If the new tempo is 01 - 0A, it is compatible with Trackers, but now you
should use the command 9 instead of this command, as it's directly
Tracker-compatible (set the primary tempo to 33).

Example:
         E-3 6FF0 <- highest tempo
         --- 0000
         --- 0F0B <- slowest

Data bytes FF1 - FFF are reserved for special actions, some of them
are currently used:

FF1 causes the same note played actually twice. This way it's possible
to create fast rhythms.

         C-3 2FF1 is same as C-3 2000
                             C-3 2000 with double tempo

FF2 plays the note only once, but it is not started immediately:

         C-3 2FF2 is same as --- 0000
                             C-3 2000 with double tempo

FF3 works like FF1 except the note is played three times (very fast).

FF8 turns off the low-pass filter (power-LED will dim).

FF9 turns the low-pass filter on (bright LED).

FFA sends MIDI "hold pedal on"-command (works only with MIDI-instruments).

FFB sends MIDI "hold pedal off"-command (works only with MIDI-instruments).

FFD works only with Amiga-samples. It causes the pitch of the channel to
    be set to the pitch of the new note, but the new note is not replayed.

         C-1 2000 <- play note
         --- 0000
         C-2 2FFD <- don't replay the note, just set the pitch to C-2

FFE stops playing immediately. If you want to make a song which plays only
    once, put this command to the end of the song. This command can be
    easily entered: Click "Stop playing" while holding the Shift-key.

FFF Stops the note on the current track. Works with both Amiga- and MIDI-
    instruments. Nearly identical to "C00" on Amiga-samples, but because
    "C00" doesn't work with MIDI, I made this command.
