@DATABASE Devices Manual
@NODE MAIN " A / Third Party Public FORM and Chunk Specifications "
@INDEX Dev_Index/MAIN
@TOC Dev_A_3rd_Party_Form/MAIN

@{" 0000.CSET.doc " link 0000.CSET.doc}      @{" ANIM.brush.doc " link ANIM.brush.doc}     @{" ILBM.DPI.doc " link ILBM.DPI.doc}  @{" RGBN-RGB8.doc " link RGBN-RGB8.doc}
@{" 0000.FVER.doc " link 0000.FVER.doc}      @{" ANIM.doc " link ANIM.doc}           @{" ILBM.DPPV.doc " link ILBM.DPPV.doc} @{" SAMP.doc " link SAMP.doc}
@{" 8SVX.CHAN.PAN.doc " link 8SVX.CHAN.PAN.doc}  @{" DR2D.doc " link DR2D.doc}           @{" ILBM.DRNG.doc " link ILBM.DRNG.doc} @{" TDDD.doc " link TDDD.doc}
@{" 8SVX.SEQN.FADE.doc " link 8SVX.SEQN.FADE.doc} @{" FANT.doc " link FANT.doc}           @{" ILBM.EPSF.doc " link ILBM.EPSF.doc} @{" WORD.doc " link WORD.doc}
@{" ACBM.doc " link ACBM.doc}           @{" HEAD.doc " link HEAD.doc}           @{" MTRX.doc " link MTRX.doc}
@{" AIFF.doc " link AIFF.doc}           @{" ILBM.CLUT.doc " link ILBM.CLUT.doc}      @{" PGTB.doc " link PGTB.doc}
@{" ANBM.doc " link ANBM.doc}           @{" ILBM.CTBL.DYCP.doc " link ILBM.CTBL.DYCP.doc} @{" PRSP.doc " link PRSP.doc}

@ENDNODE

@NODE 0000.CSET.doc "A / IFF Third Party Public Form and Chunk Specification / 0000.CSET.doc"
Chunk for specifying character set

Registered by Martin Taillefer.

A chunk for use in any FORM, to specify character set used for text in
FORM.

   struct CSet {
           LONG    CodeSet;       /* 0=ECMA Latin 1 (std Amiga charset) */
           LONG    Reserved[7];   /* CBM will define additional values  */
           }

@ENDNODE


@NODE 0000.FVER.doc "A / IFF Third Party Public Form and Chunk Specification / 0000.FVER.doc"
Chunk for 2.0 VERSION string of an IFF file

Registered by Martin Taillefer.

A chunk for use in any FORM, to contain standard 2.0 version string.

$VER: name ver.rev

where "name" is the name or identifier of the file and ver.rev is a
version/revision such as 37.1

Example:

$VER: workbench.catalog 37.42

@ENDNODE


@NODE 8SVX.CHAN.PAN.doc "A / IFF Third Party Public Form and Chunk Specification / 8SVX.CHAN.PAN.doc"
Stereo chunks for 8SVX form

                     SMUS.CHAN and SMUS.PAN Chunks
            Stereo imaging in the "8SVX" IFF 8-bit Sample Voice
            ---------------------------------------------------
                 Registered by David Jones, Gold Disk Inc.

There are two ways to create stereo imaging when playing back a digitized
sound. The first relies on the original sound being created with a stereo
sampler: two different samples are digitized simultaneously, using right
and left inputs. To play back this type of sample while maintaining the
stereo imaging, both channels must be set to the same volume. The second
type of stereo sound plays the identical information on two different
channels at different volumes. This gives the sample an absolute position
in the stereo field. Unfortunately, there are currently a number of
methods for doing this currently implemented on the Amiga, none truly
adhering to any type of standard. What I have tried to to is provide a way
of doing this consistently, while retaining compatibility with existing
(non-standard) systems. Introduced below are two optional data chunks,
CHAN and PAN. CHAN deals with sounds sampled in stereo, and PAN with
samples given stereo characteristics after the fact.

@{" Optional Data Chunk CHAN " link 8SVX-1}
@{" Optional Data Chunk PAN " link 8SVX-2}


@ENDNODE

@NODE 8SVX-1 "8SVX.CHAN.PAN.doc / Optional Data Chunk CHAN "
This chunk is already written by the software for a popular stereo
sampler. To maintain the ability read these samples, its implementation
here is therefore limited to maintain compatability.

The optional data chunk CHAN gives the information neccessary to play a
sample on a specified channel, or combination of channels. This chunk
would be useful for programs employing stereo recording or playback of
sampled sounds.

    #define RIGHT           4L
    #define LEFT            2L
    #define STEREO          6L

    #define ID_CHAN MakeID('C','H','A','N')

    typedef sampletype LONG;

If "sampletype" is RIGHT, the program reading the sample knows that it was
originally intended to play on a channel routed to the right speaker,
(channels 1 and 2 on the Amiga). If "sampletype" is LEFT, the left speaker
was intended (Amiga channels 0 and 3). It is left to the discretion of the
programmer to decide whether or not to play a sample when a channel on the
side designated by "sampletype" cannot be allocated.

If "sampletype" is STEREO, then the sample requires a pair of channels
routed to both speakers (Amiga pairs [0,1] and [2,3]). The BODY chunk for
stereo pairs contains both left and right information. To adhere to
existing conventions, sampling software should write first the LEFT
information, followed by the RIGHT. The LEFT and RIGHT information should
be equal in length.

Again, it is left to the programmer to decide what to do if a channel for
a stereo pair can't be allocated; wether to play the available channel
only, or to allocate another channels routed to the wrong speaker.

@ENDNODE


@NODE 8SVX-2 "8SVX.CHAN.PAN.doc / Optional Data Chunk PAN "
The optional data chunk PAN provides the neccessary information to create
a stereo sound using a single array of data. It is neccessary to replay
the sample simultaneously on two channels, at different volumes.

    #define ID_PAN MakeID('P','A','N',' ')

    typedef sposition Fixed; /* 0 <= sposition <= Unity */

    /* Unity is elsewhere #defined as 10000L, and
     * refers to the maximum possible volume.
     * /

    /* Please note that "Fixed" (elsewhere #defined as LONG) is used to
     * allow for compatabilty between audio hardware of different
     * resolutions.
     * /

The "sposition" variable describes a position in the stereo field. The
numbers of discrete stereo positions available is equal to 1/2 the number
of discrete volumes for a single channel.

The sample must be played on both the right and left channels. The overall
volume of the sample is determined by the "volume" field in the
Voice8Header structure in the VHDR chunk.

The left channel volume = overall volume / (Unity / sposition).
 "  right   "       "   = overall volume - left channel volume.

For example:
	If sposition = Unity, the sample is panned all the way to the left.
	If sposition = 0, the sample is panned all the way to the right.
	If sposition = Unity/2, the sample is centered in the stereo field.

@ENDNODE


@NODE 8SVX.SEQN.FADE.doc "A / IFF Third Party Public Form & Chunk Specification / 8SVXSEQN.FADE.doc"
Looping chunks for 8SVX form

                          SEQN and FADE Chunks

       Multiple Loop Sequencing in the '8SVX' IFF 8-bit Sample Voice
       -------------------------------------------------------------
           Registered by Peter Norman, RamScan Software Pty Ltd.

Sound samples are notorious for demanding huge amounts of memory.

While earlier uses of digital sound on the Amiga were mainly in the form
of short looping waveforms for use as musical instruments, many people
today wish to record several seconds (even minutes) of sound. This of
course eats memory.

Assuming that quite often the content of these recordings is music, and
that quite often music contains several passages which repeat at given
times, "verse1 .. chorus ..  verse2 .. chorus .." etc, a useful extention
has been added to the 8SVX list of optional data chunks. It's purpose is
to conserve memory by having the computer repeat sections rather than
having several instances of a similar sound or musical passage taking up
valuable sample space.

The 'SEQN' chunk has been created to define "Multiple" loops or sections
within a single octave 8SVX MONO or STEREO waveform.

It is intended that a sampled sound player program which supports this
chunk will play sections of the waveform sequentially in an order that the
SEQN chunk specifies. This means for example, if an identical chorus
repeats throughout a recording, rather than have this chorus stored
several times along the waveform, it is only necessary to have one copy of
the chorus stored in the waveform.

A "SEQeNce" of definitions can then be set up to have the computer loop
back and repeat the chorus at the required time. The remaining choruses
stored in the waveform will no longer be necessary and can be removed.

E.g., if we had a recording of the following example, we would find that
there are several parts which simply repeat. Substantial savings can be
made by having the computer repeat sections rather than have them stored
in memory.

@{" EXAMPLE " link 8SVXSEQ-1}
@{" Chunk Definitions " link 8SVXSEQ-2}

@ENDNODE


@NODE 8SVXSEQ-1 " 8SVXSEQN.FADE.doc / EXAMPLE "
"Haaaallelujah....Haaaallelujah...Hallelujah..Hallelujah..
Halleeeelujaaaah."

Applying a sequence to the above recording would look as follows.

Haaaallelujah....Haaaallelujah...Hallelujah..Hallelujah..Halleeeelujaaaah.
[     Loop1     ]
[     Loop2     ]
                                 [  Loop3   ]
                                 [  Loop4   ]
                                                         [     Loop5     ]
                [   Dead Space   ]          [ Dead Space ]

The DEAD SPACE can be removed. With careful editing of the multiple loop
positions, the passage can be made to sound exactly the same as the
original with far less memory required.

@ENDNODE


@NODE 8SVXSEQ-2 " 8SVXSEQN.FADE.doc / Chunk Definitions "

@{" Optional Data Chunk SEQN " link 8SVXSEQ-2-1}
@{" Optional Data Chunk FADE " link 8SVXSEQ-2-2}

@ENDNODE


@NODE 8SVXSEQ-2-1 " 8SVXSEQN.FADE.doc / Optional Data Chunk SEQN "
The optional data chunk SEQN gives the information necessary to play a
sample in a sequence of defined blocks. To have a segment repeat twice,
the definition occurs twice in the list.

This list consists of pairs of ULONG "loop start" and "end" definitions
which are offsets from the start of the waveform. The locations or values
must be LONGWORD aligned (divisable by 4).

To determine how many loop definitions in a given file, simply divide the
SEQN chunk size by 8.

E.g., if chunk size == 40 ... number of loops = (40 / 8) .. equals 5 loops.

The raw data in a file might look like this...

'S-E-Q-N' [ size ] [     Loop 1    ] [     Loop 2    ] [     Loop 3    ]

 5345514E 00000028 00000000 00000C00 00000000 00000C00 00000C08 00002000
             ^
             ^     'Haaaallelujah..' 'Haaaallelujah..'   'Hallelujah..'
             ^
             ^
             40 bytes decimal / 8 = 5 loop or segments


      [     Loop 4    ] [    Loop 5     ]'B-O-D-Y'   Size     Data

      00000C08 00002000 00002008 00003000 424F4459 000BE974 010101010101010

        'Hallelujah..'  'Halleeeelujah..'


In a waveform containing SEQN chunks, the oneShotHiSamples should be set
to 0 and the repeatHiSamples should equal the BODY length (divided by 2 if
STEREO).

Remember the locations of the start and end of each segment or loop should
be LONGWORD aligned.

If the waveform is Stereo, treat the values and locations in exactly the
same way. In other words, if a loop starts at location 400 within a Stereo
waveform, you start the sound at the 400th byte position in the left data
and the 400th byte position in the right data simultaneously.

	#define ID_SEQN MakeID('S','E','Q','N')

@ENDNODE


@NODE 8SVXSEQ-2-2 " 8SVXSEQN.FADE.doc / Optional Data Chunk FADE "
The FADE chunk defines at what loop number the sound should begin to fade
away to silence. It is possible to finish a sample of music in much the
same way as commercial music does today. A FADE chunk consists of one
ULONG value which has a number in it. This number corresponds to the loop
number at which the fade should begin.

eg. You may have a waveform containing 50 loops. A FADE definition of 45
will specify that once loop 45 is reached, fading to zero volume should
begin. The rate at which this fade takes place is determined by the length
of time left to play. The playing software should do a calculation based
on the following...

Length of all remaining sequences including current sequence (in bytes)

divided by

the current playback rate in samples per second

= time remaining.

Begin stepping the volume down at a rate which will hit zero volume just
as the waveform finishes.

The raw data in a file may look like this.


 'F-A-D-E'  [ Size ]   Loop No.  'B-O-D-Y'   Size   Data..

  46414445  00000004   0000002D   424F4459 000BE974 01010101 01010101 etc
                          ^
                          Start fading when loop number 45 is reached.


	#define ID_FADE MakeID('F','A','D','E')

Although order shouldn't make much difference, it is a general rule of
thumb that SEQN should come before FADE and FADE should be last before the
BODY.

Stereo waveforms would have CHAN,SEQN,FADE,BODY in that order.

@ENDNODE


@NODE ACBM.doc "A / IFF Third Party Public Form and Chunk Specification / ACBM.doc"
Amiga Contiguous Bitmap form

                IFF FORM / CHUNK DESCRIPTION

Form/Chunk ID:   FORM  ACBM  (Amiga Contiguous BitMap)
                 Chunk ABIT  (Amiga BITplanes)

Date Submitted:  05/29/86
Submitted by:    Carolyn Scheppner   CBM

@{" FORM " link ACBM-1}
@{" Chunk " link ACBM-2}
@{" Supporting Software " link ACBM-3}

@ENDNODE


@NODE ACBM-1 "ACBM.doc / FORM "
FORM ID:  ACBM  (Amiga Contiguous BitMap)

FORM Description:

FORM ACBM has the same format as FORM ILBM except the normal BODY chunk
(InterLeaved BitMap) is replaced by an ABIT chunk (Amiga BITplanes).

FORM Purpose:

To enable faster loading/saving of screens, especially from Basic, while
retaining the flexibility and portability of IFF format files.

@ENDNODE


@NODE ACBM-2 "ACBM.doc / Chunk "
Chunk ID:   ABIT  (Amiga BITplanes)

Chunk Description:

The ABIT chunk contains contiguous bitplane data.  The chunk contains
sequential data for bitplane 0 through bitplane n.

Chunk Purpose:

To enable loading/storing of bitmaps with one DOS Read/Write per bitplane.
Significant speed increases are realized when loading/saving screens from
Basic.

@ENDNODE


@NODE ACBM-3 "ACBM.doc / Supporting Software "
(Public Domain, available soon via Fish PD disk, various networks)

LoadILBM-SaveACBM (AmigaBasic)
   Loads and displays an IFF ILBM pic file (Graphicraft, DPaint, Images).
   Optionally saves the screen in ACBM format.

LoadACBM (AmigaBasic)
   Loads and display an ACBM format pic file.

SaveILBM (AmigaBasic)
   Saves a demo screen as an ILBM pic file which can be loaded into
   Graphicraft, DPaint, Images.

@ENDNODE


@NODE AIFF.doc "A / IFF Third Party Public Form and Chunk Specification / AIFF.doc"
Audio 1-32 bit samples (Mac,AppleII,Synthia Pro)

provided by Steve Milne and Matt Deatherage, Apple Computer, Inc.


           AIFF: Audio Interchange File Format File

The Audio Interchange File Format (Audio IFF) provides a standard for
storing sampled sounds.  The format is quite flexible, allowing the
storage of monaural or multichannel sampled sounds at a variety of sample
rates and sample widths.

Audio IFF conforms to the "EA IFF 85: Standard for Interchange Format
Files" developed by Electronic Arts.

Audio IFF is primarily an interchange format, although application
designers should find it flexible enough to use as a data storage format
as well.  If an application does choose to use a different storage format,
it should be able to convert to and from the format defined in this
document.  This ability to convert will facilitate the sharing of sound
data between applications.

Audio IFF is the result of several meetings held with music developers
over a period of ten months during 1987 and 1988.  Apple Computer greatly
appreciates the comments and cooperation provided by all developers who
helped define this standard.

Another "EA IFF 85" sound storage format is "8SVX IFF 8-bit Sampled
Voice", by Electronic Arts.  '8SVX', which handles eight-bit monaural
samples, is intended mainly for storing sound for playback on personal
computers.  Audio IFF is intended for use with a larger variety of
computers, sampled sound instruments, sound software applications, and
high fidelity recording devices.

@{" Data Types " link AIFF-1}                            @{" The Marker Chunk " link AIFF-10}
@{" Constants " link AIFF-2}                             @{" The Instrument Chunk " link AIFF-11}
@{" Data Organization " link AIFF-3}                     @{" The MIDI Data Chunk " link AIFF-12}
@{" Referring to Audio IFF " link AIFF-4}                @{" Audio Recording Chunk " link AIFF-13}
@{" File Structure " link AIFF-5}                        @{" Application Specific Chunk " link AIFF-14}
@{" Storage of AIFF on Other Platforms " link AIFF-6}    @{" The Comments Chunk " link AIFF-15}
@{" Local Chunk Types " link AIFF-7}                     @{" Text Chunks " link AIFF-16}
@{" Sample Points and Sample Frames " link AIFF-8}       @{" Chunk Precedence " link AIFF-17}
@{" Block Aligning Sound Data " link AIFF-9}             @{" Further Reference " link AIFF-18}

@ENDNODE


@NODE AIFF-1 "AIFF.doc / AIFF / Data Types "
A C-like language will be used to describe the data structures in this
document The data types used are listed below.

char:          8 bits signed.  A char can contain more than just ASCII
               characters.  It can contain any number from -128 to 127
               (inclusive).
unsigned char: 8 bits signed. Contains numbers from 0 to 255 (inclusive).
short:         16 bits signed.  Contains any number from -32,768 to 32,767
               (inclusive).
unsigned short:16 bits unsigned.  Contains any number from 0 to 65,535
               (inclusive).
long:          32 bits signed. Contains any number from -2,147,483,648
               to 2,147,483,647 (inclusive).
unsigned long: 32 bits unsigned. Contains any number from 0 to
               4,294,967,295 (inclusive).
extended:      80 bit IEEE Standard 754 floating point number (Standard
               Apple Numeric Environment [SANE] data type Extended)
pstring:       Pascal-style string, a one-byte count followed by text
               bytes.  The total number of bytes in this data type should
               be even.  A pad byte can be added to the end of the text to
               accomplish this.  This pad byte is not reflected in the
               count.
ID:            32 bits,the concatenation of four printable ASCII characters
               in the range ' ' (space, 0x20) through '~' (tilde, 0x7E).
               Leading spaces are not allowed in the ID but trailing spaces
               are OK.  Control characters are forbidden.

@ENDNODE


@NODE AIFF-2 "AIFF.doc / AIFF / Constants "
Decimal values are referred to as a string of digits, for example 123, 0,
100 are all decimal numbers.  Hexadecimal values are preceded by a 0x -
e.g., 0x0A, 0x1, 0x64.

@ENDNODE


@NODE AIFF-3 "AIFF.doc / AIFF / Data Organization "
All data is stored in Motorola 68000 format.  The bytes of multiple-byte
values are stored with the high-order bytes first.  Data is organized as
follows:

                7  6  5  4  3  2  1  0
	      +-----------------------+
	char: | msb              lsb  |
	      +-----------------------+

               15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
	      +-----------------------+-----------------------+
	char: | msb    byte 0         |        byte 1     lsb |
	      +-----------------------+-----------------------+

               15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
	      +-----------------------+-----------------------+
	char: | msb    byte 0         |        byte 1         |
	      +-----------------------+-----------------------+
	char: |        byte 2         |        byte 3     lsb |
	      +-----------------------+-----------------------+

		Figure 1: IFF data storage formats

@ENDNODE


@NODE AIFF-4 "AIFF.doc / AIFF / Referring to Audio IFF "
The official name for this standard is Audio Interchange File Format.  If
an application program needs to present the name of this format to a user,
such as in a "Save As..." dialog box, the name can be abbreviated to Audio
IFF. Referring to Audio IFF files by a four-letter abbreviation (i.e.,
'AIFF') in user-level documentation or program-generated messages should
be avoided.

@ENDNODE


@NODE AIFF-5 "AIFF.doc / AIFF / File Structure "
The "EA IFF 85 Standard for Interchange Format Files" defines an overall
structure for storing data in files.  Audio IFF conforms to those portions
of "EA IFF 85" that are germane to Audio IFF.  For a more complete
discussion of "EA IFF 85", please refer to the document "EAIFF 85,
Standard for Interchange Format Files."

An "EA IFF 85" file is made up of a number of chunks of data.  Chunks are
the building blocks of "EA IFF 85" files.  A chunk consists of some header
information followed by data:

		+--------------------+
		|       ckID         |\
		+--------------------+ } header info
	        |      ckSize        |/
		+--------------------+
        	|                    |
        	|                    |
        	|       data         |
        	|                    |
        	|                    |
		+--------------------+

	      Figure 2: IFF Chunk structure

A chunk can be represented using our C-like language in the following
manner:

    typedef struct {
	ID		ckID;		/* chunk ID		*/
	long		ckSize;		/* chunk Size		*/

	char		ckData[];	/* data			*/
	} Chunk;

The ckID describes the format of the data portion of a chunk.  A program
can determine how to interpret the chunk data by examining ckID.

The ckSize is the size of the data portion of the chunk, in bytes.  It
does not include the 8 bytes used by ckID and ckSize.

The ckData contains the data stored in the chunk.  The format of this data
is determined by ckID.  If the data is an odd number of bytes in length, a
zero pad byte must be added at the end.  The pad byte is not included in
ckSize.

Note that an array with no size specification (e.g., char ckData[];)
indicates a variable-sized array in our C-like language.  This differs
from standard C.

An Audio IFF file is a collection of a number of different types of
chunks. There is a Common Chunk which contains important parameters
describing the sampled sound, such as its length and sample rate.  There
is a Sound Data Chunk which contains the actual audio samples.  There are
several other optional chunks which define markers, list instrument
parameters, store application-specific information, etc.  All of these
chunks are described in detail in later sections of this document.

The chunks in an Audio IFF file are grouped together in a container chunk.
"EA IFF 85" Standard for Interchange Format Files  defines a number of
container chunks, but the one used by Audio IFF is called a FORM.  A FORM
has the following format:

    typedef struct {
	ID	ckID;
	long	ckSize;
	ID	formType;
	char	chunks[];
    }

The ckID is always 'FORM'.  This indicates that this is a FORM chunk.

The ckSize contains the size of data portion of the 'FORM' chunk.  Note
that the data portion has been broken into two parts, formType and
chunks[].

The formType field describes what's in the 'FORM' chunk.  For Audio IFF
files, formType is always 'AIFF'.  This indicates that the chunks within
the FORM pertain to sampled sound.  A FORM chunk of formType 'AIFF' is
called a FORM AIFF.

The chunks field are the chunks contained within the FORM.  These chunks
are called local chunks.  A FORM AIFF along with its local chunks make up
an Audio IFF file.

Here is an example of a simple Audio IFF file.  It consists of a file
containing single FORM AIFF which contains two local chunks, a Common
Chunk and a Sound Data Chunk.

                        __________________________
                      | FORM AIFF Chunk          |
                      |   ckID  = 'FORM'         |
                      |   formType = 'AIFF'      |
                      |    __________________    |
                      |   | Common Chunk     |   |
                      |   |   ckID = 'COMM'  |   |
                      |   |__________________|   |
                      |    __________________    |
                      |   | Sound Data Chunk |   |
                      |   |   ckID = 'SSND'  |   |
                      |   |__________________|   |
                      |__________________________|

                     Figure 3: Simple Audio IFF File

There are no restrictions on the ordering of local chunks within a FORM
AIFF.

A more detailed example of an Audio IFF file can be found in Appendix A.
Please refer to this example as often as necessary while reading the
remainder of this document.

@ENDNODE


@NODE AIFF-6 "AIFF.doc / AIFF / Storage of AIFF on Apple and Other Platforms "
On a Macintosh, the FORM AIFF, is stored in the data fork of an Audio IFF
file. The Macintosh file type of an Audio IFF file is 'AIFF'.  This is the
same as the formType of the FORM AIFF.  Macintosh applications should not
store any information in Audio IFF file's resource fork, as this
information may not be preserved by all applications.  Applications can
use the Application Specific Chunk, defined later in this document, to
store extra information specific to their application.

Audio IFF files may be identified in other Apple file systems as well.  On
a Macintosh under MFS or HFS, the FORM AIFF is stored in the data fork of
a file with file type 'AIFF'.  This is the same as the formType of the
FORM AIFF.

On an operating system such as MS-DOS or UNIX, where it is customary to
use a file name extension, it is recommended that Audio IFF file names use
'.AIF' for the extension.

On an Apple II, FORM AIFF is stored in a file with file type $D8 and
auxiliary type $0000.  Versions 1.2 and earlier of the Audio IFF standard
used file type $CB and auxiliary type $0000.  This is incorrect; the
assignment listed in this document is the correct assignment.

On the Apple IIGS stereo data is stored with right data on even channels
and left data on odd channels.  Some portions of AIFF do not follow this
convention.  Even where it does follow the convention, AIFF usually uses
channel two for right data instead of channel zero as most Apple IIGS
standards do.  Be prepared to interpret data accordingly.

@ENDNODE


@NODE AIFF-7 "AIFF.doc / AIFF / Local Chunk Types "
The formats of the different local chunk types found within a FORM AIFF
are described in the following sections, as are their ckIDs.

There are two types of chunks:  required and optional.  The Common Chunk
is required.  The Sound Data chunk is required if the sampled sound has a
length greater than zero.  All other chunks are optional.  All
applications that use FORM AIFF must be able to read the required chunks
and can choose to selectively ignore the optional chunks.  A program that
copies a FORM AIFF should copy all the chunks in the FORM AIFF, even those
it chooses not to interpret.

@{" The Common Chunk " link AIFF-7-1}
@{" Sound Data Chunk " link AIFF-7-2}

@ENDNODE


@NODE AIFF-7-1 " AIFF / Local Chunk Types / The Common Chunk "
The Common Chunk describes fundamental parameters of the sampled sound.

    #define	CommonID	'COMM'	/* ckID for Common Chunk */

    typedef struct {
	ID		ckID;
	long		ckSize;

	short		numChannels;
	unsigned long	numSampleFrames;
	short		sampleSize;
	extended	sampleRate;
    } CommonChunk;

The ckID is always 'COMM'.  The ckSize is the size of the data portion of
the chunk, in bytes.  It does not include the 8 bytes used by ckID and
ckSize. For the Common Chunk, ckSize is always 18.

The numChannels field contains the number of audio channels for the sound.
A value of 1 means monophonic sound, 2 means stereo, and 4 means four
channel sound, etc.  Any number of audio channels may be represented.  For
multichannel sounds, single sample points from each channel are
interleaved. A set of interleaved sample points is called a sample frame.

The actual sound samples are stored in another chunk, the Sound Data
Chunk, which will be described shortly.

Single sample points from each channel are interleaved such that each
sample frame is a sample point from the same moment in time for each
channel available.

The numSampleFrames field contains the number of sample frames.  This is
not necessarily the same as the number of bytes nor the number of
samplepoints in the Sound Data Chunk.  The total number of sample points
in the file is numSampleFrames times numChannels.

The sampleSize is the number of bits in each sample point.  It can be any
number from 1 to 32.  The format of a sample point will be described in
the next section.

The sampleRate field is the sample rate at which the sound is to be played
back in sample frames per second.

One, and only one, Common Chunk is required in every FORM AIFF.

@ENDNODE


@NODE AIFF-7-2 " AIFF / Local Chunk Types / Sound Data Chunk "
The Sound Data Chunk contains the actual sample frames.

    #define 	SoundDataID	'SSND'	/* ckID for Sound Data Chunk 	*/

    typedef struct {
	ID		ckID;
	long		ckSize;

	unsigned long	offset;
	unsigned long	blockSize;
	unsigned char	SoundData [];
    }  SoundDataChunk;

The ckID is always 'SSND'.  The ckSize is the size of the data portion of
the chunk, in bytes.  It does not include the 8 bytes used by ckID and
ckSize.

The offset field determines where the first sample frame in the soundData
starts.  The offset is in bytes.  Most applications won't use offset and
should set it to zero.  Use for a non-zero offset is explained in the
Block-Aligning Sound Data section below.

The blockSize is used in conjunction with offset for block-aligning sound
data.  It contains the size in bytes of the blocks that sound data is
aligned to.  As with offset, most applications won't use blockSize and
should set it to zero.  More information on blockSize is in the
Block-Aligning Sound Data section below.

The soundData field contains the sample frames that make up the sound.
The number of sample frames in the soundData is determined by the
numSampleFrames field in the Common Chunk.  Sample points and sample
frames are explained in detail in the next section.

The Sound Data Chunk is required unless the numSampleFrames field in the
Common Chunk is zero.  A maximum of one Sound Data Chunk may appear in a
FORM AIFF.

@ENDNODE


@NODE AIFF-8 "AIFF.doc / AIFF / Sample Points and Sample Frames "
A large part of interpreting Audio IFF files revolves around the two
concepts of sample points and sample frames.

A sample point is a value representing a sample of a sound at a given
point in time.  Each sample point is stored as a linear, 2's-complement
value which may be from 1 to 32 bits wide, as determined by sampleSize in
the Common Chunk.

Sample points are stored in an integral number of contiguous bytes.  One-
to eight-bit wide sample points are stored in one byte, 9- to 16-bit wide
sample points are stored in two bytes, 17- to 24-bit wide sample points
are stored in three bytes, and 25- to 32-bit wide sample points are stored
in four bytes (most significant byte first).  When the width of a sample
point is not a multiple of eight bits, the sample point data is left
justified, with the remaining bits zeroed.  An example case is illustrated
in Figure 4.  A 12-bit sample point, binary 101000010111, is stored left
justified in two bytes. The remaining bits are set to zero.

     ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___
    |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
    | 1   0   1   0   0   0   0   1 | 0   1   1   1   0   0   0   0 |
    |___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|
     <---------------------------------------------> <------------->
          12 bit sample point is left justified         rightmost
                                                        4 bits are
                                                        zero padded
                      Figure 4: 12-Bit Sample Point

For multichannel sounds, single sample points from each channel are
interleaved.  A set of interleaved sample points is called a sample frame.
Single sample points from each channel are interleaved such that each
sample frame is a sample point from the same moment in time for each
channel available.  This is illustrated in Figure 5 for the stereo (two
channel) case.

                   sample      sample              sample
                   frame 0     frame 1             frame N
                 _____ _____ _____ _____         _____ _____
                | ch1 | ch2 | ch1 | ch2 | . . . | ch1 | ch2 |
                |_____|_____|_____|_____|       |_____|_____|
                             _____
                            |     | = one sample point
                            |_____|

                Figure 5: Sample Frames for Multichannel Sound

For monophonic sound, a sample frame is a single sample point.  For
multichannel sounds, you should follow the conventions in Figure 6.

                                       channel
               1          2          3          4          5          6
             _________ _________ _________ _________ _________ _________
            | left    | right   |         |         |         |         |
  stereo    |         |         |         |         |         |         |
            |_________|_________|_________|_________|_________|_________|
            | left    | right   | center  |         |         |         |
  3 channel |         |         |         |         |         |         |
            |_________|_________|_________|_________|_________|_________|
            | front   | front   | rear    | rear    |         |         |
  quad      | left    | right   | left    | right   |         |         |
            |_________|_________|_________|_________|_________|_________|
            | left    | center  | right   | surround|         |         |
  4 channel |         |         |         |         |         |         |
            |_________|_________|_________|_________|_________|_________|
            | left    | left    | center  | right   | right   |surround |
  6 channel |         | center  |         |         | center  |         |
            |_________|_________|_________|_________|_________|_________|

             Figure 6: Sample Frame Conventions for Multichannel Sound

Sample frames are stored contiguously in order of increasing time.  The
sample points within a sample frame are packed together; there are no
unused bytes between them.  Likewise, the sample frames are packed
together with no pad bytes.

@ENDNODE


@NODE AIFF-9 "AIFF.doc / AIFF / Block-Aligning Sound Data "
There may be some applications that, to ensure real time recording and
playback of audio, wish to align sampled sound data with fixed-size
blocks. This alignment can be accomplished with the offset and blockSize
parameters of the Sound Data Chunk, as shown in Figure 7.

        ____________ __________________________________ ____________
       |\\ unused \\|          sample frames           |\\ unused \\|
       |____________|__________________________________|____________|
       <-- offset --><- numSampleFrames sample frames ->

    |   blockSize   |               |               |               |
    |<- bytes     ->|               |               |               |
    |_______________|_______________|_______________|_______________|
       block N-1       block N         block N+1       block N+2

                     Figure 7: Block-Aligned Sound Data

In Figure 7, the first sample frame starts at the beginning of block N.
This is accomplished by skipping the first offset bytes of the soundData.
Note too, that the soundData bytes can extend beyond valid sample frames,
allowing the soundData bytes to end on a block boundary as well.

The blockSize specifies the size in bytes of the block to which you would
align the sound data.  A blockSize of zero indicates that the sound data
does not need to be block-aligned.  Applications that don't care about
block alignment should set the blockSize and offset to zero when creating
Audio IFF files.  Applications that write block-aligned sound data should
set blockSize to the appropriate block size.  Applications that modify an
existing Audio IFF file should try to preserve alignment of the sound
data, although this is not required.  If an application does not preserve
alignment, it should set the blockSize and offset to zero.  If an
application needs to realign sound data to a different sized block, it
should update blockSize and offset accordingly.

@ENDNODE


@NODE AIFF-10 "AIFF.doc / AIFF / The Marker Chunk "
The Marker Chunk contains markers that point to positions in the sound
data. Markers can be used for whatever purposes an application desires.
The Instrument Chunk, defined later in this Note, uses markers to mark
loop beginning and end points.

@{" Markers " link AIFF-10-1}
@{" Marker Chunk Format " link AIFF-10-2}

@ENDNODE


@NODE AIFF-10-1 "AIFF / The Marker Chunk / Markers "
A marker has the following format.

    typedef	short		MarkerId;

    typedef	struct	{
		MarkerID	id;
		unsigned long	position;
		pstring		markerName;
    } Marker;

The id is a number that uniquely identifies that marker within a FORM
AIFF. The id can be any positive non-zero integer, as long as no other
marker within the same FORM AIFF has the same id.

The marker's position in the sound data is determined by the position
field. Markers conceptually fall between two sample frames.  A marker that
falls before the first sample frame in the sound data is at position zero,
while a marker that falls between the first and second sample frame in the
sound data is at position 1.  Note that the units for position  are sample
frames, not bytes nor sample points.

                              Sample Frames
             ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___
            |   |   |   |   |   |   |   |   |   |   |   |   |
            |___|___|___|___|___|___|___|___|___|___|___|___|
            ^                   ^                           ^
        position 0          position 5                  position 12

                 Figure 8: Sample Frame Marker Positions

The markerName field is a Pascal-style text string containing the name of
the mark.

Note: Some "EA IFF 85" files store strings a C-strings (text bytes
followed by a null terminating character) instead of Pascal-style strings.
Audio IFF uses pstrings because they are more efficiently skipped over
when scanning through chunks.  Using pstrings, a program can skip over a
string by adding the string count to the address of the first character.
C strings require that each character in the string be examined for the
null terminator.

@ENDNODE


@NODE AIFF-10-2 "AIFF / The Marker Chunk / Marker Chunk Format "
The format for the data within a Marker Chunk is shown below.

    #define	MarkerID 	'MARK'	/* ckID for Marker Chunk */

    typedef  struct {
	ID				ckID;
	long				ckSize;

	unsigned short		numMarkers;
	Marker			Markers [];
    } MarkerChunk;

The ckID is always 'MARK'.  The ckSize is the size of the data portion of
the chunk in bytes.  It does not include the 8 bytes used by ckID and
ckSize.

The numMarkers field is the number of markers in the Marker Chunk.  If
numMarkers is non-zero, it is followed by the markers themselves.  Because
all fields in a marker are an even number of bytes, the length of any
marker will always be even.  Thus, markers are packed together with no
unused bytes between them.  The markers need not be ordered in any
particular manner.

The Marker Chunk is optional.  No more than one Marker Chunk can appear in
a FORM AIFF.

@ENDNODE


@NODE AIFF-11 "AIFF.doc / AIFF / The Instrument Chunk "
The Instrument Chunk defines basic parameters that an instrument, such as
a sample, could use to play the sound data.

@{" Looping " link AIFF-11-1}
@{" The Instrument Chunk Format " link AIFF-11-2}

@ENDNODE


@NODE AIFF-11-1 "AIFF / The Instrument Chunk / Looping "
Sound data can be looped, allowing a portion of the sound to be repeated
in order to lengthen the sound.  The structure below describes a loop.

    typedef struct {
	short	PlayMode;
	MarkerId beginLoop;
	MarkerId endLoop;
    } Loop;

A loop is marked with two points, a begin position and an end position.
There are two ways to play a loop, forward looping and forward/backward
looping. In the case of forward looping, playback begins at the beginning
of the sound, continues past the begin position and continues to the end
position, at which point playback starts again at the begin position.  The
segment between the begin and end positions, called the loop segment, is
played repeatedly until interrupted by a user action, such as the release
of a key on a sampling instrument.

                   ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ ___
    sample frames |   |   |   |<--- loop segment ---->|   |   |   |
                  |___|___|___|___|___|___|___|___|___|___|___|___|
                              ^                       ^
                        begin position           end position

                        Figure 9: Sample Frame Looping

With forward/backward looping, the loop segment is first played from the
begin position to the end position, and then played backwards from the end
position to the begin position.  This flip-flop pattern is repeated over
and over again until interrupted.

The playMode specifies which type of looping is to be performed:

	#define NoLooping		0
	#define ForwardLooping		1
	#define ForwardBackwardLooping  2

If NoLooping is specified, then the loop points are ignored during
playback.

The beginLoop is a marker id that marks the begin position of the loop
segment.

The endLoop marks the end position of a loop.  The begin position must be
less than the end position.  If this is not the case, then the loop
segment has zero or negative length and no looping takes place.

@ENDNODE


@NODE AIFF-11-2 "AIFF / The Instrument Chunk / The Instrument Chunk Format "
The format of the data within an Instrument Chunk is described below.

   #define             InstrumentID  'INST' /*ckID for Instruments Chunk */

   typedef struct {
       ID              ckID;
       long            ckSize;

       char            baseNote;
       char            detune;
       char            lowNote;
       char            highNote;
       char            lowvelocity;
       char            highvelocity;
       short           gain;
       Loop            sustainLoop;
       Loop            releaseLoop;
   } InstrumentChunk;

The ckID is always 'INST'.  ckSize is the size of the data portion of the
chunk, in bytes.  For the Instrument Chunk, ckSize is always 20.

The baseNote is the note at which the instrument plays back the sound data
without pitch modification.  Units are MIDI (MIDI is an acronym for
Musical Instrument Digital Interface) note numbers, and are in the range 0
through 127.  Middle C is 60.

The detune field determines how much the instrument should alter the pitch
of the sound when it is played back.  Units are in cents (1/100 of a
semitone) and range from -50 to +50.  Negative numbers mean that the pitch
of the sound should be lowered, while positive numbers mean that it should
be raised.

The lowNote and highNote fields specify the suggested range on a keyboard
for playback of the sound data.  The sound data should be played if the
instrument is requested to play a note between the low and high,
inclusive.  The base note does not have to be within this range.  Units
for lowNote and highNote are MIDI note values.

The lowVelocity and highVelocity fields specify the suggested range of
velocities for playback of the sound data.  The sound data should be
played if the note-on velocity is between low and high velocity,
inclusive.  Units are MIDI velocity values, 1 (lowest velocity) through
127 (highest velocity).

The gain is the amount by which to change the gain of the sound when it is
played.  Units are decibels.  For example, 0db means no change, 6db means
double the value of each sample point, while -6db means halve the value of
each sample point.

The sustainLoop field specifies a loop that is to be played when an
instrument is sustaining a sound.

The releaseLoop field specifies a loop that is to be played when an
instrument is in the release phase of playing back a sound.  The release
phase usually occurs after a key on an instrument is released.

The Instrument Chunk is optional.  No more than one Instrument Chunk can
appear in a FORM AIFF.

ASIF Note:    The Apple IIGS Sampled Instrument Format also defines a
              chunk with ID of 'INST', which is not the same as the Audio
              IFF Instrument Chunk.  A good way to tell the two chunks
              apart in generic IFF-style readers is by the ckSize fields.
              The Audio IFF Instrument Chunk's ckSize field is always 20,
              whereas the Apple IIGS Sampled Instrument Format Instrument
              Chunk's ckSize field, for structural reasons, can never be
              20.

@ENDNODE


@NODE AIFF-12 "AIFF.doc / AIFF / The MIDI Data Chunk "
The MIDI Data Chunk can be used to store MIDI data.  Please refer to
Musical Instrument Digital Interface Specification 1.0, available from the
International MIDI Association, for more details on MIDI.

The primary purpose of this chunk is to store MIDI System Exclusive
messages, although other types of MIDI data can be stored in the block as
well.  As more instruments come to market, they will likely have
parameters that have not been included in the Audio IFF specification.
The MIDI System Exclusive messages for these instruments may contain many
parameters that are not included in the Instrument Chunk.  For example, a
new sampling instrument may have more than the two loops defined in the
Instrument Chunk.  These loops will likely be represented in the MIDI
System Exclusive message for the new machine.  This MIDI System Exclusive
message can be stored in the MIDI Data Chunk.

    #define		MIDIDataID   'MIDI' /* ckID for MIDI Data Chunk */

    typedef struct {
	ID		ckID;
	long		ckSize;

	unsigned char	MIDIdata[];
    } MIDIDataChunk;

The ckID is always 'MIDI'.  ckSize of the data portion of the chunk, in
bytes. It does not include the 8 bytes used by ckID and ckSize.

The MIDIData field contains a stream of MIDI data.

The MIDI Data Chunk is optional.  Any number of MIDI Data Chunks may exist
in a FORM AIFF.  If MIDI System Exclusive messages for several instruments
are to be stored in a FORM AIFF, it is better to use one MIDI Data Chunk
per instrument than one big MIDI Data Chunk for all of the instruments.

@ENDNODE


@NODE AIFF-13 "AIFF.doc / AIFF / The Audio Recording Chunk "
The Audio Recording Chunk contains information pertinent to audio
recording devices.

    #define     AudioRecordingID 'AESD'  /* ckID for Audio Recording */
                                         /*  Chunk.                 */
    typedef struct {
        ID                      ckID
        long                    ckSize;

        unsigned char   AESChannelStatusData[24];
    } AudioRecordingChunk;

The ckID is always 'AESD'. The ckSize is the size of the data portion of
the chunk, in bytes For the Audio Recording Chunk, ckSize is always 24.

The 24 bytes of AESCChannelStatusData are specified in the "AES
Recommended Practice for Digital Audio Engineering - Serial Transmission
Format for Linearly Represented Digital Audio Data", transmission of
digital audio between audio devices.  This information is duplicated in
the Audio Recording Chunk for convenience.  Of general interest would be
bits 2, 3, and 4 of byte 0, which describe recording emphasis.

The Audio Recording Chunk is optional.  No more than one Audio Recording
Chunk may appear in a FORM AIFF.

@ENDNODE


@NODE AIFF-14 "AIFF.doc / AIFF / The Application Specific Chunk "
The Application Specific Chunk can be used for any purposes whatsoever by
developers and application authors.  For example, an application that
edits sounds might want to use this chunk to store editor state parameters
such as magnification levels, last cursor position, etc.

    #define	ApplicationSpecificID 'APPL' /* ckID for Application */
					     /*  Specific Chunk.     */
    typedef struct {
	ID		ckID;
	long		ckSize;
	OSType		applicationSignature;
	char		data[];
    } ApplicationSpecificChunk;

The ckID is always 'APPL'.  The ckSize is the size of the data portion of
the chunk, in bytes.  It does not include the 8 bytes used by ckID and
ckSize.

The applicationSignature identifies a particular application.  For
Macintosh applications, this will be the application's four character
signature.

The OSType field is used by applications which run on platforms from Apple
Computer, Inc.  For the Apple II, the OStype field should be set to
'pdos'. For the Macintosh, this field should be set to the four character
signature as registered with Apple Technical Support.

The data field is the data specific to the application.

The Application Specific Chunk is optional.  Any number of Application
Specific Chunks may exist in a single FORM AIFF.

@ENDNODE


@NODE AIFF-15 "AIFF.doc / AIFF / The Comments Chunk "
The Comments Chunk is used to store comments in the FORM AIFF.  "EA IFF
85" has an Annotation Chunk (used in ASIF) that can be used for comments,
but the Comments Chunk has two features not found in the "EA IFF 85"
chunk.  They are a time-stamp for the comment and a link to a marker.

@{" Comment " link AIFF-15-1}
@{" Comments Chunk Format " link AIFF-15-2}

@ENDNODE


@NODE AIFF-15-1 "AIFF / The Comments Chunk / Comment "
A comment consists of a time stamp, marker id, and a text count followed
by text.

    typedef struct {
	unsigned long	timeStamp;
	MarkerID	marker;
	unsigned short	count;
	char		text;
    } Comment;

The timeStamp indicates when the comment was created.  On the Amiga, units
are the number of seconds since January 1, 1978.  On the Macintosh, units
are the number of seconds since January 1, 1904.

A comment can be linked to a marker.  This allows applications to store
long descriptions of markers as a comment.  If the comment is referring to
a marker, then the marker field is the ID of that marker.  Otherwise,
marker is zero, indicating that this comment is not linked to a marker.

The count is the length of the text that makes up the comment.  This is a
16-bit quantity, allowing much longer comments than would be available
with a pstring.

The text field contains the comment itself.

The Comments Chunk is optional.  No more than one Comments Chunk may
appear in a single FORM AIFF.

@ENDNODE


@NODE AIFF-15-2 "AIFF / The Comments Chunk / Comments Chunk Format "
    #define 	CommentID	'COMT'	/* ckID for Comments Chunk  */

    typedef struct {
	ID		ckID;
	long		ckSize;

	unsigned short  numComments;
	Comment		comments[];
    }CommentsChunk;

The ckID is always 'COMT'.  The ckSize is the size of the data portion of
the chunk, in bytes.  It does not include the 8 bytes used by ckID and
ckSize.

The numComments field contains the number of comments in the Comments
Chunk. This is followed by the comments themselves.  Comments are always
even numbers of bytes in length, so there is no padding between comments
in the Comments Chunk.

The Comments Chunk is optional.  No more than one Comments Chunk may
appear in a single FORM AIFF.

@ENDNODE


@NODE AIFF-16 "AIFF.doc / AIFF / The Text Chunks, Name, Author, Copyright, Annotation "
These four chunks are included in the definition of every "EA IFF 85"
file. All are text chunks; their data portion consists solely of text.
Each of these chunks is optional.

    #define 	NameID 'NAME' 	/* ckID for Name Chunk */
    #define 	NameID 'AUTH' 	/* ckID for Author Chunk */
    #define 	NameID '(c) ' 	/* ckID for Copyright Chunk */
    #define 	NameID 'ANNO' 	/* ckID for Annotation Chunk */

    typedef struct {
	ID	ckID;
	long	ckSize;
	char 	text[];
    }TextChunk;

The ckID is either 'NAME', 'AUTH', '(c) ', or 'ANNO' depending on whether
the chunk is a Name Chunk, Author Chunk, Copyright Chunk, or  Annotation
Chunk, respectively.  For the Copyright Chunk, the 'c' is lowercase and
there is a space (0x20) after the close parenthesis.

The ckSize is the size of the data portion of the chunk, in this case the
text.

The text field contains pure ASCII characters.  it is not a pstring or a C
string.  The number of characters in text is determined by ckSize.  The
contents of text depend on the chunk, as described below:

@{" Name Chunk " link AIFF-16-1}
@{" Author Chunk " link AIFF-16-2}
@{" Copyright Chunk " link AIFF-16-3}
@{" Annotation Chunk " link AIFF-16-4}

@ENDNODE


@NODE AIFF-16-1 "AIFF / The Text Chunks / Name Chunk "
The text contains the name of the sampled sound.  The Name Chunk is
optional.  No more than one Name Chunk may exist within a FORM AIFF.

@ENDNODE


@NODE AIFF-16-2 "AIFF / The Text Chunks / Author Chunk "
The text contains one or more author names.  An author in this case is the
creator of a sampled sound.  The Author Chunk is optional.  No more than
one Author Chunk may exist within a FORM AIFF.

@ENDNODE


@NODE AIFF-16-3 "AIFF / The Text Chunks / Copyright Chunk "
The Copyright Chunk contains a copyright notice for the sound.  The text
field contains a date followed by the name of the copyright owner.  The
chunk ID '(c) ' serves as the copyright character.  For example, a
Copyright Chunk containing the text "1991 Commodore-Amiga, Inc." means
"(c) 1991 Commodore-Amiga, Inc."  The Copyright Chunk is optional.  No
more than one Copyright Chunk may exist within a FORM AIFF.

@ENDNODE


@NODE AIFF-16-4 "AIFF / The Text Chunks / Annotation Chunk "
The text contains a comment.  Use of this chunk is discouraged within a
FORM AIFF.  The more powerful Comments Chunk should be used instead.  The
Annotation Chunk is optional.  Many Annotation Chunks may exist within a
FORM AIFF.

@ENDNODE


@NODE AIFF-17 "AIFF.doc / AIFF / Chunk Precedence "
Several of the local chunks for FORM AIFF may contain duplicate
information. For example, the Instrument Chunk defines loop points and
MIDI System Exclusive data in the MIDI Data Chunk may also define loop
points.  What happens if these loop points are different?  How is an
application supposed to loop the sound?  Such conflicts are resolved by
defining a precedence for chunks.  This precedence is illustrated in
Figure 10.

                       Common Chunk           Highest Precedence
                            |
                     Sound Data Chunk
                            |
                       Marker Chunk
                            |
                     Instrument Chunk
                            |
                       Comment Chunk
                            |
                        Name Chunk
                            |
                       Author Chunk
                            |
                      Copyright Chunk
                            |
                      Annotation Chunk
                            |
                   Audio Recording Chunk
                            |
                      MIDI Data Chunk
                            |
                 Application Specific Chunk   Lowest Precedence

                Figure 10: Chunk Precedence

The Common Chunk has the highest precedence, while the Application
Specific Chunk has the lowest.  Information in the Common Chunk always
takes precedence over conflicting information in any other chunk.  The
Application Specific Chunk always loses in conflicts with other chunks.
By looking at the chunk hierarchy, for example, one sees that the loop
points in the Instrument Chunk take precedence over conflicting loop
points found in the MIDI Data Chunk.

It is the responsibility of applications that write data into the lower
precedence chunks to make sure that the higher precedence chunks are
updated accordingly.

Figure 11 illustrates an example of a FORM AIFF.  An Audio IFF file is
simple a file containing a single FORM AIFF.  The FORM AIFF is stored in
the data fork of Macintosh file systems that can handle resource forks.

     _____________________________________________________________________
    | FORM AIFF                                                           |
    |                          _____________                              |
    |                    ckID |_ 'FORM' ____|                             |
    |                  ckSize |_ 176516 ____|                             |
    |  _____________ formType |_ 'AIFF' ____| __________________________  |
    | | Common           ckID |_ 'COMM' ____|                           | |
    | | Chunk          ckSize |_ 18 ________|                           | |
    | |           numChannels |_ 2 ___|_____                            | |
    | |       numSampleFrames |_ 88200 _____|                           | |
    | |            sampleSize |_ 16 __|_______________________________  | |
    | |___________ sampleRate |_ 44100.00 ____________________________| | |
    | | Marker           ckID |_ 'MARK' _____|                          | |
    | | Chunk          ckSize |_ 34 _________|                          | |
    | |            numMarkers |_ 2 ___|                                 | |
    | |                    id |_ 1 ___|_______                          | |
    | |              position |_ 44100 ___ ___|___ ___ ___ ___ ___ ___  | |
    | |            markerName | 8 |'b'|'e'|'g'|' '|'l'|'o'|'o'|'p'| 0 | | |
    | |                    id |_ 2 ___|_______                          | |
    | |              position |_ 88200 _______|___ ___ ___ ___ ___ ___  | |
    | |___________ markerName | 8 |'e'|'n'|'d'|' '|'l'|'o'|'o'|'p'| 0 | | |
    | | Instrument       ckID |_ 'INST' ______|                         | |
    | | Chunk          ckSize |_ 20 __________|                         | |
    | |              baseNote | 60|                                     | |
    | |                detune | -3|                                     | |
    | |               lowNote | 57|                                     | |
    | |              highNote | 63|                                     | |
    | |           lowVelocity | 1 |                                     | |
    | |          highVelocity |127|__                                   | |
    | |                  gain |_ 6 __|                                  | |
    | |  sustainLoop.playMode |_ 1 __|                                  | |
    | | sustainLoop.beginLoop |_ 1 __|                                  | |
    | |   sustainLoop.endLoop |_ 2 __|                                  | |
    | |  releaseLoop.playMode |_ 0 __|                                  | |
    | | releaseLoop.beginLoop |_ - __|                                  | |
    | |__ releaseLoop.endLoop |_ - __|__________________________________| |
    | | Sound            ckID |_ 'SSND' ______|                         | |
    | | Data           ckSize |_ 176408 ______|                         | |
    | | Chunk          offset |_ 0 ___________|                         | |
    | |             blockSize |_ 0 ___________|        _______ _______  | |
    | |             soundData |_ch 1 _|_ch 2 _| . . . |_ch 1 _|_ch 2 _| | |
    | |                       first sample frame   88200th sample frame | |
    | |_________________________________________________________________| |
    |_____________________________________________________________________|

                         Figure 11: Sample FORM AIFF

@ENDNODE


@NODE AIFF-18 "AIFF.doc / AIFF / Further Reference "
 o    "Inside Macintosh", Volume II, Apple Computer, Inc.
 o    "Apple Numerics Manual", Second Edition, Apple Computer, Inc.
 o    "File Type Note: File Type $D8, Auxiliary Type $0002, Apple IIGS
       Sampled Instrument Format", Apple Computer, Inc.
 o    "Audio Interchange File Format v1.3",  APDA
 o    "AES Recommended Practice for Digital Audio Engineering--Serial
      Transmission Format for Linearly Represented Digital Audio Data",
      Audio Engineering Society, 60 East 42nd Street, New York, NY 10165
 o    "MIDI:  Musical Instrument Digital Interface, Specification 1.0", the
      International MIDI Association.
 o    "`EA IFF 85' Standard for Interchange Format Files", Electronic Arts
 o    "`8SVX' IFF 8-bit Sampled Voice", Electronic Arts

@ENDNODE


@NODE ANBM.doc "A / IFF Third Party Public Form and Chunk Specification / ANBM.doc"
Animated bitmap form (Framer, Deluxe Video)

TITLE:  Form ANBM (animated bitmap form used by Framer, Deluxe Video)

(note from the author)

The format was designed for simplicity at a time when the IFF standard was
very new and strange to us all.  It was not designed to be a general
purpose animation format.  It was intended to be a private format for use
by DVideo, with the hope that a more powerful format would emerge as the
Amiga became more popular.

I hope you will publish this format (and we did!) so that other formats
will not inadvertantly conflict with it.

PURPOSE:  To define simple animated bitmaps for use in DeluxeVideo.

In Deluxe Video objects appear and move in the foreground with a picture
in the background.  Objects are "small" bitmaps usually saved as brushes
from DeluxePaint and pictures are large full screen bitmaps saved as files
from DeluxePaint.

Two new chunk headers are defined: ANBM and FSQN.

An animated bitmap (ANBM) is a series of bitmaps of the same size and
depth.  Each bitmap in the series is called a frame and is labeled by a
character, 'a b c ...' in the order they appear in the file.

The frame sequence chunk (FSQN) specifies the playback sequence of the
individual bitmaps to achieve animation. FSQN_CYCLE and FSQN_TOFRO specify
two algorithmic sequences.  If neither of these bits is set, an arbitrary
sequence can be used instead.


    ANBM         - identifies this file as an animated bitmap
    .FSQN        - playback sequence information
    .LIST ILBM   - LIST allows following ILBMs to share properties
    ..PROP ILBM  - properties follow
    ...BMHD      - bitmap header defines common size and depth
    ...CMAP      - colormap defines common colors
    ..FORM ILBM  - first frame follows
    ..BODY       - the first frame
       .         - FORM ILBM and BODY for each remaining frame
       .
       .

@{" ANBM " link ANBM-1}
@{" FSQN " link ANBM-2}
@{" Supporting Software " link ANBM-3}

@ENDNODE

@NODE ANBM-1 " ANBM.doc / ANBM "
Chunk Description:

The ANBM chunk identifes this file as an animated bitmap

Chunk Spec:

   #define ANBM    MakeID('A','N','B','M')

Disk record:

   none

@ENDNODE


@NODE ANBM-2 " ANBM.doc / FSQN "
Chunk Description:

The FSQN chunk specifies the frame playback sequence

Chunk Spec:


#define FSQN    MakeID('F','S','Q','N')

/* Flags */
#define FSQN_CYCLE  0x0001 /* Ignore sequence, cycle a,b,..y,z,a,b,.. */
#define FSQN_TOFRO  0x0002 /* Ignore sequence, cycle a,b,..y,z,y,..a,b, */
/* Disk record */
typedef struct {
    WORD numframes;      /* Number of frames in the sequence */
    LONG dt;             /* Nominal time between frames in jiffies */
    WORDBITS flags;      /* Bits modify behavior of the animation */
    UBYTE sequence[80];  /* string of 'a'..'z' specifying sequence */
    } FrameSeqn;

@ENDNODE


@NODE ANBM-3 " ANBM.doc / Supporting Software "
DeluxeVideo by Mike Posehn and Tom Case for Electronic Arts

@ENDNODE


@NODE ANIM.BRUSH.doc "A / IFF Third Party Public Form and Chunk Specification / ANIM.brush.doc"
ANIM brush format

                    Dpaint Anim Brush IFF Format

             From a description by the author of DPaint,
                      Dan Silva, Electronic Arts

The "Anim Brushes" of DPaint III are saved on disk in the IFF "ANIM"
format. Basically, an ANIM Form consists of an initial ILBM which is the
first frame of the animation, and any number of subsequent "ILBM"S (which
aren't really ILBM's) each of which contains an ANHD animation header
chunk and a DLTA chunk comprised of the encoded difference between a frame
and a previous one.

To use ANIM terminology (for a description of the ANIM format, see the IFF
Anim Spec, by Gary Bonham). Anim Brushes use a "type 5" encoding, which is
a vertical, byte-oriented delta encoding (based on Jim Kent's RIFF).  The
deltas have an interleave of 1, meaning deltas are computed between
adjacent frames, rather than between frames 2 apart, which is the usual
ANIM custom for the purpose of fast hardware page-flipping.  Also, the
deltas use Exclusive Or to allow reversable play.

However, to my knowledge, all the existing Anim players in the Amiga world
will only play type 5 "Anim"s which have an interleave of 0 (i.e. 2) and
which use a Store operation rather than Exclusive Or, so no existing
programs will read Anim Brushes anyway.  The job of modifying existing
Anim readers to read Anim Brushes should be simplified, however.

Here is an outline of the structure of the IFF Form output by DPaint III
as an "Anim Brush".  The IFF Reader should of course be flexible enough to
tolerate variation in what chunks actually appear in the initial ILBM.

                  FORM ANIM
                      . FORM ILBM         first frame
                      . . BMHD
                      . . CMAP
                      . . DPPS
                      . . GRAB
                      . . CRNG
                      . . CRNG
                      . . CRNG
                      . . CRNG
                      . . CRNG
                      . . CRNG
                      . . DPAN     my own little chunk.
                      . . CAMG
                      . . BODY

                      . FORM ILBM         frame 2
                      . . ANHD                animation header chunk
                      . . DLTA                delta mode data

                      . FORM ILBM         frame 3
                      . . ANHD                animation header chunk
                      . . DLTA                delta mode data

                      . FORM ILBM         frame 4
                      . . ANHD                animation header chunk
                      . . DLTA                delta mode data
       ...
                   . FORM ILBM         frame N
                      . . ANHD                animation header chunk
                      . . DLTA                delta mode data

@{" DPAN Chunk Format " link ANIM.BRUSH-1}
@{" ANHD Chunk Format " link ANIM.BRUSH-2}
@{" RIFF " link ANIM.BRUSH-3}

@ENDNODE


@NODE ANIM.BRUSH-1 "ANIM.brush.doc / DPAN chunk Format "
   typedef struct {
    UWORD version;   /* current version=4 */
    UWORD nframes;   /* number of frames in the animation.*/
    ULONG flags;   /* Not used */
    } DPAnimChunk;

The version number was necessary during development. At present all I look
at is "nframes".

@ENDNODE


@NODE ANIM.BRUSH-2 "ANIM.brush.doc / ANHD chunk format "
typedef struct {
 UBYTE operation;  /* =0  set directly
       =1  XOR ILBM mode,
       =2 Long Delta mode,
       =3 Short Delta mode
       =4 Generalize short/long Delta mode,
       =5 Byte Vertical Delta (riff)
       =74 (Eric Grahams compression mode)
   */
 UBYTE mask;      /* XOR ILBM only: plane mask where data is*/
 UWORD w,h;
 WORD x,y;
 ULONG abstime;
 ULONG reltime;
 UBYTE interleave; /* 0 defaults to 2 */
 UBYTE pad0;   /* not used */
 ULONG bits;   /* meaning of bits:
    bit# =0                 =1
    0    short data         long data
    1    store              XOR
    2    separate info      one info for
         for each plane     for all planes
    3    not RLC            RLC (run length encoded)
    4    horizontal         vertical
    5    short info offsets long info offsets
   */
 UBYTE pad[16];
 } AnimHdr;


for Anim Brushes, set:

 animHdr.operation = 5;  /* RIFF encoding */
 animHdr.interleave = 1;
 animHdr.w = curAnimBr.bmob.pict.box.w;
 animHdr.h = curAnimBr.bmob.pict.box.h;
 animHdr.reltime = 1;
 animHdr.abstime = 0;
 animHdr.bits = 4; /* indicating XOR */

- everything else is set to 0.

NOTE: the "bits" field was actually intended ( by the original creator of
the ANIM format, Gary Bonham of SPARTA, Inc.) for use with only with
compression method 4. I am using bit 2 of the bits field to indicate the
Exclusive OR operation in the context of method 5, which seems like a
reasonable generalization.

For an Anim Brush with 10 frames, there will be an initial frame followed
by 10 Delta's (i.e ILBMS containing ANHD and DLTA chunks).  Applying the
first Delta to the initial frame generates the second frame, applying the
second Delta to the second frame generates the third frame, etc.  Applying
the last Delta thus brings back the first frame.

The DLTA chunk begins with 16 LONG plane offets, of which DPaint only uses
the first 6 (at most).  These plane offsets are either the offset (in
bytes) from the beginning of the DLTA chunk to the data for the
corresponding plane, or Zero, if there was no change in that plane.  Thus
the first plane offset is either 0 or 64.

@ENDNODE


@NODE ANIM.BRUSH-3 "ANIM.brush.doc / RIFF "
The following description of the method is based on Gary Bonham's
rewording of Jim Kent's RIFF documentation.

Compression/decompression is performed on a plane-by-plane
basis.

Each byte-column of the bitplane is compressed separately.  A
320x200 bitplane would have 40 columns of 200 bytes each.  In
general, the bitplanes are always an even number of bytes wide,
so for instance a 17x20 bitplane would have 4 columns of 20
bytes each.

Each column starts with an op-count followed by a number of
ops.  If the op-count is zero, that's ok, it just means there's
no change in this column from the last frame.  The ops are of
three kinds, and followed by a varying amount of data depending
on which kind:

     1. SKIP - this is a byte with the hi bit clear that   says
        how many rows to move the "dest" pointer forward, ie to
        skip. It is non-zero.

     2. DUMP - this is a byte with the hi bit set.  The hi bit is
        masked off and the remainder is a count of the number of
        bytes of data to XOR directly.  It is followed by the
        bytes to copy.

     3. RUN - this is a 0 byte followed by a count byte, followed
        by a byte value to repeat "count" times, XOR'ing it into
        the destination.

Bear in mind that the data is compressed vertically rather than
horizontally, so to get to the next byte in the destination  you
add the number of bytes per row instead of one.

The Format of DLTA chunks is as described in section 2.2.2 of the Anim
Spec. The encoding for type 5 is described in section 2.2.3 of the Anim
Spec.

@ENDNODE


@NODE ANIM.doc "A / IFF Third Party Public Form and Chunk Specification / ANIM.doc"
Cel animation form
                              A N I M
                  An IFF Format For CEL Animations

                    Revision date:  4 May 1988
                    Prepared by:
                          SPARTA Inc.
                          23041 de la Carlota
                          Laguna Hills, Calif 92653
                          (714) 768-8161
                          contact: Gary Bonham

                    and:  Aegis Development Co.
                          2115 Pico Blvd.
                          Santa Monica, Calif 90405
                          213) 392-9972

@{" Introduction " link ANIM-1}
@{" Chunk Formats " link ANIM-2}

@ENDNODE


@NODE ANIM-1 " ANIM.doc / Introduction "
The ANIM IFF format was developed at Sparta originally for the production
of animated video sequences on the Amiga computer.  The intent was to be
able to store, and play back, sequences of frames and to minimize both the
storage space on disk (through compression) and playback time (through
efficient de-compression algorithms). It was desired to maintain maximum
compatibility with existing IFF formats and to be able to display the
initial frame as a normal still IFF picture.

Several compression schemes have been introduced in the ANIM format. Most
of these are strictly of historical interest as the only one currently
being placed in new code is the vertical run length encoded byte encoding
developed by Jim Kent.

@{" ANIM Format Overview " link ANIM-1-1}
@{" Recording ANIMs " link ANIM-1-2}
@{" Playing ANIMs " link ANIM-1-3}

@ENDNODE


@NODE ANIM-1-1 "Introduction / ANIM Format Overview "
The general philosophy of ANIMs is to present the initial frame as a
normal, run-length-encoded, IFF picture.  Subsequent frames are then
described by listing only their differences from a previous frame.
Normally, the "previous" frame is two frames back as that is the frame
remaining in the hidden screen buffer when double-buffering is used.  To
better understand this, suppose one has two screens, called A and B, and
the ability to instantly switch the display from one to the other.  The
normal playback mode is to load the initial frame into A and duplicate it
into B.  Then frame A is displayed on the screen.  Then the differences
for frame 2 are used to alter screen B and it is displayed.  Then the
differences for frame 3 are used to alter screen A and it is displayed,
and so on.  Note that frame 2 is stored as differences from frame 1, but
all other frames are stored as differences from two frames back.

ANIM is an IFF FORM and its basic format is as follows (this assumes the
reader has a basic understanding of IFF format files):

                FORM ANIM
                . FORM ILBM         first frame
                . . BMHD                normal type IFF data
                . . ANHD                optional animation header
                                        chunk for timing of 1st frame.
                . . CMAP
                . . BODY
                . FORM ILBM         frame 2
                . . ANHD                animation header chunk
                . . DLTA                delta mode data
                . FORM ILBM         frame 3
                . . ANHD
                . . DLTA
                     ...

The initial FORM ILBM can contain all the normal ILBM chunks, such as
CRNG, etc.  The BODY will normally be a standard run-length-encoded data
chunk (but may be any other legal compression mode as indicated by the
BMHD).  If desired, an ANHD chunk can appear here to provide timing data
for the first frame.  If it is here, the operation field should be =0.

The subsequent FORMs ILBM contain an ANHD, instead of a BMHD, which
duplicates some of BMHD and has additional parameters pertaining to the
animation frame.  The DLTA chunk contains the data for the delta
compression modes.  If the older XOR compression mode is used, then a BODY
chunk will be here.  In addition, other chunks may be placed in each of
these as deemed necessary (and as code is placed in player programs to
utilize them).  A good example would be CMAP chunks to alter the color
palette.  A basic assumption in ANIMs is that the size of the bitmap, and
the display mode (e.g. HAM) will not change through the animation.  Take
care when playing an ANIM that if a CMAP occurs with a frame, then the
change must be applied to both buffers.

Note that the DLTA chunks are not interleaved bitmap representations, thus
the use of the ILBM form is inappropriate for these frames. However, this
inconsistency was not noted until there were a number of commercial
products either released or close to release which generated/played this
format.  Therefore, this is probably an inconsistency which will have to
stay with us.

@ENDNODE


@NODE ANIM-1-2 "Introduction / Recording ANIMs "
To record an ANIM will require three bitmaps - one for creation of the
next frame, and two more for a "history" of the previous two frames for
performing the compression calculations (e.g. the delta mode calculations).

There are five frame-to-frame compression methods currently defined. The
first three are mainly for historical interest.  The product Aegis
VideoScape 3D utilizes the third method in version 1.0, but switched to
method 5 on 2.0.  This is the only instance known of a commercial product
generating ANIMs of any of the first three methods.  The fourth method is
a general short or long word compression scheme which has several options
including whether the compression is horizontal or vertical, and whether
or not it is XOR format.  This offers a choice to the user for the
optimization of file size and/or playback speed.  The fifth method is the
byte vertical run length encoding as designed by Jim Kent.  Do not confuse
this with Jim's RIFF file format which is different than ANIM.  Here we
utilized his compression/ decompression routines within the ANIM file
structure.

The following paragraphs give a general outline of each of the methods of
compression currently included in this spec.

@{" XOR Mode " link ANIM-1-2-1}
@{" Long Delta Mode " link ANIM-1-2-2}
@{" Short Delta Mode " link ANIM-1-2-3}
@{" General Delta Mode " link ANIM-1-2-4}
@{" Byte Vertical Compression " link ANIM-1-2-5}

@ENDNODE


@NODE ANIM-1-2-1 "Introduction Recording ANIMs / XOR mode "
This mode is the original and is included here for historical interest.
In general, the delta modes are far superior. The creation of XOR mode is
quite simple.  One simply performs an exclusive-or (XOR) between all
corresponding bytes of the new frame and two frames back.  This results in
a new bitmap with 0 bits wherever the two frames were identical, and 1
bits where they are different.  Then this new bitmap is saved using
run-length-encoding.  A major obstacle of this mode is in the time
consumed in performing the XOR upon reconstructing the image.

@ENDNODE


@NODE ANIM-1-2-2 "Introduction / Recording ANIMs / Long Delta mode "
This mode stores the actual new frame long-words which are different,
along with the offset in the bitmap.  The exact format is shown and
discussed in section 2 below. Each plane is handled separately, with no
data being saved if no changes take place in a given plane.  Strings of 2
or more long-words in a row which change can be run together so offsets do
not have to be saved for each one.

Constructing this data chunk usually consists of having a buffer to hold
the data, and calculating the data as one compares the new frame,
long-word by long-word, with two frames back.

@ENDNODE


@NODE ANIM-1-2-3 "Introduction / Recording ANIMs / Short Delta mode "
This mode is identical to the Long Delta mode except that short-words are
saved instead of long-words.  In most instances, this mode results in a
smaller DLTA chunk. The Long Delta mode is mainly of interest in improving
the playback speed when used on a 32-bit 68020 Turbo Amiga.

@ENDNODE


@NODE ANIM-1-2-4 "Introduction / Recording ANIMs / General Delta mode "
The above two delta compression modes were hastily put together. This mode
was an attempt to provide a well-thought-out delta compression scheme.
Options provide for both short and long word compression, either vertical
or horizontal compression, XOR mode (which permits reverse playback), etc.
About the time this was being finalized, the fifth mode, below, was
developed by Jim Kent.  In practice the short-vertical-run-length-encoded
deltas in this mode play back faster than the fifth mode (which is in
essence a byte-vertical-run-length-encoded delta mode) but does not
compress as well - especially for very noisy data such as digitized
images.  In most cases, playback speed not being terrifically slower, the
better compression (sometimes 2x) is preferable due to limited storage
media in most machines.

Details on this method are contained in the Format for Method 4
sub-section within the Delta Chunk section.

@ENDNODE


@NODE ANIM-1-2-5 "Introduction / Recording ANIMs / Byte Vertical Compression "
This method does not offer the many options that method 4 offers, but is
very successful at producing decent compression even for very noisy data
such as digitized images.  The method was devised by Jim Kent and is
utilized in his RIFF file format which is different than the ANIM format.
The description of this method in this document is taken from Jim's
writings.  Further, he has released both compression and decompression
code to public domain.

Details on this method are contained in the Format for Method 5
sub-section within the Delta Chunk section.

@ENDNODE


@NODE ANIM-1-3 "Introduction / Playing ANIMs "
Playback of ANIMs will usually require two buffers, as mentioned above,
and double-buffering between them.  The frame data from the ANIM file is
used to modify the hidden frame to the next frame to be shown.  When using
the XOR mode, the usual run- length-decoding routine can be easily
modified to do the exclusive-or operation required.  Note that runs of
zero bytes, which will be very common, can be ignored, as an exclusive or
of any byte value to a byte of zero will not alter the original byte value.

The general procedure, for all compression techniques, is to first decode
the initial ILBM picture into the hidden buffer and double- buffer it into
view.  Then this picture is copied to the other (now hidden) buffer.  At
this point each frame is displayed with the same procedure.  The next
frame is formed in the hidden buffer by applying the DLTA data (or the XOR
data from the BODY chunk in the case of the first XOR method) and the new
frame is double-buffered into view.  This process continues to the end of
the file.

A master colormap should be kept for the entire ANIM which would be
initially set from the CMAP chunk in the initial ILBM.  This colormap
should be used for each frame.  If a CMAP chunk appears in one of the
frames, then this master colormap is updated and the new colormap applies
to all frames until the occurrance of another CMAP chunk.

Looping ANIMs may be constructed by simply making the last two frames
identical to the first two.  Since the first two frames are special cases
(the first being a normal ILBM and the second being a delta from the
first) one can continually loop the anim by repeating from frame three.
In this case the delta for creating frame three will modify the next to
the last frame which is in the hidden buffer (which is identical to the
first frame), and the delta for creating frame four will modify the last
frame which is identical to the second frame.

Multi-File ANIMs are also supported so long as the first two frames of a
subsequent file are identical to the last two frames of the preceeding
file.  Upon reading subsequent files, the ILBMs for the first two frames
are simply ignored, and the remaining frames are simply appended to the
preceeding frames.  This permits splitting ANIMs across multiple floppies
and also permits playing each section independently and/or editing it
independent of the rest of the ANIM.

Timing of ANIM playback is easily achieved using the vertical blank
interrupt of the Amiga.  There is an example of setting up such a timer in
the ROM Kernel Manual.  Be sure to remember the timer value when a frame
is flipped up, so the next frame can be flipped up relative to that time.
This will make the playback independent of how long it takes to decompress
a frame (so long as there is enough time between frames to accomplish this
decompression).

@ENDNODE


@NODE ANIM-2 "ANIM.doc / Chunk Formats "

@{" ANHD Chunk " link ANIM-2-1}
@{" DLTA ChunK " link ANIM-2-2}


@ENDNODE


@NODE ANIM-2-1 "Chunk Formats / ANHD Chunk "
The ANHD chunk consists of the following data structure:

   UBYTE operation  The compression method:
                    =0 set directly (normal ILBM BODY),
                    =1 XOR ILBM mode,
                    =2 Long Delta mode,
                    =3 Short Delta mode,
                    =4 Generalized short/long Delta mode,
                    =5 Byte Vertical Delta mode
                    =6 Stereo op 5 (third party)
                    =74 (ascii 'J') reserved for Eric Graham's
                       compression technique (details to be
                       released later).

   UBYTE mask      (XOR mode only - plane mask where each
                    bit is set =1 if there is data and =0
                    if not.)
   UWORD w,h       (XOR mode only - width and height of the
                    area represented by the BODY to eliminate
                    unnecessary un-changed data)
   WORD  x,y       (XOR mode only - position of rectangular
                    area representd by the BODY)
   ULONG abstime   (currently unused - timing for a frame
                    relative to the time the first frame
                    was displayed - in jiffies (1/60 sec))
   ULONG reltime   (timing for frame relative to time
                    previous frame was displayed - in
                    jiffies (1/60 sec))
   UBYTE interleave (unused so far - indicates how may frames
                     back this data is to modify.  =0 defaults
                     to indicate two frames back (for double
                     buffering). =n indicates n frames back.
                     The main intent here is to allow values
                     of =1 for special applications where
                     frame data would modify the immediately
                     previous frame)
   UBYTE pad0        Pad byte, not used at present.
   ULONG bits        32 option bits used by options=4 and 5.
                     At present only 6 are identified, but the
                     rest are set =0 so they can be used to
                     implement future ideas.  These are defined
                     for option 4 only at this point.  It is
                     recommended that all bits be set =0 for
                     option 5 and that any bit settings used in
                     the future (such as for XOR mode) be compatible
                     with the option 4 bit settings.   Player code
                     should check undefined bits in options 4 and 5
                     to assure they are zero.

                     The six bits for current use are:

                     bit #              set =0               set =1
                     ===============================================
                     0              short data           long data
                     1                 set                  XOR
                     2             separate info        one info list
                                   for each plane       for all planes
                     3               not RLC        RLC (run length coded)
                     4              horizontal           vertical
                     5           short info offsets   long info offsets

   UBYTE pad[16]     This is a pad for future use for future
                     compression modes.

@ENDNODE


@NODE ANIM-2-2 "Chunk Formats / DLTA Chunk "
This chunk is the basic data chunk used to hold delta compression data.
The format of the data will be dependent upon the exact compression format
selected.  At present there are two basic formats for the overall
structure of this chunk.

@{" Format for methods 2 & 3 " link ANIM-2-2-1}
@{" Format for method 4 " link ANIM-2-2-2}
@{" Format for method 5 " link ANIM-2-2-3}

@ENDNODE


@NODE ANIM-2-2-1 "Chunk Formats / DLTA Chunk / Format for methods 2 & 3 "
This chunk is a basic data chunk used to hold the delta compression data.
The minimum size of this chunk is 32 bytes as the first 8 long-words are
byte pointers into the chunk for the data for each of up to 8 bitplanes.
The pointer for the plane data starting immediately following these 8
pointers will have a value of 32 as the data starts in the 33-rd byte of
the chunk (index value of 32 due to zero-base indexing).

The data for a given plane consists of groups of data words.  In Long
Delta mode, these groups consist of both short and long words - short
words for offsets and numbers, and long words for the actual data.  In
Short Delta mode, the groups are identical except data words are also
shorts so all data is short words. Each group consists of a starting word
which is an offset.  If the offset is positive then it indicates the
increment in long or short words (whichever is appropriate) through the
bitplane. In other words, if you were reconstructing the plane, you would
start a pointer (to shorts or longs depending on the mode) to point to the
first word of the bitplane.  Then the offset would be added to it and the
following data word would be placed at that position.  Then the next
offset would be added to the pointer and the following data word would be
placed at that position.  And so on...  The data terminates with an offset
equal to 0xFFFF.

A second interpretation is given if the offset is negative.  In that case,
the absolute value is the offset+2.  Then the following short-word
indicates the number of data words that follow.  Following that is the
indicated number of contiguous data words (longs or shorts depending on
mode) which are to be placed in contiguous locations of the bitplane.

If there are no changed words in a given plane, then the pointer in the
first 32 bytes of the chunk is =0.

@ENDNODE


@NODE ANIM-2-2-2 "Chunk Formats / DLTA Chunk / Format for method 4 "
The DLTA chunk is modified slightly to have 16 long pointers at the start.
The first 8 are as before - pointers to the start of the data for each of
the bitplanes (up to a theoretical max of 8 planes).  The next 8 are
pointers to the start of the offset/numbers data list.  If there is only
one list of offset/numbers for all planes, then the pointer to that list
is repeated in all positions so the playback code need not even be aware
of it.  In fact, one could get fancy and have some bitplanes share lists
while others have different lists, or no lists (the problems in these
schemes lie in the generation, not in the playback).

The best way to show the use of this format is in a sample playback
routine.

   SetDLTAshort(bm,deltaword)
   struct BitMap *bm;
   WORD *deltaword;
   {
      int i;
      LONG *deltadata;
      WORD *ptr,*planeptr;
      register int s,size,nw;
      register WORD *data,*dest;

      deltadata = (LONG *)deltaword;
      nw = bm->BytesPerRow >>1;

      for (i=0;i<bm->Depth;i++) {
         planeptr = (WORD *)(bm->Planes[i]);
         data = deltaword + deltadata[i];
         ptr  = deltaword + deltadata[i+8];
         while (*ptr != 0xFFFF) {
            dest = planeptr + *ptr++;
            size = *ptr++;
            if (size < 0) {
               for (s=size;s<0;s++) {
                  *dest = *data;
                  dest += nw;
               }
               data++;
            }
            else {
               for (s=0;s<size;s++) {
                  *dest = *data++;
                  dest += nw;
               }
            }
         }
      }
      return(0);
   }

The above routine is for short word vertical compression with run length
compression.  The most efficient way to support the various options is to
replicate this routine and make alterations for, say, long word or XOR.
The variable nw indicates the number of words to skip to go down the
vertical column.  This one routine could easily handle horizontal
compression by simply setting nw=1.  For ultimate playback speed, the
core, at least, of this routine should be coded in assembly language.

@ENDNODE


@NODE ANIM-2-2-3 "Chunk Formats / DLTA Chunk / Format for method 5 "
In this method the same 16 pointers are used as in option 4. The first 8
are pointers to the data for up to 8 planes. The second set of 8 are not
used but were retained for several reasons.  First to be somewhat
compatible with code for option 4 (although this has not proven to be of
any benefit) and second, to allow extending the format for more bitplanes
(code has been written for up to 12 planes).

Compression/decompression is performed on a plane-by-plane basis. For each
plane, compression can be handled by the skip.c code (provided Public
Domain by Jim Kent) and decompression can be handled by unvscomp.asm (also
provided Public Domain by Jim Kent).

Compression/decompression is performed on a plane-by-plane basis. The
following description of the method is taken directly from Jim Kent's code
with minor re-wording.  Please refer to Jim's code (skip.c and
unvscomp.asm) for more details:

Each column of the bitplane is compressed separately. A 320x200 bitplane
would have 40 columns of 200 bytes each. Each column starts with an
op-count followed by a number of ops.  If the op-count is zero, that's ok,
it just means there's no change in this column from the last frame. The
ops are of three classes, and followed by a varying amount of data
depending on which class:

  1. Skip ops - this is a byte with the hi bit clear that
     says how many rows to move the "dest" pointer forward,
     ie to skip. It is non-zero.
  2. Uniq ops - this is a byte with the hi bit set.  The hi
     bit is masked down and the remainder is a count of the
     number of bytes of data to copy literally.  It's of
     course followed by the data to copy.
  3. Same ops - this is a 0 byte followed by a count byte,
     followed by a byte value to repeat count times.

Do bear in mind that the data is compressed vertically rather than
horizontally, so to get to the next byte in the destination we add the
number of bytes per row instead of one!

@ENDNODE


@NODE DR2D.doc "A / IFF Third Party Public Form and Chunk Specification / DR2D.doc"
2-D Object standard format

FORM DR2D

Description by Ross Cunniff and John Orr

A standard IFF FORM to describe 2D drawings has been sorely needed for a
long time.  Several commercial drawing packages have been available for
some time but none has established its file format as the Amiga standard.
The absence of a 2D drawing standard hinders the development of
applications that use 2D drawings as it forces each application to
understand several private standards instead of a single one.  Without a
standard, data exchange for both the developer and the user is difficult,
if not impossible.

The DR2D FORM fills this void.  This FORM was developed by Taliesin, Inc.
for use as the native file format for their two-dimensional structured
drawing package, ProVector.  Saxon Industries and Soft Logik Publishing
Corporation are planning to support this new FORM in the near future.

Many of the values stored in the DR2D FORM are stored as IEEE single
precision floating point numbers.  These numbers consist of 32 bits,
arranged as follows:


 _______________________________________________________________________
| s e e e e e e e | e m m m m m m m | m m m m m m m m | m m m m m m m m |
 -----------------------------------------------------------------------
  31            24  23            16  15            8   7             0


where:

    s   is the sign of the number where 1 is negative and 0 is
          positive.
    e   is the 8 bit exponent in excess 127 form.  This number
          is the power of two to which the mantissa is raised
          (Excess 127 form means that 127 is added to the
          exponent before packing it into the IEEE number.)
    m   is the 23 bit mantissa.  It ranges from 1.0000000 to
          1.999999..., where the leading base-ten one is
          assumed.

An IEEE single precision with the value of 0.0000000 has all its bits
cleared.

@{" The DR2D Chunks " link DR2D-1}
@{" Simple DR2D Example " link DR2D-2}
@{" OFNT Form " link DR2D-3}

@ENDNODE


@NODE DR2D-1 "DR2D.doc / The DR2D Chunks "
FORM (0x464F524D)  	/* All drawings are a FORM */

    struct FORMstruct {
        ULONG       ID;             /* DR2D */
        ULONG       Size;
    };

DR2D (0x44523244)  /* ID of 2D drawing */

The DR2D chunks are broken up into three groups: the global drawing
attribute chunks, the object attribute chunks, and the object chunks. The
global drawing attribute chunks describe elements of a 2D drawing that are
common to many objects in the drawing.  Document preferences, palette
information, and custom fill patterns are typical document-wide settings
defined in global drawing attribute chunks. The object attribute chunks
are used to set certain properties of the object chunk(s) that follows the
object attribute chunk.  The current fill pattern, dash pattern, and line
color are all set using an object attribute chunk.  Object chunks describe
the actual DR2D drawing. Polygons, text, and bitmaps are found in these
chunks.

@{" Global Drawing Attribute Chunk " link DR2D-1-1}
@{" Object Attribute Chunks " link DR2D-1-2}
@{" The Object Chunks " link DR2D-1-3}

@ENDNODE


@NODE DR2D-1-1 "The DR2D Chunks / The Global Drawing Attribute Chunks "
The following chunks describe global attributes of a DR2D document.

@{" DRHD " link DR2D-1-1-1}     @{" CMAP " link DR2D-1-1-3}     @{" DASH " link DR2D-1-1-5}     @{" FILL " link DR2D-1-1-7}
@{" PPRF " link DR2D-1-1-2}     @{" FONS " link DR2D-1-1-4}     @{" AROW " link DR2D-1-1-6}     @{" LAYR " link DR2D-1-1-8}

@ENDNODE


@NODE DR2D-1-1-1 "The Global Drawing Attribute Chunks / DRHD "
DRHD (0x44524844) 	/* Drawing header */

The DRHD chunk contains the upper left and lower right extremes of the
document in (X, Y) coordinates.  This chunk is required and should only
appear once in a document in the outermost layer of the DR2D file (DR2Ds
can be nested).

	struct DRHDstruct {
	    ULONG	ID;
	    ULONG	Size;    		/* Always 16 */
	    IEEE	XLeft, YTop,
			XRight, YBot;
	};

The point (XLeft,YTop) is the upper left corner of the project and the
point (XRight,YBot) is its lower right corner.  These coordinates not only
supply the size and position of the document in a coordinate system, they
also supply the project's orientation.  If XLeft < XRight, the X-axis
increases toward the right.  If YTop < YBot, the Y-axis increases toward
the bottom.  Other combinations are possible; for example in Cartesian
coordinates, XLeft would be less than XRight but YTop would be greater
than YBot.

@ENDNODE


@NODE DR2D-1-1-2 "The Global Drawing Attribute Chunks / PPRF "
PPRF (0x50505249)   	/* Page preferences */

The PPRF chunk contains preference settings for ProVector.  Although this
chunk is not required, its use is encouraged because it contains some
important environment information.

	struct PPRFstruct {
	    ULONG	ID;
	    ULONG	Size;
	    char	Prefs[Size];
	};

DR2D stores preferences as a concatenation of several null-terminated
strings, in the Prefs[] array.  The strings can appear in any order. The
currently supported strings are:

		Units=<unit-type>
		Portrait=<boolean>
		PageType=<page-type>
		GridSize=<number>

where:
		<unit-type> 	is either Inch, Cm, or Pica
		<boolean>   	is either True or False
		<page-type> 	is either Standard, Legal, B4, B5, A3,
				  A4, A5, or Custom
		<number>    	is a floating-point number

The DR2D FORM does not require this chunk to explicitly state all the
possible preferences.  In the absence of any particular preference string,
a DR2D reader should fall back on the default value.  The defaults are:

		Units=Inch
		Portrait=True
		PageType=Standard
		GridSize=1.0

@ENDNODE


@NODE DR2D-1-1-3 "The Global Drawing Attribute Chunks / CMAP "
CMAP (0x434D4150)   	/* Color map (Same as ILBM CMAP) */

This chunk is identical to the ILBM CMAP chunk as described in the IFF
ILBM documentation.

    struct CMAPstruct {
        ULONG       ID;
        ULONG       Size;
        UBYTE       ColorMap[Size];
    };

ColorMap is an array of 24-bit RGB color values.  The 24-bit value is
spread across three bytes, the first of which contains the red intensity,
the next contains the green intensity, and the third contains the blue
intensity.  Because DR2D stores its colors with 24-bit accuracy, DR2D
readers must not make the mistake that some ILBM readers do in assuming
the CMAP chunk colors correspond directly to Amiga color registers.

@ENDNODE


@NODE DR2D-1-1-4 "The Global Drawing Attribute Chunks / FONS "
FONS (0x464F4E53)  