/*
 * @(#)RIFFChunks.txt  1.1.1  2011-08-22
 *
 * Copyright (c) 2005-2011 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 Resource Interchange File Format (RIF)
 * data structures.
 *
 * @author Werner Randelshofer, Hausmatt 10, CH-6405 Immensee, Switzerland
 * @version 1.1.1 2011-08-22 Adds enum values to wFormatTagEnum.
 * <br>1.1 2010-07-06 Adds info for the strl strd chunk.
 * <br>1.0 2005-01-09 Created.
 */

/* ============================================
 *
 * Primitive Data Types
 *
 * ============================================
 */
/* Numbers */
typedef ubyte    BYTE;    //  8 bits unsigned
typedef ubyte    UInt8;   //  8 bits unsigned
typedef shortLE  Int16;   // 16 bits signed little endian
typedef shortLE  WORD;    // 16 bits signed little endian
typedef ushortLE UInt16;  // 16 bits unsigned little endian
typedef intLE    Int32;   // 32 bits signed little endian
typedef uintLE   UInt32;  // 32 bits unsigned little endian
typedef intLE    DWORD;   // 32 bits signed little endian
typedef intLE    LONG;    // 32 bits signed little endian
typedef magic    FOURCC;  // Four character code


/* ============================================
 *
 * "WAVE" Wave Form Audio
 * As described at
 * http://ccrma.stanford.edu/courses/422/projects/WaveFormat/
 *
 * ============================================
 */
/*  Form types we may encounter  */
magic WaveForm "RIFFWAVE";
description WaveForm "Wave Form Audio", "The Wave Form Audio (WAV) file format is used to store sounds as waveforms.";

/* Chunk ID's we may encounter
 */
magic WaveFormatChunk "WAVEfmt ";
description WaveFormatChunk "Format", "The required property 'fmt ' describes the format of the sampled waveforms in the 'data' chunk.";
magic WaveDataChunk "WAVEdata";
description WaveDataChunk "Data", "The 'data' chunk contains audio data samples.";

enum {
    pcm = 1 // Linear quantization 
} waveAudioFormat;

enum {
    mono = 1,
    stereo = 2
} waveNumChannels;
/*
 * Wave Fmt Format
 * --------------------------------------------
 */
typedef struct {
    UInt16 enum waveAudioFormat audioFormat; 
                           // PCM = 1, values other than 1 
                           // indicate some form of compression.
    UInt16 enum waveNumChannels numChannels;  
    UInt32 sampleRate;     // Samples per sec.
    UInt32 byteRate;       // == SampleRate * NumChannels * BitsPerSample/8
    UInt16 blockAlign;     // == NumChannels * BitsPerSample/8
                           // The number of bytes for one sample including
                           // all channels. I wonder what happens when
                           //    this number isn't an integer?
    UInt16 bitsPerSample;  // 8 bits = 8, 16 bits = 16, etc.
    UInt16 extraParamSize; // if PCM, then doesn't exist
    UInt8[] extraParams;   // space for extra parameters
} WaveFormatChunk;


/* ============================================
 *
 * "AVI" Audio Video Interleave
 * http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/htm/avirifffilereference.asp
 *
 * ============================================
 */
/*  Form types we may encounter  */
magic AVIForm "RIFFAVI ";
description AVIForm "Audio Video", "The Audio Video (AVI) file format is used with applications that capture, edit, and play back audio-video sequences.";

/* Chunk ID's we may encounter
 */
magic AVIHeaderListChunk "LISThdrl";
description AVIHeaderListChunk "Header List", "The 'hdrl' list defines the format of the data and is the first required LIST chunk in an AVI file.";
magic AVIMAINHEADER "hdrlavih";
description AVIMAINHEADER "Main Header", "The AVI Main Header structure defines global information in an AVI file.";
magic AVIStreamHeaderListChunk "LISTstrl";
description AVIStreamHeaderListChunk "Stream Header List", "A 'strl' list is required for each data stream. Each 'strl' list contains information about one stream in the file.";
magic AVISTREAMHEADER "strlstrh";
description AVISTREAMHEADER "Stream Header", "The AVI Stream Header structure contains information about one stream in an AVI file.";

magic AVIStreamFormatChunk "strlstrf";
description AVIStreamFormatChunk "Stream Format", "A stream format chunk ('strf') must follow the stream header chunk. The stream format chunk describes the format of the data in the stream. The data contained in this chunk depends on the stream type. For video streams, the information is a BITMAPINFO structure, including palette information if appropriate. For audio streams, the information is a WAVEFORMATEX structure.";

magic BITMAPINFOHEADER "strlstrfvids";
description BITMAPINFOHEADER "Bitmap Info Header (BITMAPINFOHEADER)", "The BITMAPINFOHEADER structure contains information about the dimensions and color format of a device-independent bitmap (DIB).";
magic WAVEFORMATEX "strlstrfauds";
description WAVEFORMATEX "Wave Format Header (WAVEFORMATEX)", "The WAVEFORMATEX structure defines the format of waveform-audio data. Only format information common to all waveform-audio data formats is included in this structure. For formats that require additional information, this structure is included as the first member in another structure, along with the additional information.";

magic AVIStreamName "strlstrn";
description AVIStreamName "Stream Name", "Specifies the name of the stream.";
magic AVIMovieList "LISTmovi";
description AVIMovieList "Stream Data", "Following the header information is a 'movi' list that contains the actual data in the streams -  that is, the video frames and audio samples. The data chunks can reside directly in the 'movi' list, or they might be grouped within 'rec ' lists. The 'rec ' grouping implies that the grouped chunks should be read from disk all at once, and is intended for files that are interleaved to play from CD-ROM.";
magic AVIMovie00db "movi00db";
description AVIMovie00db "Uncompressed Video Frame", "Uncompressed video frame in stream 0.";
magic AVIMovie01db "movi01db";
description AVIMovie01db "Uncompressed Video Frame", "Uncompressed video frame in stream 1.";
magic AVIMovie00dc "movi00dc";
description AVIMovie00dc "Compressed Video Frame", "Compressed video frame in stream 0.";
magic AVIMovie01dc "movi01dc";
description AVIMovie01dc "Compressed Video Frame", "Compressed video frame in stream 1.";
magic AVIMovie02dc "movi02dc";
description AVIMovie02dc "Compressed Video Frame", "Compressed video frame in stream 2.";
magic AVIPALCHANGE00 "movi00pc";
description AVIPALCHANGE00 "Palette Change", "Palette change in stream 0.";
magic AVIPALCHANGE01 "movi01pc";
description AVIPALCHANGE01 "Palette Change", "Palette change in stream 1.";
magic AVIMovie00wb "movi00wb";
description AVIMovie00wb "Audio Data", "Audio data in stream 0.";
magic AVIMovie01wb "movi01wb";
description AVIMovie01wb "Audio Data", "Audio data in stream 1.";
magic AVIOLDINDEX "AVI idx1";
description AVIOLDINDEX "AVI Index", "An optional index ('idx1') chunk can follow the 'movi' list. The index contains a list of the data chunks and their location in the file. It consists of an AVIOLDINDEX structure with entries for each data chunk, including 'rec ' chunks. If the file contains an index, set the AVIF_HASINDEX flag in the dwFlags member of the AVIMAINHEADER structure.";
magic AVIText "INFOICMT";
magic AVIJunk "AVI JUNK";
description AVIJunk "Data Alignment", "Data can be aligned in an AVI file by inserting 'JUNK' chunks as needed. Files played from CD-ROM use these chunks to align data for the 2 kilobyte CD-ROM boundaries, so they can be read more efficiently. Applications should ignore the contents of a 'JUNK' chunk.";

/* Vendor specific chunks.
 */
magic AVIStreamDescription "strlstrd";
description AVIStreamDescription "Fujifilm Stream Description", "This chunk contains EXIF meta data about the stream. The data is represented using a TIFF image file directory (IFD) data structure.";



/* ---------------
 * AVI Main Header
 * ---------------
 */
// Set values taken from
// http://graphics.cs.uni-sb.de/NMM/dist-0.4.0/Docs/Doxygen/html/avifmt_8h.html
set {
   hasIndex = 0x00000010,
                        // Indicates the AVI file has an index.
   mustUseIndex = 0x00000020,
                        // Indicates that application should use the index, 
                        // rather than the physical ordering of the chunks in 
                        // the file, to determine the order of presentation of 
                        // the data. For example, this flag could be used to 
                        // create a list of frames for editing.
   isInterleaved = 0x00000100,
                        // Indicates the AVI file is interleaved.
   trustCKType = 0x00000800,
                        // ???
   wasCaptureFile = 0x00010000,
                        // Indicates the AVI file is a specially allocated file
                        // used for capturing real-time video. Applications 
                        // should warn the user before writing over a file with
                        // this flag set because the user probably defragmented 
                        // this file.
   copyrighted = 0x00020000
                        // Indicates the AVI file contains copyrighted data and 
                        // software. When this flag is used, software should not
                        // permit the data to be duplicated.
} avihFlags;


typedef struct {
    DWORD  microSecPerFrame;
            // Specifies the number of microseconds between frames. 
            // This value indicates the overall timing for the file.
    DWORD  maxBytesPerSec;
            // Specifies the approximate maximum data rate of the file. This 
            // value indicates the number of bytes per second the system must
            // handle to present an AVI sequence as specified by the other  
            // parameters contained in the main header and stream header chunks.
    DWORD  paddingGranularity;
            // Specifies the alignment for data, in bytes. Pad the data to 
            // multiples of this value.
    DWORD set avihFlags  flags;
            // Contains a bitwise combination of zero or more of the following flags:
    DWORD  totalFrames;
            // Specifies the total number of frames of data in the file.
    DWORD  initialFrames;
            // Specifies the initial frame for interleaved files. Noninterleaved
            // files should specify zero. If you are creating interleaved files,
            // specify the number of frames in the file prior to the initial 
            // frame of the AVI sequence in this member. For more information 
            // about the contents of this member, see "Special Information for
            // Interleaved Files" in the Video for Windows Programmer's Guide.
    DWORD  streams;
            // Specifies the number of streams in the file. For example, a file 
            // with audio and video has two streams.
    DWORD  suggestedBufferSize;
            // Specifies the suggested buffer size for reading the file. 
            // Generally, this size should be large enough to contain the 
            // largest chunk in the file. If set to zero, or if it is too small,
            // the playback software will have to reallocate memory during 
            // playback, which will reduce performance. For an interleaved file,
            // the buffer size should be large enough to read an entire record, 
            // and not just a chunk.
    DWORD  width;
            // Specifies the width of the AVI file in pixels.
    DWORD  height;
            // Specifies the height of the AVI file in pixels.
    DWORD[]  reserved;
            // Reserved. Set this array to zero.
} AVIMAINHEADER;


/* -----------------
 * AVI Stream Header
 * -----------------
 */
enum {
    audioStream = "auds",
    midiStream = "mids",
    textStream = "txts",
    videoStream = "vids"
} aviStrhType;

// Values for this set taken from
// http://graphics.cs.uni-sb.de/NMM/dist-0.4.0/Docs/Doxygen/html/avifmt_8h.html
set {
    disabled = 0x00000001, // Indicates this stream should not be enabled by default.
    videoPaletteChanges = 0x00010000 
        // Indicates this video stream contains palette changes. This flag 
        // warns the playback software that it will need to animate the palette.
} aviStrhFlags;

typedef struct {
    Int16 left;
    Int16 top;
    Int16 right;
    Int16 bottom;
} aviRectangle;

typedef struct {
     FOURCC enum aviStrhType type; 
        // Contains a FOURCC that specifies the type of the data contained in 
        // the stream. The following standard AVI values for video and audio are 
        // defined.
     FOURCC handler;
        // Optionally, contains a FOURCC that identifies a specific data
        // handler.
        // The data handler is the preferred handler for the stream. For audio 
        // and video streams, this specifies the codec for decoding the stream.
     DWORD  set aviStrhFlags flags;
        // Contains any flags for the data stream. The bits in the high-order 
        // word of these flags are specific to the type of data contained in the
        // stream. 
     WORD   priority;
        // Specifies priority of a stream type. For example, in a file with 
        // multiple audio streams, the one with the highest priority might be 
        // the default stream.
     WORD   language;
     DWORD  initialFrames;
        // Specifies how far audio data is skewed ahead of the video frames in
        // interleaved files. Typically, this is about 0.75 seconds. If you are
        // creating interleaved files, specify the number of frames in the file 
        // prior to the initial frame of the AVI sequence in this member. For 
        // more information about the contents of this member, see "Special 
        // Information for Interleaved Files" in the Video for Windows 
        // Programmer's Guide.
     DWORD  timeScale;
        // Used with "rate" to specify the time scale that this stream will use.
        // Dividing "rate" by "timeScale" gives the number of samples per second.
        // For video streams, this is the frame rate. For audio streams, this 
        // rate corresponds to the time needed to play nBlockAlign bytes of 
        // audio, which for PCM audio is the just the sample rate.
     DWORD  rate;
        // See "timeScale".
     DWORD  startTime;
        // Specifies the starting time for this stream. The units are defined by
        // the "rate" and "timeScale" members in the main file header. Usually, this
        // is zero, but it can specify a delay time for a stream that does not 
        // start concurrently with the file.
     DWORD  length;
        // Specifies the length of this stream. The units are defined by the 
        // "rate" and "timeScale" members of the stream's header.
     DWORD  suggestedBufferSize;
        // Specifies how large a buffer should be used to read this stream.
        // Typically, this contains a value corresponding to the largest chunk
        // present in the stream. Using the correct buffer size makes playback 
        // more efficient. Use zero if you do not know the correct buffer size.
     DWORD  quality;
        // Specifies an indicator of the quality of the data in the stream. 
        // Quality is represented as a number between 0 and 10,000. For 
        // compressed data, this typically represents the value of the quality 
        // parameter passed to the compression software. If set to �1, drivers 
        // use the default quality value.
     DWORD  sampleSize;
        // Specifies the size of a single sample of data. This is set to zero if
        // the samples can vary in size. If this number is nonzero, then
        // multiple samples of data can be grouped into a single chunk within 
        // the file. If it is zero, each sample of data (such as a video frame)
        // must be in a separate chunk. For video streams, this number is 
        // typically zero, although it can be nonzero if all video frames are 
        // the same size. For audio streams, this number should be the same as 
        // the nBlockAlign member of the WAVEFORMATEX structure describing the audio.
    aviRectangle frame;
        // Specifies the destination rectangle for a text or video stream within
        // the movie rectangle specified by the "frameWidth" and "frameHeight"
        // members of the AVI main header structure. The "frame" member is 
        // typically used in support of multiple video streams. Set this 
        // rectangle to the coordinates corresponding to the movie rectangle to 
        // update the whole movie rectangle. Units for this member are pixels. 
        // The upper-left corner of the destination rectangle is relative to the 
        // upper-left corner of the movie rectangle.
} AVISTREAMHEADER;

/* ----------------------
 * AVI Bitmap Info Header
 * ----------------------
 */
typedef struct {
  BYTE    blue; 
  BYTE    green; 
  BYTE    red; 
  BYTE    reserved; 
} RGBQUAD; 

// Values for this enum taken from:
// http://www.fourcc.org/index.php?http%3A//www.fourcc.org/rgb.php
enum {
    BI_RGB = 0x00000000,
    RGB = 0x32424752, // Alias for BI_RGB
    BI_RLE8 = 0x01000000,
    RLE8 = 0x38454C52, // Alias for BI_RLE8
    BI_RLE4 = 0x00000002, 
    RLE4 = 0x34454C52, // Alias for BI_RLE4
    BI_BITFIELDS = 0x00000003,
    raw = 0x32776173,
    RGBA = 0x41424752,
    RGBT = 0x54424752,
    cvid = "cvid"
} bitmapCompression;

typedef struct {
    DWORD  structSize;
        // Specifies the number of bytes required by the structure.
    LONG   width;
        // Specifies the width of the bitmap.
        // - For RGB formats, the width is specified in pixels.
        // - The same is true for YUV formats if the bitdepth is an even power 
        //   of 2.
        // - For YUV formats where the bitdepth is not an even power of 2, 
        //   however, the width is specified in bytes.
        // Decoders and video sources should propose formats where "width" is 
        // the width of the image. If the video renderer is using DirectDraw, it
        // modifies the format so that "width" equals the stride of the surface, 
        // and the "target" member of the VIDEOINFOHEADER or VIDEOINFOHEADER2 
        // structure specifies the image width. Then it proposes the modified 
        // format using IPin::QueryAccept.
        // For RGB and even-power-of-2 YUV formats, if the video renderer does 
        // not specify the stride, then round the width up to the nearst DWORD 
        // boundary to find the stride.
    LONG   height;
        // Specifies the height of the bitmap, in pixels.
        // - For uncompressed RGB bitmaps, if "height" is positive, the bitmap 
        //   is a bottom-up DIB with the origin at the lower left corner. If 
        //   "height" is negative, the bitmap is a top-down DIB with the origin 
        //   at the upper left corner.
        // - For YUV bitmaps, the bitmap is always top-down, regardless of the
        //   sign of "height". Decoders should offer YUV formats with postive 
        //   "height", but for backward compatibility they should accept YUV 
        //   formats with either positive or negative "height".
        // - For compressed formats, biHeight must be positive, regardless of 
        //   image orientation.
    WORD   planes;
        // Specifies the number of planes for the target device. This value must 
        // be set to 1.
    WORD   bitCount;
        // Specifies the number of bits per pixel.
    //DWORD enum bitmapCompression compression;
    FOURCC enum bitmapCompression compression;
        // If the bitmap is compressed, this member is a FOURCC the specifies 
        // the compression. 
        // Value         Description
        // BI_RLE8       A run-length encoded (RLE) format for bitmaps with 8 
        //               bpp. The compression format is a 2-byte format 
        //               consisting of a count byte followed by a byte containing a color index. For more information, see Bitmap Compression.
        // BI_RLE4       An RLE format for bitmaps with 4 bpp. The compression 
        //               format is a 2-byte format consisting of a count byte 
        //               followed by two word-length color indexes. For more 
        //               information, see Bitmap Compression.
        // BI_JPEG       Windows 98/Me, Windows 2000/XP: Indicates that the 
        //               image is a JPEG image.
        // BI_PNG        Windows 98/Me, Windows 2000/XP: Indicates that the 
        //               image is a PNG image.
        // For uncompressed formats, the following values are possible:
        // Value         Description
        // BI_RGB        Uncompressed RGB.
        // BI_BITFIELDS  Specifies that the bitmap is not compressed and that 
        //               the color table consists of three DWORD color masks 
        //               that specify the red, green, and blue components, 
        //               respectively, of each pixel. This is valid when used 
        //               with 16- and 32-bpp bitmaps.
    DWORD  imageSizeInBytes;
        // Specifies the size, in bytes, of the image. This can be set to 0 for 
        // uncompressed RGB bitmaps.
    LONG   xPelsPerMeter;
        // Specifies the horizontal resolution, in pixels per meter, of the 
        // target device for the bitmap.
    LONG   yPelsPerMeter;
        // Specifies the vertical resolution, in pixels per meter, of the target 
        // device for the bitmap.
    DWORD  numberOfColorsUsed;
        // Specifies the number of color indices in the color table that are 
        // actually used by the bitmap
    DWORD  numberOfColorsImportant;
        // Specifies the number of color indices that are considered important 
        // for displaying the bitmap. If this value is zero, all colors are 
        // important.
    RGBQUAD colors[];
        // If the bitmap is 8-bpp or less, the bitmap uses a color table, which 
        // immediately follows the BITMAPINFOHEADER. The color table consists of
        // an array of RGBQUAD values. The size of the array is given by the 
        // "clrUsed" member. If "clrUsed" is zero, the array contains the 
        // maximum number of colors for the given bitdepth; that is, 
        // 2^"bitCount" colors.
} BITMAPINFOHEADER;

/* ----------------------
 * AVI Wave Format Header
 * ----------------------
 */
// values for this enum taken from mmreg.h
enum {
        WAVE_FORMAT_PCM = 0x0001,
        /**  Microsoft Corporation  */
        WAVE_FORMAT_ADPCM = 0x0002,
        /**  Microsoft Corporation
         *   IEEE754: range (+1, -1]
         *  32-bit/64-bit format as defined by
         *  MSVC++ float/double type
         */
        WAVE_FORMAT_IEEE_FLOAT = 0x0003,
        /**  IBM Corporation  */
        WAVE_FORMAT_IBM_CVSD = 0x0005,
        /**  Microsoft Corporation  */
        WAVE_FORMAT_ALAW = 0x0006,
        /**  Microsoft Corporation  */
        WAVE_FORMAT_MULAW = 0x0007,
        /**  OKI  */
        WAVE_FORMAT_OKI_ADPCM = 0x0010,
        /**  Intel Corporation  */
        WAVE_FORMAT_DVI_ADPCM = 0x0011,
        /**  Intel Corporation  */
        WAVE_FORMAT_IMA_ADPCM = 0x0011,
        /**  Videologic  */
        WAVE_FORMAT_MEDIASPACE_ADPCM = 0x0012,
        /**  Sierra Semiconductor Corp  */
        WAVE_FORMAT_SIERRA_ADPCM = 0x0013,
        /**  Antex Electronics Corporation  */
        WAVE_FORMAT_G723_ADPCM = 0x0014,
        /**  DSP Solutions, Inc.  */
        WAVE_FORMAT_DIGISTD = 0x0015,
        /**  DSP Solutions, Inc.  */
        WAVE_FORMAT_DIGIFIX = 0x0016,
        /**  Dialogic Corporation  */
        WAVE_FORMAT_DIALOGIC_OKI_ADPCM = 0x0017,
        /**  Media Vision, Inc. */
        WAVE_FORMAT_MEDIAVISION_ADPCM = 0x0018,
        /**  Yamaha Corporation of America  */
        WAVE_FORMAT_YAMAHA_ADPCM = 0x0020,
        /**  Speech Compression  */
        WAVE_FORMAT_SONARC = 0x0021,
        /**  DSP Group, Inc  */
        WAVE_FORMAT_DSPGROUP_TRUESPEECH = 0x0022,
        /**  Echo Speech Corporation  */
        WAVE_FORMAT_ECHOSC1 = 0x0023,
        /**    */
        WAVE_FORMAT_AUDIOFILE_AF36 = 0x0024,
        /**  Audio Processing Technology  */
        WAVE_FORMAT_APTX = 0x0025,
        /**    */
        WAVE_FORMAT_AUDIOFILE_AF10 = 0x0026,
        /**  Dolby Laboratories  */
        WAVE_FORMAT_DOLBY_AC2 = 0x0030,
        /**  Microsoft Corporation  */
        WAVE_FORMAT_GSM610 = 0x0031,
        /**  Microsoft Corporation  */
        WAVE_FORMAT_MSNAUDIO = 0x0032,
        /**  Antex Electronics Corporation  */
        WAVE_FORMAT_ANTEX_ADPCME = 0x0033,
        /**  Control Resources Limited  */
        WAVE_FORMAT_CONTROL_RES_VQLPC = 0x0034,
        /**  DSP Solutions, Inc.  */
        WAVE_FORMAT_DIGIREAL = 0x0035,
        /**  DSP Solutions, Inc.  */
        WAVE_FORMAT_DIGIADPCM = 0x0036,
        /**  Control Resources Limited  */
        WAVE_FORMAT_CONTROL_RES_CR10 = 0x0037,
        /**  Natural MicroSystems  */
        WAVE_FORMAT_NMS_VBXADPCM = 0x0038,
        /** Crystal Semiconductor IMA ADPCM */
        WAVE_FORMAT_CS_IMAADPCM = 0x0039,
        /** Echo Speech Corporation */
        WAVE_FORMAT_ECHOSC3 = 0x003A,
        /** Rockwell International */
        WAVE_FORMAT_ROCKWELL_ADPCM = 0x003B,
        /** Rockwell International */
        WAVE_FORMAT_ROCKWELL_DIGITALK = 0x003C,
        /** Xebec Multimedia Solutions Limited */
        WAVE_FORMAT_XEBEC = 0x003D,
        /**  Antex Electronics Corporation  */
        WAVE_FORMAT_G721_ADPCM = 0x0040,
        /**  Antex Electronics Corporation  */
        WAVE_FORMAT_G728_CELP = 0x0041,
        /**  Microsoft Corporation  */
        WAVE_FORMAT_MPEG = 0x0050,
        /**  ISO/MPEG Layer3 Format Tag */
        WAVE_FORMAT_MPEGLAYER3 = 0x0055,
        /**  Cirrus Logic  */
        WAVE_FORMAT_CIRRUS = 0x0060,
        /**  ESS Technology  */
        WAVE_FORMAT_ESPCM = 0x0061,
        /**  Voxware Inc  */
        WAVE_FORMAT_VOXWARE = 0x0062,
        /**  Canopus, co., Ltd.  */
        WAVE_FORMAT_CANOPUS_ATRAC = 0x0063,
        /**  APICOM  */
        WAVE_FORMAT_G726_ADPCM = 0x0064,
        /**  APICOM      */
        WAVE_FORMAT_G722_ADPCM = 0x0065,
        /**  Microsoft Corporation  */
        WAVE_FORMAT_DSAT = 0x0066,
        /**  Microsoft Corporation  */
        WAVE_FORMAT_DSAT_DISPLAY = 0x0067,
        /**  Softsound, Ltd.      */
        WAVE_FORMAT_SOFTSOUND = 0x0080,
        /**  Rhetorex Inc  */
        WAVE_FORMAT_RHETOREX_ADPCM = 0x0100,
        /**  Creative Labs, Inc  */
        WAVE_FORMAT_CREATIVE_ADPCM = 0x0200,
        /**  Creative Labs, Inc  */
        WAVE_FORMAT_CREATIVE_FASTSPEECH8 = 0x0202,
        /**  Creative Labs, Inc  */
        WAVE_FORMAT_CREATIVE_FASTSPEECH10 = 0x0203,
        /**  Quarterdeck Corporation  */
        WAVE_FORMAT_QUARTERDECK = 0x0220,
        /**  Fujitsu Corp.  */
        WAVE_FORMAT_FM_TOWNS_SND = 0x0300,
        /**  Brooktree Corporation  */
        WAVE_FORMAT_BTV_DIGITAL = 0x0400,
        /**  Ing C. Olivetti & C., S.p.A.  */
        WAVE_FORMAT_OLIGSM = 0x1000,
        /**  Ing C. Olivetti & C., S.p.A.  */
        WAVE_FORMAT_OLIADPCM = 0x1001,
        /**  Ing C. Olivetti & C., S.p.A.  */
        WAVE_FORMAT_OLICELP = 0x1002,
        /**  Ing C. Olivetti & C., S.p.A.  */
        WAVE_FORMAT_OLISBC = 0x1003,
        /**  Ing C. Olivetti & C., S.p.A.  */
        WAVE_FORMAT_OLIOPR = 0x1004,
        /**  Lernout & Hauspie  */
        WAVE_FORMAT_LH_CODEC = 0x1100,
        /**  Norris Communications, Inc.  */
        WAVE_FORMAT_NORRIS = 0x1400,
        /**
         *  the WAVE_FORMAT_DEVELOPMENT format tag can be used during the
         *  development phase of a new wave format.  Before shipping, you MUST
         *  acquire an official format tag from Microsoft.
         */
        WAVE_FORMAT_DEVELOPMENT = 0xFFFF,
} wFormatTagEnum;

typedef struct { 
  WORD enum wFormatTagEnum formatTag;
    // Waveform-audio format type. Format tags are registered with Microsoft 
    // Corporation for many compression algorithms. A complete list of format
    // tags can be found in the Mmreg.h header file. For one- or two-channel 
    // Pulse Code Modulation (PCM) data, this value should be WAVE_FORMAT_PCM.
  WORD  numberOfChannels;
    // Number of channels in the waveform-audio data. Monaural data uses one 
    // channel and stereo data uses two channels.
  DWORD samplesPerSec;
    // Sample rate, in samples per second (hertz). If "formatTag" is
    // "WAVE_FORMAT_PCM", then common values for "samplesPerSec" are 8.0 kHz,
    // 11.025 kHz, 22.05 kHz, and 44.1 kHz. For non-PCM formats, this member
    // must be computed according to the manufacturer's specification of the 
    // format tag.
  DWORD avgBytesPerSec;
    // Required average data-transfer rate, in bytes per second, for the format 
    // tag. If "formatTag" is "WAVE_FORMAT_PCM", "avgBytesPerSec" should be
    // equal to the product of "samplesPerSec" and "blockAlignment". For non-PCM
    // formats, this member must be computed according to the manufacturer's 
    // specification of the format tag.
  WORD  blockAlignment;
    // Block alignment, in bytes. The block alignment is the minimum atomic unit
    // of data for the "formatTag" format type. If "formatTag" is
    // "WAVE_FORMAT_PCM" or "WAVE_FORMAT_EXTENSIBLE, "blockAlignment" must be equal
    // to the product of "numberOfChannels" and "bitsPerSample" divided by 8 (bits per
    // byte). For non-PCM formats, this member must be computed according to the 
    // manufacturer's specification of the format tag.
    // Software must process a multiple of "blockAlignment" bytes of data at a
    // time. Data written to and read from a device must always start at the
    // beginning of a block. For example, it is illegal to start playback of PCM 
    // data in the middle of a sample (that is, on a non-block-aligned boundary).
  WORD  bitsPerSample;
    // Bits per sample for the waveFormatTag format type. If "formatTag" is
    // "WAVE_FORMAT_PCM", then "bitsPerSample" should be equal to 8 or 16. For
    // non-PCM formats, this member must be set according to the manufacturer's 
    // specification of the format tag. If "formatTag" is
    // "WAVE_FORMAT_EXTENSIBLE", this value can be any integer multiple of 8. 
    // Some compression schemes cannot define a value for "wBitsPerSample", so 
    // this member can be zero.
  WORD  cbSize; 
    // Size, in bytes, of extra format information appended to the end of the 
    // WAVEFORMATEX structure. This information can be used by non-PCM formats
    // to store extra attributes for the "wFormatTag". If no extra information 
    // is required by the "wFormatTag", this member must be set to zero. For 
    // WAVE_FORMAT_PCM formats (and only WAVE_FORMAT_PCM formats), this member 
    // is ignored.
  byte[cbSize] extra;
} WAVEFORMATEX; 

/* ------------------
 * AVI Stream Name
 * ------------------
 */
typedef struct {
  cstring name;
} AVIStreamName;

/* ------------------
 * AVI Stream Text
 * ------------------
 */
typedef struct {
  cstring text;
} AVIText;
 
/* ------------------
 * AVI Palette Change
 * ------------------
 */

// Values for this enum have been taken from:
// http://biodi.sdsc.edu/Doc/GARP/garp-1.1/define.h
enum {
    PC_EXPLICIT = 0x02,
    // Specifies that the low-order word of the logical palette entry 
    // designates a hardware palette index. This flag allows the application to 
    // show the contents of the display device palette.
    PC_NOCOLLAPSE = 0x04,
    // Specifies that the color be placed in an unused entry in the system 
    // palette instead of being matched to an existing color in the system 
    // palette. If there are no unused entries in the system palette, the color 
    // is matched normally. Once this color is in the system palette, colors in
    // other logical palettes can be matched to this color.
    PC_RESERVED = 0x01
    // Specifies that the logical palette entry be used for palette animation. 
    // This flag prevents other windows from matching colors to the palette 
    // entry since the color frequently changes. If an unused system-palette
    // entry is available, the color is placed in that entry. Otherwise, the 
    // color is not available for animation.
} peFlagsEnum;
/* 
 * The PALETTEENTRY structure specifies the color and usage of an entry in a
 * logical palette. A logical palette is defined by a LOGPALETTE structure.
 */
typedef struct { 
  BYTE peRed; // Specifies a red intensity value for the palette entry.
  BYTE peGreen; // Specifies a green intensity value for the palette entry.
  BYTE peBlue; // Specifies a blue intensity value for the palette entry.
  BYTE enum peFlagsEnum peFlags; // Specifies how the palette entry is to be used.
} PALETTEENTRY;

typedef struct {
  AVIPALCHANGE avipalchange;
} AVIPALCHANGE0;

typedef struct {
    BYTE          firstEntry;
        // Specifies the index of the first palette entry to change.
    BYTE          numEntries;
        // Specifies the number of palette entries to change, or zero to change 
        // all 256 palette entries.
    WORD          flags;
        // Reserved.
    PALETTEENTRY  peNew[numEntries];
        // Specifies an array of PALETTEENTRY structures, of size "numEntries".
} AVIPALCHANGE;

/* --------------
 * AVI old Index
 */

// The values for this set have been taken from:
// http://graphics.cs.uni-sb.de/NMM/dist-0.4.0/Docs/Doxygen/html/avifmt_8h.html
set {
    AVIIF_KEYFRAME = 0x00000010, 
        // The data chunk is a key frame.
    AVIIF_LIST = 0x00000001,
        // The data chunk is a 'rec ' list.
    AVIIF_NO_TIME = 0x00000100,
        // The data chunk does not affect the timing of the stream. For example, 
        // this flag should be set for palette changes.
    AVIIF_COMPUSE = 0x0fff0000
        // These bits are for compressor use
} avioldindex_flags;

typedef struct {
      FOURCC   chunkId;
      // Specifies a FOURCC that identifies a stream in the AVI file. The 
      // FOURCC must have the form 'xxyy' where xx is the stream number and yy 
      // is a two-character code that identifies the contents of the stream:
      DWORD  set avioldindex_flags flags;
      // Specifies a bitwise combination of zero or more of flags.
      DWORD   offset;
      // Specifies the location of the data chunk in the file. The value should 
      // be specified as an offset, in bytes, from the start of the 'movi' list; 
      // however, in some AVI files it is given as an offset from the start of 
      // the file.
      DWORD   size;
      // Specifies the size of the data chunk, in bytes.
} avioldindex_entry;

typedef struct {
   avioldindex_entry idx[];
} AVIOLDINDEX;
