Ad Lib, January 1989
--------------------

The .INS instrument files have been grouped together to create a .BNK (bank)
file.  The purpose of this is to save space.  DOS will allocate 1K of space
for a file regardless of how small the file actually is.  So the bank file
saves a significant amount of space.

We are currently modifying our software to use the .BNK file instead of
.INS files.  The new software versions will all be numbered 1.5 and will
not support the old .INS files.  However, a utility will be provided to
convert between the two formats.  The default name for the bank file is
STANDARD.BNK although any name may be used as long as the file extension
is .BNK.

The .BNK file a basically a collection of the old .INS file structures (as
shown in Appendix C of the Programmer's Manual) with the waveform added to
the end.


Structure of .BNK files
-----------------------

FIELD#  SIZE-bytes  TYPE        DESCRIPTION

								HEADER
1       1           char        file version, major
2       1           char        file version, minor
3       6           char        signature: "ADLIB-"
4       2           unsigned    number of list entries used
5       2           unsigned    total number of list entries in file
6       4           long        absolute offset in file of start of name list
7       4           long        absolute offset in file of start of data
8       8           char        filler (set to zero)

								INSTRUMENT NAME SECTION RECORD
1       2           unsigned    index into data section
2       1           char        flag: 0 if this record is not used, else 1
3       9           char        instrument name (max 8 char + NULL)

								DATA SECTION RECORD
1       1           char        mode (0=melodic, 1=percussive)
2       1           char        voice number (if percussive mode)
3       13          char        modulator (operator 0) parameters
4       13          char        carrier (operator 1) parameters
5       1           char        wave form for modulator
6       1           char        wave form for carrier


There is one header at the very beginning of the file.  Field #6 in the
header is the absolute offset of the start of the instrument name section.

The instrument name section contains a list of records which contain the
instrument name, a flag and a pointer to the data section.  Header field #5
gives the total number of records in this list, although not all of these
records may be in use.  Header field #4 gives the number of name records which
are actually being used.  The records in use will be placed at the beginning
of the section and will be arranged alphabetically by instrument name.

The data section contains the records of instrument parameters.  One of these
records is equivalent to the .INS file structure, except that the 2-byte
fields are now 1-byte long.  Two more bytes have been added for the wave
form type for each operator.

So, to read an instrument from the new bank file:
1. Read the header.
2. Use header field #6 to do a seek to the start of the instrument name
   section.
3. Search the name section for the desired name.  (The search is delimited
   by header field #4.)
4. When found, get its index into the data section (name field #1).
5. Calculate the address where the data for this instument will be found:
	  header_field_#7 + (index * sizeof_data_record)
6. Do a seek to the calculated address and read the data.


Notes
-----

The instrument names are alphabetically arranged so that you are not limited
to using a linear search method.  A binary search would be appropriate.

If you are going to be creating or deleting an instrument, you must preserve
the alphabetical order of instrument names.  However, the data section is
not neccesarily ordered.  When adding data, you can find the data record
to use from the index pointer from the first unused instrument name
record.

The unused instrument name records are not empty: the pointers into the data
section are valid and are used when adding instruments.  When expanding the
instrument name section, field #1 must be initialized to a valid value.
(In this case, the data section must be shifted down and header field #7
must be adjusted accordingly.)  The purpose of having empty name records is
to avoid having to rewrite the entire file every time an instrument is added.


C Structures
------------
The following are C structures which correspond to the information
given above.


/* Instrument bank file header */
typedef struct {
   char      majorVersion;
   char      minorVersion;
   char      sig [6];            /* signature: "ADLIB-" */
   unsigned  nrDefined;          /* number of list entries used */
   unsigned  nrEntry;            /* number of total entries in list */
   long      offsetIndex;        /* offset in file of start of name list */
   long      offsetTimbre;       /* offset in file of start of data */
   char      filler [8];         /* must be zero */
} BankHeader;


/* Name of instrument with a pointer to its position in the file */
typedef struct {
   unsigned nrReference;       /* index into data section */
   char  usedFlag;             /* 0 if this entry is not used */
   char  TimbreName [9];       /* max 8 char's + NULL */
} BankEntry;


/* Operator structure */
typedef struct {
   char  ksl;
   char  freqMult;
   char  feedBack;              /* used by operator 0 only */
   char  attack;
   char  sustLevel;
   char  sustain;
   char  decay;
   char  release;
   char  output;
   char  am;
   char  vib;
   char  ksr;
   char  fm;                    /* used by operator 0 only */
} Operator;


typedef struct {
	char      mode;
	char      percVoice;
	Operator  op0;
	Operator  op1;
	char      wave0;            /* wave form for operator 0 */
	char      wave1;            /* wave form for operator 1 */
} PackedTimbre;