/*
 * @(#)IFFChunks.txt  1.6  2010-06-27
 *
 * Copyright (c) 2000-2010 Werner Randelshofer, Immensee, Switzerland.
 * All rights reserved.
 *
 * You may not use, copy or modify this file, except in compliance with the
 * license agreement you entered into with Werner Randelshofer.
 * For details see accompanying license terms.
 */

/**
 * This file contains the description of some
 * well known EA 85 Interchange File Format
 * data structures (IFF) as published in
 *   AMIGA ROM Kernel Reference Manual: Devices,
 *   Third Edition,
 *   Addison-Wesley, Reading
 *   ISBN 0-201-56775-X
 *
 * The following FORM's are described in this file:
 *
 *   8SVX  IFF 8-Bit Sampled Voice
 *   ACBM  Amiga Contiguous Bitmap
 *   AIFF  Audio Interchange File Format
 *   ANIM  IFF Cel Animation
 *   ILBM  IFF Interleaved Bitmap
 *   PBM   IFF Pixel Bitmap
 *   FTXT  IFF Formatted Text
 *   SMUS  IFF Simple Musical Score
 *
 * @author Werner Randelshofer
 * @version 1.4 2005-05-04 PBM chunks added
 * <br>1.3 2005-01-22 AIFF ID3 tag added
 * <br>1.2 2004-12-26 SXHD and SBDY chunks added 
 * <br>1.1 2003-04-01 SCTL chunk added.
 * <br>1.0 2000-10-05 Created. 
 */

/* ============================================
 *
 * Primitive Data Types
 *
 * ============================================
 */
/* Numbers */
typedef ubyte  UBYTE;  //  8 bits unsigned
typedef short  WORD;   // 16 bits signed
typedef ushort UWORD;  // 16 bits unsigned
typedef ushort USHORT;  // 16 bits unsigned
typedef int    LONG;   // 32 bits signed
typedef uint   ULONG;  // 32 bits unsigned

/* ============================================
 *
 * Generic Chunks
 *
 * ============================================
 */

/*
 * Group Type's
 */
magic formGroup "FORM????";
description propGroup "Data Section", "A FORM is one self-contained 'data object' that might be stored in a file by itself. It is one high level data object such as a picture or a sound effect, and generally contains a grouping of chunks. The IFF structure FORM makes it self-identifying. It could be a composite object like a musical score with nested musical instrument descriptions.";
magic catGroup "CAT ????";
description catGroup "Concatenated Data Objects", "A CAT is an untyped group of data objects (FORM's).";
magic listGroup "LIST????";
description listGroup "List of Data Objects", "A LIST is a typed group of data objects (FORM's). Property chunks of FORM's in the list may be shared using a PROP group.";
magic propGroup "PROP????";
description propGroup "Shared Properties", "PROP groups supply shared properties for FORM's within a LIST group.";

/* Chunk ID's
 */
magic NameChunk "????NAME";
description NameChunk "Name", "The Object's name.";
magic CopyrightChunk "????(c) ";
description CopyrightChunk "Copyright", "The FORM's copyright notice.";
magic AuthorChunk "????AUTH";
description AuthorChunk "Author", "The name of the author.";
magic AnnotationsChunk "????ANNO";
description AnnotationsChunk "Annotations", "Author's text annotations.";
magic CSetChunk "????CSET";
description CSetChunk "Code Set", "A chunk for use in any FORM, to specify character set used for the text in the FORM.";
magic FVerChunk "????FVER";
description FVerChunk "Version", "A chunk for use in any FORM, to contain standard Amiga version string.";

/* ---------- NAME -----------------------------------------------------*/
/* NAME chunk contains a CHAR[], the object's name. */
typedef struct { cstring name } NameChunk;

/* ---------- Copyright (c) --------------------------------------------*/
/* "(c) " chunk contains a CHAR[], the FORM's copyright notice. */
typedef struct { cstring copyrightNotice } CopyrightChunk;

/* ---------- AUTH -----------------------------------------------------*/
/* AUTH chunk contains a CHAR[], the name of the object's author. */
typedef struct { cstring author } AuthorChunk;

/* ---------- ANNO -----------------------------------------------------*/
/* ANNO chunk contains a CHAR[], the author's text annotations. */
typedef struct { cstring annotations } AnnotationsChunk;

/* ---------- CSET -----------------------------------------------------*/
enum {
    ecmaLatin1 = 1
} csetCodeSet;

typedef struct {
    LONG enum csetCodeSet codeSet; /* 0=ECMA Latin 1 (std Amiga charset) */
                                   /* CBM will define additional values. */
    LONG reserved[7];
} CSetChunk;

/* ---------- FVER -----------------------------------------------------*/
typedef struct { cstring version } FVerChunk;






/* ============================================
 *
 * "8SVX" IFF 8-Bit Sampled Voice
 *
 * ============================================
 */
/*  IFF types we may encounter  */
magic Voice8Form "FORM8SVX";
description Voice8Form "IFF 8-Bit Sampled Voice", "8SVX holds a digitally sampled audio voice consisting of 8-bit samples. A voice can be a one-shot sound or - with repetition and pitch scaling - a musical instrument.";

/* Chunk ID's we may encounter
 */
magic Voice8HeaderChunk "8SVXVHDR";
description Voice8HeaderChunk "Voice Header", "The required property VHDR holds the playback parameters for the sampled waveforms in the BODY chunk.";
magic Voice8AttackChunk "8SVXATAK";
description Voice8AttackChunk "Attack Envelope", "The optional data chunks ATAK and RLSE together give a piecewise-linear 'envelope' or 'amplitude contour'. This controu may be used to mudlate the sound during playback. It's especially useful for playing musical notes of variable duratoins. Playback programs may ignore the supplied envelope or substitute another.";
magic Voice8ReleaseChunk "8SVXRLSE";
description Voice8ReleaseChunk "Release Envelope", "The optional data chunks ATAK and RLSE together give a piecewise-linear 'envelope' or 'amplitude contour'. This controu may be used to mudlate the sound during playback. It's especially useful for playing musical notes of variable duratoins. Playback programs may ignore the supplied envelope or substitute another.";
magic Voice8BodyChunk "8SVXBODY";
description Voice8BodyChunk "Body", "The BODY chunk contains audio data samples grouped by octave. Within each octave are one-short and repeat portions.";
magic Voice8ChanChunk "8SVXCHAN";
description Voice8ChanChunk "Audio Channels", "The optional property chunk CHAN gives the information necessary to play a sample on a specified channel, or combination of channels.";
magic Voice8ChanChunk "8SVXPAN ";
description Voice8PanChunk "Stereo Pan", "The optional property chunk PAN provides the necessary information to create a stereo sound using a single array of data. It is necessary to replay the sample simultaneously on two channels, at different volume.";

/*
 * 8SVX VHDR Voice8Header
 * --------------------------------------------
 */
enum {
    none=0,        /* not compressed */
    fibonacciDelta=1        /* Fibonacci-delta encoding (Appendix C) */
} Voice8VHDRCompression;

typedef struct {
    ULONG oneShotHiSamples;     /* # samples in the high octave 1-shot part */
    ULONG repeatHiSamples;      /* # samples in the high octave repeat part */
    ULONG samplesPerHiCycle;    /* # samples/cycle in high octave, else 0 */
    UWORD samplesPerSec;        /* data sampling rate */
    UBYTE numberOfOctaves;             /* # of octaves of waveforms */
    UBYTE enum Voice8VHDRCompression soundCompression;         /* data compression technique used */
    LONG volume;               /* playback nominal volume from 0 to Unity
                                 * (full volume). Map this value into
                                 * the output hardware's dynamic range.
                                 */
} Voice8HeaderChunk;

/*
 * 8SVX ATAK and RLSE
 * --------------------------------------------
 */
typedef struct {
    UWORD duration;     /* segment duration in milliseconds, > 0 */
    Fixed dest;         /* destination volume factor */
} Voice8EGPoint;

/* ATAK and RLSE chunks contain an EGPoint[], piecewise-linear envelope. */
typedef struct {
    Voice8EGPoint egPoint;
} Voice8AttackChunk;

typedef struct {
    Voice8EGPoint egPoint;
} Voice8ReleaseChunk;

/* The envelope defines a function of time returning Fixed values.
 * It's used to scale the nominal volume specified in the Voice8Header.
 */

/*
typedef struct {
    UBYTE[] data;
} Voice8BodyChunk;
*/

/*
 * 8SVX CHAN and PAN
 * --------------------------------------------
 */
enum {
    right = 4,
    left  = 2,
    stereo= 6
} voice8ChanSampletype;

typedef struct {
     LONG enum voice8ChanSampletype sampletype;
} Voice8ChanChunk;

typedef struct {
     long stereoPosition;
} Voice8PanChunk;


/* ---------- BODY -----------------------------------------------------*/
/* BODY chunk contains a BYTE[], array of audio data samples. */
/* (8-bit signed numbers, -128 through 127.) */



/* ============================================
 *
 * "ACBM" Amiga Contiguous Bitmap
 *
 * ============================================
 */
/* FORM ACBM has the same format as FORM ILBM except the normal BODY
 * chunk (Interleaved Bitmap Body) is replaced by an ABIT chunk (Amiga Bitplane).
 */
/*  IFF types we may encounter  */
magic AmigaContiguousBitmapForm "FORMACBM";
description AmigaContiguousBitmapForm "IFF Amiga Contiguous Bitmap", "ACBM is an optimized image file format for Amiga-Basic. FORM ACBM has the same format as FORM ILBM except that the normal BODY chunk (Interleaved Bitmap) is replaced by an ABIT chunk (Amiga Bitplanes).";

/* Chunk ID's we may encounter
 */
magic ilbmBitmapHeaderChunk "ACBMBMHD";
magic ilbmColorMapChunk "ACBMCMAP";
magic ilbmColorRegisterRangeChunk "ACBMCRNG";
magic ilbmColorCyclingRangeAndTimingChunk "ACBMCCRT";
magic ilbmGrabChunk "ACBMGRAB";
magic ilbmSpritePrecedenceChunk "ACBMSPRT";
magic ilbmDestinationMergeChunk "ACBMDEST";
magic ilbmAmigaViewportModeDisplayIDChunk  "ACBMCAMG";
magic acbmAmigaBitplanesChunk "ACBMABIT";
description acbmAmigaBitplanesChunk "Amiga Bitplanes", "The ABIT chunk contains contiguous bitplane data. The chunk contains sequential data for bitplane 0 through bitplane n, to enable loading/storing of bitmaps with one DOS Read/Write per bitplane. Significant speed increases are realized when loading/saving screens from Amiga-Basic.";

/*
typedef struct {
    UBYTE[] data;
} acbmAmigaBitplanesChunk;
*/



/* ============================================
 *
 * "AIFF" Audio Interchange File Format
 *
 * ============================================
 */
/*  IFF types we may encounter  */
magic AudioIFFForm "FORMAIFF";
magic AudioIFFForm "FORMAIFC";
description AudioIFFForm "Audio Interchange File Format", "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.";

/* Chunk ID's we may encounter
 */
magic aiffCommonChunk "AIFFCOMM";
magic aiffCommonChunk "AIFCCOMM";
description aiffCommonChunk "Common Chunk", "The Common Chunk describes fundamental parameters of the sampled sound.";
magic aiffSoundDataChunk "AIFFSSND";
magic aiffSoundDataChunk "AIFCSSND";
description aiffSoundDataChunk "Sound Data Chunk", "The Sound Data Chunk contains the actual sample frames.";
magic aiffMarkerChunk "AIFFMARK";
magic aiffMarkerChunk "AIFCMARK";
description aiffMarkerChunk "Marker Chunk", "The Marker Chunk contains markers that point to positions in the sound data. Markers can be used for whatever purpose an application desires. e.g the Instrument Chunk uses markers to mark loop beginning and end points.";
magic aiffInstrumentChunk "AIFFINST";
magic aiffInstrumentChunk "AIFCINST";
description aiffInstrumentChunk "Instrument Chunk", "The Instrument Chunk defines basic parameters that an instrument, such as a sample, could use to play the sound data.";
magic aiffMidiDataChunk "AIFFMIDI";
magic aiffMidiDataChunk "AIFCMIDI";
description aiffMidiDataChunk "MIDI Data Chunk", "The Midi Data Chunk can be used to store MIDI data. 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.";
magic aiffAudioRecordingChunk "AIFFAESD";
magic aiffAudioRecordingChunk "AIFCAESD";
description aiffAudioRecordingChunk "Audio Recording Chunk", "The Audio Recording Chunk contains information pertinent to audio recording devices.";
magic aiffApplicationSpecificChunk "AIFFAPPL";
magic aiffApplicationSpecificChunk "AIFCAPPL";
description aiffApplicationSpecificChunk "Application Specific Chunk", "The Application Specific Chunk can be used for any purpose whatesoever by developers and application atuhros. 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.";
magic aiffCommentsChunk "AIFFCOMT";
magic aiffCommentsChunk "AIFCCOMT";
description aiffCommentsChunk "Comments Chunk", "The Comments Chunk is used to store comments in the FORM AIFF.";
magic aiffID3Chunk "AIFFID3 ";
description aiffID3Chunk "ID3 Audio Metadata Chunk", "ID3 is a general tagging format for audio, which makes it possible to store meta data about the audio inside the audio file itself."; 

typedef struct {
    WORD      numChannels;
    ULONG     numSampleFrames;
    WORD      sampleSize;
    extended  sampleRate;
} aiffCommonChunk;

/*
typedef struct {
    ULONG     offset;
    ULONG     blockSize;
    UBYTE[]   soundData;
} aiffSoundDataChunk;
*/

typedef struct {
    USHORT     numMarkers;
    aiffMarker markers[numMarkers];
} aiffMarker;

typedef SHORT aiffMarkerID;

typedef struct {
    aiffMarkerID     markerId;
    ULONG     position;
    pstring   markerName;
} aiffMarkerChunk;

typedef struct {
    SHORT         playMode;
    aiffMarkerID  beginLoopMarkerId;
    aiffMakerID   endLoopMarkerId;
} aiffLoop;

typedef struct {
    UBYTE   baseNote;
    UBYTE   detune;
    UBYTE   lowNote;
    UBYTE   highNote;
    UBYTE   lowVelocity;
    UBYTE   highVelocity;
    SHORT   gain;
    aiffLoop sustainLoop;
    aiffLoop releaseLoop;
} aiffInstrumentChunk;

/*
typedef struct {
    UBYTE[] midiData;
} aiffMidiDataChunk;
*/

typedef struct {
    UBYTE[24] aesChannelStatusData;
} aiffAudioRecordingChunk;

typedef struct {
    magic applicationSignature;
    UBYTE[] data;
} aiffApplicationSpecificChunk;

typedef struct {
    ULONG timeStamp;
    aiffMarkerID marker;
    USHORT count;
    char[count] text;
} aiffComment;

typedef struct {
    USHORT numComments;
    aiffComment comments[numComments];
} aiffCommentsChunk;

/* ============================================
 *
 * "ANIM" IFF Cel Animation
 *
 * ============================================
 */
/*  IFF types we may encounter  */
magic AnimIFFForm "FORMANIM";
description AnimIFFForm "IFF Cel Animation", "ANIM is an optimized animation format for Amiga Computers. 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.";

/* Chunk ID's we may encounter
 */
magic animDPAnimChunk "ILBMDPAN";
description animDPAnimChunk "Deluxe Paint Anim Chunk", "This optional property chunk is used by Deluxe Paint. It specifies the number of frames in the animation.";
magic animAnimHdrChunk "ILBMANHD";
description animAnimHdrChunk "Anim Header", "The ANHD property chunk provides timing data and specifies the data layout and compression method of the subsequent DLTA or BODY chunk.";
magic animAnimDeltaChunk "ILBMDLTA";
description animAnimDeltaChunk "Anim Delta", "The DLTA 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 specified by the ANHD.";
magic animSoundControlChunk "ILBMSCTL";
description animSoundControlChunk "Anim Sound Control", "The SCTL collection chunk controls playback of IFF 8SVX sounds synchronized with the subsequent DLTA or BODY chunk.";
magic animANFIChunk "ILBMANFI";
description animANFIChunk "ANFI Chunk", "";
magic animSoundHeaderChunk "ILBMSXHD";
description animSoundHeaderChunk "Anim Sound Header", "The SXHD property chunk describes the format of the sound samples contained in the SBDY chunks of the file. This chunk must appear in the first frame of an animation.";
magic animSoundBodyChunk "ILBMSBDY";
description animSoundBodyChunk "Anim Sound Body with Sample Data", "The SBDY property chunk holds sound sample data for a single animation frame. The format of data is described in the SXHD chunk in the first frame of the animation.";

/*
 * ANIM: ILBM DPAN
 * --------------------------------------------
 */

typedef struct {
 UWORD version;   /* current version=4 */
 UWORD numberOfFrames;   /* number of frames in the animation.*/
 ULONG flags;   /* Not used */
} animDPAnimChunk;

/*
 * ANIM: ILBM ANHD
 * --------------------------------------------
 */

enum {
    setDirectly=0,
    xorIlbmMode=1,
    longDeltaMode=2,
    shortDeltaMode=3,
    generalDeltaMode=4,
    byteVerticalDeltaMode=5,
    stereoOp5Mode = 6,
    vertical7Mode = 7,
    vertical8Mode = 8,
    ericGrahamsCompressionMode=74
} anhdOperation;

enum {
    longData = 0x1,
    XOR = 0x2,
    oneInfoForAllPlanes = 0x4,
    runLengthEncoded = 0x8,
    vertical = 0x10,
    longInfoOffsets = 0x20
} anhdBits;

typedef struct {
    UBYTE enum anhdOperation 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 width; UWORD height;
    WORD  xPosition; WORD yPosition;
    ULONG absoluteTime;
    ULONG relativeTime;
    UBYTE interleave; /* 0 defaults to 2 */
    UBYTE pad0;   /* not used */
    ULONG enum anhdBits 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[16] pad;
} animAnimHdrChunk;

/*
 * ANIM: ILBM DLTA
 * --------------------------------------------
 */
/*
typedef struct {
    UBYTE[] data;
} animAnimDeltaChunk;
*/

/*
 * ANIM: ILBM SCTL
 * --------------------------------------------
 */
enum {
    playSound = 1, // Start playing a sound
    stopSound = 2, // Stop the sound in a given channel
    setFreqVol = 3 // Change frequency/volume for a channel
} sctlCommand;

enum {
    noFlags = 0x0,
    noInterrupt = 0x1 // Play the sound, but only if
                      // the channel isn't in use
} sctlFlags;


typedef struct {
    UBYTE enum sctlCommand command;   // What to do, see above
    UBYTE  volume;    // Volume 0..64
    USHORT sound;     // Sound number (starting at 1).
    USHORT repeats;   // Number of times to play the sound
    USHORT channel;   // Channel(s) to use for playing (bit mask)
    USHORT frequency; // If non-zero, overrides the VHDR value
    USHORT enum sctlFlags flags;     // Flags, see above
    UBYTE[4] pad;       // For future use 
} animSoundControlChunk;

/*
 * ANIM: ILBM ANFI
 * --------------------------------------------
 */
enum {
    play = 0x28,
    doNothing = 0x0 
} anfiCommand;

typedef struct {
    USHORT enum anfiCommand command1;   // What to do, see above
    USHORT frequencyDivider1; // frequency divider (Amiga's audio.device)
    UBYTE  sound1; // Sound Number (starting at 1).
    UBYTE  channel1;    // Channel number (1 to 4, 0=invalid)
    UBYTE  repeats1; // repeat count (0..2 = play once, 3..? = play 2 or more times) 
    UBYTE  volume1;   // volume 00 to 40 (max should be 3F weird, perhaps volum 01 is 00 and 00 is channel off)

    USHORT enum anfiCommand command2;   // What to do, see above
    USHORT frequencyDivider2; // frequency divider (Amiga's audio.device)
    UBYTE  sound2; // Sound Number (starting at 1).
    UBYTE  channel2;    // Channel number (1 to 4, 0=invalid)
    UBYTE  repeats2; // repeat count (0..2 = play once, 3..? = play 2 or more times) 
    UBYTE  volume2;   // volume 00 to 40 (max should be 3F weird, perhaps volum 01 is 00 and 00 is channel off)

    USHORT enum anfiCommand command3;   // What to do, see above
    USHORT frequencyDivider3; // frequency divider (Amiga's audio.device)
    UBYTE  sound3; // Sound Number (starting at 1).
    UBYTE  channel3;    // Channel number (1 to 4, 0=invalid)
    UBYTE  repeats3; // repeat count (0..2 = play once, 3..? = play 2 or more times) 
    UBYTE  volume3;   // volume 00 to 40 (max should be 3F weird, perhaps volum 01 is 00 and 00 is channel off)

    USHORT enum anfiCommand command4;   // What to do, see above
    USHORT frequencyDivider4; // frequency divider (Amiga's audio.device)
    UBYTE  sound4; // Sound Number (starting at 1).
    UBYTE  channel4;    // Channel number (1 to 4, 0=invalid)
    UBYTE  repeats4; // repeat count (0..2 = play once, 3..? = play 2 or more times) 
    UBYTE  volume4;   // volume 00 to 40 (max should be 3F weird, perhaps volum 01 is 00 and 00 is channel off)
    UBYTE[4] pad4;       // For future use 
} animANFIChunk;

/*
 * ANIM: ILBM SXHD
 * --------------------------------------------
 */
set {
    channelLeft = 1, 
    channelRight = 2, 
    channelCenter = 4,
    surroundChannelOrSurroundLeft = 8, 
    surroundRight = 16,
    subwooferEffectChannel = 32
} sxhdUsedChannels;

enum {
    modeMono = 1, 
    modeStereo = 2, 
    threeChannel = 3,
    dtsQuadro = 4, 
    dolbySurround = 5,
    dts50AC3 = 6,
    dts51AC3 = 7
} sxhdUsedMode;

typedef struct {
    UBYTE sampleDepth; // depth of the Sample in unit Bits, most common is 8
                       // but all others from 1 Bit up to 32 Bits are
                       // (theoretical) possible
    UBYTE fixedVolume; // Amiga-typical unit for playback-volume, 0 is off and
                       // 64 is maximum
    ULONG length;      // length of a SBDY-chunk of ONE frame. This length is
                       // calculated for a constant playbackspeed. If speed
                       // varies from frame to frame the length of the
                       // SBDY-samplechunk also varies and this value is
                       // invalid and/or set to 0
    ULONG playRate;    // Amiga-typical unit for playback-speed; if you like to
                       // use the duration of sampleplayback for the synchroni-
                       // sation of the anim-playrate or if you use a soundcard,
                       // you better should use "PlayFreq"
    ULONG compressionMethod; //  has to be =0 in anims everytime, because the
                       // AnimPlayer became slower and Dolby-Surround-
                       // informations will be destroyed by all known
                       // compressions
    UBYTE set sxhdUsedChannels usedChannels;
                        // Flag for number and type of channels saved in the
                        // SBDY-chunk:
                        //  1 - Channel left
                        //  2 - Channel right
                        //  4 - Channel center
                        // Left and right together or center are supported this
                        // time, but following channels are theoretical also
                        // possible:
                        //  8 - Surroundchannel or surround left
                        // 16 - Surround right
                        // 32 - Subwoofer effectchannel
   UBYTE enum sxhdUsedMode UsedMode;
                        // says, wich soundmode has to be used:
                        //  1: Mode Mono (center-channel only)
                        //  2: Mode Stereo (channels left and right)
                        // Following modes are also possible but not supported
                        // yet:
                        //  3 - 3.0 3Channel
                        //  4 - 4.0 DTS-Quadro
                        //  5 - 4.0 DolbySurround
                        //  6 - 5.0 DTS / AC-3
                        //  7 - 5.1 DTS / AC-3
   LONG playFreq;       // play-/samplefrequency, spezifies the correct playspeed
   UWORD loop;          // Number of loops; says how often anim has to be repeated
                        // after first playback
                        // Loop=0 - No loop, leave the anim with the last frame
                        // Loop > 0 - Loop, repeat the anim for "Loop" times
                        // NOTE: if it is a looped anim, the first two frames
                        //    have been appended to the end of the anim AND
                        //    these frames include sounddata!
} animSoundHeaderChunk;

/* ============================================
 *
 * "ILBM" IFF Interleaved Bitmap
 *
 * ============================================
 */
/*  IFF types we may encounter  */
magic InterleavedBitmapImageForm "FORMILBM";
description InterleavedBitmapImageForm "IFF Interleaved Bitmap", "ILBM is a machine independent format for raster images. An Image consists of an interleaved bitmap with color map. ILBM is the standard image file format for the Commodore-Amiga computer.";

/* ILBM Chunk ID's we may encounter
 */
magic ilbmBitmapHeaderChunk "ILBMBMHD";
description ilbmBitmapHeaderChunk "Bitmap Header", "The required property BMHD describes the dimensions of the image, the encoding used, and other data necessary to understand the BODY chunk to follow.";
magic ilbmColorMapChunk "ILBMCMAP";
description ilbmColorMapChunk "Color Map", "The optional property CMAP stores color map data as triplets of red, green, and blue intensity values.";

magic ilbmColorRegisterRangeChunk "ILBMCRNG";
description ilbmColorRegisterRangeChunk "Color Register Range", "The optional collection property CRNG contains 'color register range' information. It's used by Electronic Arts' Deluxe Paint program to identify a contiguous range of color registers for a 'shade range' and color cycling.";

magic ilbmColorCyclingRangeAndTimingChunk "ILBMCCRT";
description ilbmColorCyclingRangeAndTimingChunk "Color Cycling Range and Timing", "The optional collection property CCRT contains 'color cycling range and timing' information. It's used by Commodore's Graphicraft program to identify a contiguous range of color registers for a 'shade range' and color cycling.";

magic ilbmDRangeChunk "ILBMDRNG";
description ilbmDRangeChunk "DPaint IV enhanced color cycle chunk", "The optional collection property DRNG contains color cycling information. It's used by Electronic Arts' Deluxe Paint IV program to identify a non-contiguous range of color registers and/or RGB values for color cycling.";

magic ilbmGrabChunk "ILBMGRAB";
description ilbmGrabChunk "Grab", "The optional property GRAB locates a 'handle' or 'hotspot' of the image relative to its upper left corner, e.g., when uses as a mouse cursor or a 'paint brush'.";
magic ilbmSpritePrecedenceChunk "ILBMSPRT";
description ilbmSpritePrecedenceChunk "Split Precedence", "The optional property SPRT indicates that this image is intended as a sprite.";
magic ilbmDestinationMergeChunk "ILBMDEST";
description ilbmDestinationMergeChunk "Destination Merge", "The optional property DEST is a way to say how to scatter zero or more source bitplanes into a deeper destination image.";
magic ilbmAmigaViewportModeDisplayIDChunk  "ILBMCAMG";
description ilbmAmigaViewportModeDisplayIDChunk "Amiga Viewport Mode Display ID", "A CAMG chunk is specifically for Commodore Amiga ILBM's. It is used to store the Amiga display mode in which an ILBM is meant to be displayed. This is very important, especially for special display modes such as HAM and HALFBRITE where the pixels are interpreted differently.";
magic ilbmBitmapBodyChunk "ILBMBODY";
description ilbmBitmapBodyChunk "Bitmap Body", "The data chunk BODY holds all bitplanes and the optional mask, interleaved by one row.";
magic ilbmDPIChunk "ILBMDPI ";
description ilbmDPIChunk "Dots Per Inch", "Specifies the dots per inch to allow output of an image at the same resolution it was scanned at.";

/*
 * ILBM BMHD Bitmap Header
 * --------------------------------------------
 */

/*  Masking techniques  */
enum {
    none=0, hasMask=1, hasTransparentColor=2, lasso=3
} bmhdMasking;

/*  Compression methods */
enum {
    none=0, 
    byteRun1=1,
    vertical=2 // Used by Deluxe Paint ST
} bmhdCompression;

typedef struct {
    UWORD   width; UWORD height;           /* Width, height in pixels */
    WORD    xPosition; WORD yPosition;           /* x, y position for this bitmap  */
    UBYTE   numberOfPlanes;        /* # of planes (not including mask) */
    UBYTE enum bmhdMasking masking;        /* a masking technique listed above */
    UBYTE enum bmhdCompression compression;    /* cmpNone or cmpByteRun1 */
    UBYTE   reserved1;      /* must be zero for now */
    UWORD   transparentColor;
    UBYTE   xAspect; UBYTE yAspect;
    WORD    pageWidth; WORD pageHeight;
} ilbmBitmapHeaderChunk;

/*
 * ILBM CMAP Color map
 * --------------------------------------------
 */
/* A CMAP chunk is a packed array of ColorRegisters (3 bytes each). */
typedef struct {
    uint8[3] rgb;   /* MUST be UBYTEs so ">> 4" won't sign extend.*/
} ilbmColorRegister;

typedef struct {
    ilbmColorRegister color[];
} ilbmColorMapChunk;

/*
 * ILBM GRAB Grab
 * --------------------------------------------
 */
/* A Point2D is stored in a GRAB chunk. */
typedef struct {
    WORD x; WORD y;      /* coordinates (pixels) */
} ilbmPoint2D;

typedef struct {
   ilbmPoint2D grab;
} ilbmGrabChunk;

/*
 * ILBM DEST Bitplane destination
 * --------------------------------------------
 */
/* A DestMerge is stored in a DEST chunk. */
typedef struct {
    UBYTE depth;   /* # bitplanes in the original source */
    UBYTE pad1;      /* UNUSED; for consistency store 0 here */
    UWORD planePick;   /* how to scatter source bitplanes into destination */
    UWORD planeOnOff;   /* default bitplane data for planePick */
    UWORD planeMask;   /* selects which bitplanes to store into */
} ilbmDestinationMergeChunk;

/*
 * ILBM SPRT Sprite Precedence
 * --------------------------------------------
 */
/* A SpritePrecedence is stored in a SPRT chunk. */
typedef UWORD ilbmSpritePrecedenceChunk;

/*
 * ILBM CAMG Amiga Viewport Mode Display ID
 * --------------------------------------------
 */
/* The CAMG chunk is used to store the Amiga display mode in which
 * an ILBM is meant to be displayed.  This is very important, especially
 * for special display modes such as HAM and HALFBRITE where the
 * pixels are interpreted differently.
 * Under V37 and higher, store a 32-bit Amiga DisplayID (aka. ModeID)
 * in the ULONG ViewModes CAMG variable (from GetVPModeID(viewport)).
 * Pre-V37, instead store the 16-bit viewport->Modes.
 * See the current IFF manual for information on screening for bad CAMG
 * chunks when interpreting a CAMG as a 32-bit DisplayID or 16-bit ViewMode.
 * The chunk's content is declared as a ULONG.
 */

set {
   Interlace      = 0x00004,
   ExtraHalfbrite = 0x00080,
   DualPlayfield  = 0x00400,
   HoldAndModify  = 0x00800,
   Hires          = 0x08000,
   Super          = 0x08020
} ilbmAmigaViewModes;

typedef struct {
    ULONG set ilbmAmigaViewModes ViewModes;
} ilbmAmigaViewportModeDisplayIDChunk;

/*
 * ILBM CRNG Color range cycling
 * --------------------------------------------
 */
//#define RNG_NORATE  36   /* Dpaint uses this rate to mean non-active */
set {
    active = 1, reverse = 2,reverseDPaint = 0x20
} crngActive;

/* A CRange is store in a CRNG chunk. */
typedef struct {
    WORD  pad1;              /* reserved for future use; store 0 here */
    WORD  rate;              /* 60/sec=16384, 30/sec=8192, 1/sec=16384/60=273 */
    WORD set crngActive flags;     /* bit0 set = active, bit 1 set = reverse */
    UBYTE low; UBYTE high;         /* lower and upper color registers selected */
} ilbmColorRegisterRangeChunk;

/*
 * ILBM CCRT Color cycling range and timing
 * --------------------------------------------
 */
enum {
    dontCycle = 0, forward = 1, backwards = -1
} ccrtDirection;
typedef struct {
   WORD enum ccrtDirection direction;  /* 0=don't cycle, 1=forward, -1=backwards */
   UBYTE start;      /* range lower */
   UBYTE end;        /* range upper */
   ULONG  seconds;    /* seconds between cycling */
   ULONG  microseconds; /* msecs between cycling */
   WORD  pad;        /* future exp - store 0 here */
} ilbmColorCyclingRangeAndTimingChunk;

/*
 * ILBM DRNG DPaint IV enhanced color cycle chunk
 * --------------------------------------------
 * The RNG_ACTIVE flag is set when the range is cyclable. A range should
 * only have the RNG _ACTIVE if it:
 *
 * 1 - contains at least one color register
 * 2 - has a defined rate
 * 3 - has more than one color and/or color register
 */

set {
    active=1,DPReserved=4 /* RNG_ACTIVE and RNG_DP_RESERVED */
} drngFlags;

/* True color cell */
typedef struct {
    UBYTE cell;
    UBYTE r;
    UBYTE g;
    UBYTE b;
} ilbmDRNGDColor;

/* Color register cell */
typedef struct {
    UBYTE cell;
    UBYTE index;
} ilbmDRNGDIndex;

/* DRNG chunk. */
typedef struct {
    UBYTE min; /* min cell value */
    UBYTE max; /* max cell value */
    UWORD rate; /* color cycling rate, 16384 = 60 steps/second */
    UWORD set drngFlags flags; /* 1=RNG_ACTIVE, 4=RNG_DP_RESERVED */
    UBYTE ntrue; /* number of DColor structs to follow */
    UBYTE ntregs; /* number of DIndex structs to follow */
    ilbmDRNGDColor[ntrue] trueColorCells;
    ilbmDRNGDIndex[ntregs] colorRegisterCells;
} ilbmDRangeChunk;


/*
 * ILBM DPI Dots per Inch
 * --------------------------------------------
 */
typedef struct {
    UWORD dpiX;
    UWORD dpiY;
} ilbmDPIChunk;

/* ============================================
 *
 * "PBM" IFF Pixel Bitmap
 *
 * ============================================
 */
/*  IFF types we may encounter  */
magic PixelBitmapImageForm "FORMPBM ";
description PixelBitmapImageForm "IFF Pixel Bitmap", "File format for images used by Deluxe Paint II Enhanced and Deluxe Paint Animation for IBM Personal System/2 and IBM compatible-computers.";

/* PBM Chunk ID's we may encounter
 */
magic ilbmBitmapHeaderChunk "PBM BMHD";
magic ilbmColorMapChunk "PBM CMAP";
magic ilbmColorRegisterRangeChunk "PBM CRNG";
magic ilbmColorCyclingRangeAndTimingChunk "PBM CCRT";
magic ilbmGrabChunk "PBM GRAB";
magic ilbmSpritePrecedenceChunk "PBM SPRT";
magic ilbmDestinationMergeChunk "PBM DEST";
magic ilbmAmigaViewportModeDisplayIDChunk  "PBM CAMG";
magic ilbmBitmapBodyChunk "PBM BODY";
magic ilbmDPIChunk "PBM DPI ";
magic animDPAnimChunk "PBM DPAN";
magic animAnimHdrChunk "PBM ANHD";
magic animAnimDeltaChunk "PBM DLTA";
magic animSoundControlChunk "PBM SCTL";
magic animANFIChunk "PBM ANFI";
magic animSoundHeaderChunk "PBM SXHD";
magic animSoundBodyChunk "PBM SBDY";

/* ============================================
 *
 * "FTXT" IFF Formatted Text
 *
 * ============================================
 */
/*  IFF types we may encounter  */
magic FormattedTextForm "FORMFTXT";
description FormattedTextForm "IFF Formatted Text", "An FTXT data section contains text with character formatting information like fonts and faces. It has no paragraph or document formatting information like margins and page headers.";

/* FTXT Chunk ID's we may encounter
 */
magic ftxtCharactersChunk "FTXTCHRS";
description ftxtCharactersChunk "Characters", "A CHRS chunk contains a sequence of 8-bit characters abiding by the ISO/ANSI standards. This includes the character set and control sequences.";

magic ftxtFontSpecifierChunk "FTXTFONS";
description ftxtFontSpecifierChunk "Font Specifier", "The optional property FONS holds a font specifier. It assings a font to a numbered 'font register' so it can be referenced by number within subsequent 'CHRS' chunks. The font specifier gives both a name and a description for the font so the recipient program can do font substitution.";


/*
 * FTXT CHRS Characters
 * --------------------------------------------
 */
typedef struct {
    cstring chars;
} ftxtCharactersChunk;

/*
 * FTXT FONS Font Specifier
 * --------------------------------------------
 */
/* Note - for convenience, this structure is defined with a name array
 * of Amiga MAXFONTPATH size.  The size of actual FONS chunks will
 * depend on the length of the name stored in the chunk
 */

enum {
    unknown = 0, no = 1, yes = 2
} fontsSpecifier;

typedef struct {
        UBYTE id;       /* 0 through 9 is a font id number referenced by an SGR
                        control sequence selective parameter of 10 through 19.
                        Other values are reserved for future standardization.   */

        UBYTE pad1;             /* reserved for future use; store 0 here        */

        UBYTE enum fontsSpecifier proportional;     /* proportional font? 0 = unknown, 1 = no, 2 = yes      */

        UBYTE enum fontsSpecifier serif;            /* serif font? 0 = unknown, 1 = no, 2 = yes     */

        cstring name;         /* A NULL-terminated string naming the preferred font.   */
} ftxtFontSpecifierChunk;



/* ============================================
 *
 * "SMUS" IFF Simple Musical Score
 *
 * ============================================
 */
/*  IFF types we may encounter  */
magic SimpleMusicalScoreForm "FORMSMUS";
description SimpleMusicalScoreForm "IFF Simple Musical Score", "SMUS is a simple musical score format.";

/* SMUS Chunk ID's we may encounter
 */
magic smusScoreHeaderChunk "SMUSSHDR";
description smusScoreHeaderChunk "Score Header", "The required property SHDR specifies global information for the musical score.";
magic smusRefInstrumentChunk "SMUSINS1";
description smusRefInstrumentChunk "Instrument Reference", "The optional collection property INS1 identifies the instruments to use for this score. A program can ignore INS1 chunks and stick with its built-in default instruments assignments. Or it can use them to locate instrument data.";
magic smusRefInstrumentObsoleteChunk "SMUSINST";
description smusRefInstrumentObsoleteChunk "Instrument Reference (Obsolete)", "The chunk type INST is obsolete in SMUS. It was revised to form the 'INS1' chunk.";
magic smusTrackChunk "SMUSTRAK";
description smusTrackChunk  "Score Track", "The main contents of a score is stored in one or more TRAK chunks representing parallel 'tracks'. One TRAK chunk per track.";


/*
 * SMUS SHDR Score Header
 * --------------------------------------------
 */
typedef struct {
    UWORD tempo;        /* tempo, 128ths quarter note/minute */
    UBYTE volume;       /* playback volume 0 through 127 */
    UBYTE trackCount;      /* count of tracks in the score */
} smusScoreHeaderChunk;

/*
 * SMUS INS1 Ref Instrument
 * --------------------------------------------
 */
/* Constants for the RefInstrument's "type" field. */
//#define INS1_Name  0    /* just use the name; ignore data1, data2 */
//#define INS1_MIDI  1    /* <data1, data2> = MIDI <channel, preset> */
enum {
   name = 0, midi = 1
} ins1Type;

typedef struct {
    UBYTE iRegister;    /* set this instrument register number */
    UBYTE enum ins1Type type;         /* instrument reference type (see above) */
    UBYTE data1; UBYTE data2; /* depends on the "type" field */
    cstring name;      /* instrument name */
} smusRefInstrumentChunk;

/*
 * SMUS TRAK Track
 * --------------------------------------------
 */
/* TRAK chunk contains an SEvent[]. */

/* SEvent: Simple musical event. */
typedef struct {
    UBYTE enum SEventSID sID;          /* SEvent type code */
    UBYTE data;         /* sID-dependent data */
} trackSEvent;


typedef struct {
    trackSEvent sEvent[];
} smusTrackChunk;

/* SEvent type codes "sID". */
/*
enum {
   FirstNote   =   0,
   LastNote    = 127,  /* sIDs in the range SID_FirstNote through
                        * SID_LastNote (sign bit = 0) are notes. The
                        * sID is the MIDI tone number (pitch). * /
   Rest        = 128,  /* a rest; same data format as a note. * /

   Instrument  = 129,  /* set instrument number for this track. * /
   TimeSig     = 130,  /* set time signature for this track. * /
   KeySig      = 131,  /* set key signature for this track. * /
   Dynamic     = 132,  /* set volume for this track. * /
   MIDI_Chnl   = 133,  /* set MIDI channel number (sequencers) * /
   MIDI_Preset = 134,  /* set MIDI preset number (sequencers) * /
   Clef        = 135,  /* inline clef change.
                        * 0=Treble, 1=Bass, 2=Alto, 3=Tenor. * /
   Tempo       = 136,  /* Inline tempo change in beats per minute.* /

   /* SID values 144 through 159: reserved for Instant Music SEvents. * /

   /* The remaining sID values up through 254: reserved for future
    * standardization. * /
   Mark        = 255   /* SID reserved for an end-mark in RAM. * /
} smusSEventSID;
*/


/* ============================================
 *
 * "DPST" Deluxe Paint for Atari ST Animation
 *
 * ============================================
 */
/*  IFF types we may encounter  */
magic dpstIFFForm "FORMDPST";
description dpstIFFForm "Deluxe Paint ST Animation", "DPST is an optimized animation format for Atari ST Computers used by Deluxe Paint.";

/* Chunk ID's we may encounter
 */
magic dpstDPAHChunk "DPSTDPAH";
description dpstDPAHChunk "Deluxe Paint Anim Header", "";
magic dpstVDLTForm "FORMVDLT";
description dpstVDLTForm "Vertical Delta", "";
magic vdltADATChunk "VDLTADAT";
description vdltADATChunk "Anim Data",
    "The ADAT chunk is the basic data chunk used to hold delta compression data"
    +" for a single bitplane of an image.";


typedef struct {
    UWORD relativeTime;
    UWORD numberOfFrames;   /* number of frames in the animation.*/
    UWORD[] unknown;
} dpstDPAHChunk;
