September 21, 1998

The FLIC file format

The original FLIC file format was described by its author (Jim Kent) in Dr. Dobb's Journal, March 1993. The main purpose of this document is to document the modifications and extensions that EGI (a FLIC compiler and player engine) adds to the FLIC file format, but since you may not have Jim Kent's article, all standard file information is included as well.

There are two "official" types of FLIC files: FLI and FLC (the names of these types refer to the filename extensions). The FLI files are the older format and are limited to a resolution of 320*200. The EGI compiler only writes FLC files, but the EGI players can read and play both formats.

A FLIC file stores a number of frames. Every frame contains an image and possibly a palette, a label, or other data. A "compatible" FLIC file contains a ring frame so that the animation can be played repeatedly without a perceptible pause between the last frame and the first (the unpacking of the first frame, a complete image, is generally slower than a delta frame update). A FLIC file that contains segments optionally contains a ring frame per segment.

FLIC files are structured in a hierarchy of chunks. A chunk contains a fixed part and a variable part. The fixed part of every chunk contains the type and the size of the chunk. The rest of the chunk has no fixed format; it all depends on the chunk type. The purpose of the chunked structure is to allow new chunks to be added without breaking existing FLIC players. A reader that does not understand some chunk type can just skip it (using the information from the fixed part of the chunk). The figure below shows the hierarchy of chunks in a FLIC file.

All "word" (two bytes) or "double word" (four bytes) values are stored in Little Endian (this is the byte order used by the Intel 80x86 processor series).

Overview of the FLIC file structure
File header                   general file information

Prefix chunk                  FLC files only
   Cel data chunk             CEL files (identical to FLC files)

Segment table chunk           EGI files only
   Segment chunk              information of every segment

Huffman table chunk           EGI files only

Frame chunk
   Postage stamp              icon, FLC files only
      Image data              compressed or uncompressed
   Palette chunk              colour data
   Image data                 compressed in various ways
   Bitmap mask chunk          EGI files only
   Multilevel mask chunk      EGI files only
   Label chunk                EGI files only
   Region chunk               EGI files only
   Wave audio chunk           EGI files only
   User string chunk          EGI files only
   Key palette                EGI files only
   Key image                  EGI files only

Ring frame chunk
   Palette chunk              see above
   Image data                 see above
   Bitmap mask chunk          see above
   Multilevel mask chunk      see above
   Label chunk                see above
   Region chunk               see above
   Wave audio chunk           see above
   User string chunk          see above

The file header

A FLIC file starts with a 128-byte header, see the figure below for a C structure. The type field contains:
0xAF11For FLI files
0xAF12For standard FLC files (with an 8-bit colour depth).
0xAF44For FLIC files with a colour depth other than 8. Currently, the DTA program is the only utility that makes FLIC files with a colour depth of 1, 15, 16 or 24 bits, and EGI is currently not compatible with these FLIC files.
0xAF30For FLIC files that use Huffman or BWT compression.
???Password protected FLIC files have a scrambled type field, so that previous versions of EGI and other FLIC readers will identify them as invalid (or unknown) FLIC files.

For FLI files, the delay between two frames is in increments of 1/70 second; FLC files specify the speed in milliseconds. The header for a FLI file does not contain the offset of the first and second frames; the first frame is assumed to start directly behind the file header (no "prefix", "segment table" or "Huffman table" chunks) and the offset to the second frame is easily computed once you read in the header of the first frame. The purpose of storing the offset to the second frame is that, after playing the ring frame, the next frame to display is the second frame of the animation.

Autodesk Animator Pro also stores the MS-DOS formatted date and time stamps of the initial creation and last update of the FLIC file, as well as the serial number of the copy of the Animator Pro program that made/updated the file (in the creator and updater fields). Other utilities set the creator field to:
0Unknown (Pro Motion, DTA, VFD or other)
0x45474900EGI
0x464c4942FlicLib
0x42494c46FlicLib - release 2
0x41544542Micrografx Simply3D
0x30314c46Kinetix 3DStudio MAX

The frames field in the FLIC file header does not include the ring frame that loops back to the beginning of the animation.

The flags field is used internally by Autodesk Animator Pro. If a FLIC file is written to disk and closed correctly, Animator Pro sets this field to 3. Most other utilities set it to zero.

The FLIC file header
typedef struct {
  DWORD size;          /* Size of FLIC including this header */
  WORD  type;          /* File type 0xAF11 or 0xAF12 */
  WORD  frames;        /* Number of frames in first segment */
  WORD  width;         /* FLIC width in pixels */
  WORD  height;        /* FLIC height in pixels */
  WORD  depth;         /* Bits per pixel (usually 8) */
  WORD  flags;         /* Set to zero or to three */
  DWORD speed;         /* Delay between frames */
  WORD  reserved1;     /* Set to zero */
  DWORD created;       /* Date of FLIC creation (FLC only) */
  DWORD creator;       /* Serial number or compiler id (FLC only) */
  DWORD updated;       /* Date of FLIC update (FLC only) */
  DWORD updater;       /* Serial number (FLC only), see creator */
  WORD  aspect_dx;     /* Width of square rectangle (FLC only) */
  WORD  aspect_dy;     /* Height of square rectangle (FLC only) */
  WORD  ext_flags;     /* EGI: flags for specific EGI extensions */
  WORD  keyframes;     /* EGI: key-image frequency */
  WORD  totalframes;   /* EGI: total number of frames (segments) */
  DWORD req_memory;    /* EGI: maximum chunk size (uncompressed) */
  BYTE  reserved2[28]; /* Set to zero */
  DWORD oframe1;       /* Offset to frame 1 (FLC only) */
  DWORD oframe2;       /* Offset to frame 2 (FLC only) */
  BYTE  reserved3[40]; /* Set to zero */
} FLIC_HEADER;

The modifications that EGI made to the FLIC file header are subtler. Not only are there a few added fields, but you must also decide whether the fields are valid:

Chunks and subchunks

Every chunk starts with a 6-byte header, that contains the size (four bytes) and the type (two bytes) for the chunk. All chunks sizes should be rounded up to an even number of bytes. The values of the main level chunks are above 0xF100, values of the subchunks are below 100 (decimal). As you can see in figure "Overview of the FLIC file structure", nearly all of the subchunks appear in the "frame" chunk.

Chunks types are indicated in the FLIC file with a two-byte value, but Jim Kent's article tagged names on those values (these names appear to be extracted from the Animator Pro source code). For ease of writing, I use the same names, in the same glorious "ALL UPPER CAPS" that has become common in discussing the FLIC file format.

Overview of all chunks
   3       CEL_DATA             position and transparency
   4       COLOR_256            256-level colour palette
   7       DELTA_FLC (FLI_SS2)  delta image, word oriented RLE
  11       COLOR_64             64-level colour palette
  12       DELTA_FLI (FLI_LC)   delta image, byte oriented RLE
  13       BLACK                full black frame (rare)
  15       BYTE_RUN (FLI_BRUN)  full image, byte oriented RLE
  16       FLI_COPY             uncompressed image (rare)
  18       PSTAMP               postage stamp (icon of the first frame)
  25       DTA_BRUN             full image, pixel oriented RLE
  26       DTA_COPY             uncompressed image
  27       DTA_LC               delta image, pixel oriented RLE
  31       LABEL                frame label
  32       BMP_MASK             bitmap mask
  33       MLEV_MASK            multilevel mask
  34       SEGMENT              segment information
  35       KEY_IMAGE            key image, similar to DELTA_FLC
  36       KEY_PAL              key palette, similar to COLOR_256
  37       REGION               region of frame differences
  38       WAVE                 digitized audio
  39       USERSTRING           general purpose user data

  0xF100   PREFIX_TYPE          prefix chunk
  0xF1FA   FRAME_TYPE           frame chunk
  0xF1FB   SEGMENT_TABLE        segment table chunk
  0xF1FC   HUFFMAN_TABLE        Huffman compression table chunk

The rest of the document discusses these chunks and subchunks in detail. On the right of the caption for each chunk type is the product for which this chunk is valid. Autodesk Animator is not mentioned explicitly, because there exist (to my knowledge) no chunks that only Animator supports.

 
PREFIX_TYPE all
The prefix chunk contains (undocumented) settings and cel data. It usually appears in .CEL files.
typedef struct {
  DWORD size;           /* Size of the chunk, including subchunks */
  WORD  type;           /* Chunk type: 0xF100 */
  WORD  chunks;         /* Number of subchunks */
  BYTE  reserved[8];    /* Reserved, set to 0 */
} PREFIX_HDR;
 
CEL_DATA all
typedef struct {
  DWORD size;           /* Size of the chunk, including subchunks */
  WORD  type;           /* Chunk type: 3 */
  WORD  center_x;       /* coordinates of the cel centre */
  WORD  center_y;
  WORD  stretch_x;      /* stretch amounts */
  WORD  stretch_y;
  WORD  rot_x;          /* rotation in x-axis (always 0) */
  WORD  rot_y;          /* rotation in y-axis (always 0) */
  WORD  rot_z;          /* z-axis rotation, 0-5760=0-360 degrees */
  WORD  cur_frame;      /* current frame in cel file */
  BYTE  reserved1[2];   /* Reserved, set to 0 */
  WORD  transparent;    /* Transparent colour index */
  BYTE  reserved2[38]   /* Reserved, set to 0 */
} CEL_DATA;

The CEL_DATA chunk is usually not present in FLC files. Intermediate files used by Autodesk Animator Pro with the .CEL extension usually contain a CEL_DATA in the prefix chunk. The CEL files have the same format as FLC files.

 
SEGMENT_TABLE EGI 1+
typedef struct {
  DWORD size;          /* Size of this chunk, including subchunks */
  WORD  type;          /* Chunk type: 0xF1FB */
  WORD  segments;      /* Number of SEGMENT chunks that follow */
} SEGMENT_TABLE;

If a segment table is present, it overrules the values in the header (number of frames, offsets to the first and second frames).

 
SEGMENT EGI 1+
typedef struct {
  DWORD size;          /* Size of this chunk (always 32 bytes) */
  WORD  type;          /* Subchunk type: 34 */
  WORD  label;         /* Label of the segment (user value) */
  BYTE  reserved1[2];  /* Reserved, set to zero */
  WORD  cont_image;    /* "continued from" image id */
  WORD  last_image;    /* id of the last image of this segment */
  WORD  flags;         /* Flags */
  WORD  frames;        /* Number of frames in the segment */
  DWORD oframe1;       /* File offset to frame 1 of the segment */
  DWORD oframe2;       /* File offset to frame 2 */
  WORD  next_segment;  /* segment number of segment to proceed with */
  WORD  repeat;        /* repeat count (0=indefinitely) */
  BYTE  reserved2[2];  /* Reserved, set to zero */
} SEGMENT;

The flags field contains four bit flags:

    bit    meaning
     0     the segment contains a ring frame
     1     the first frame contains a full image
     2     the "next_segment" field of the structure is valid
     3     audio must be synchronized with the animation

If bit 1 is set, the first frame contains either a full image, or a delta image plus a key image. In other words, bit 1 indicates whether the segment is a "launch point". See the EGI compiler instruction launch_point for more details.

The frames field does not include the ring frame (if a ring frame is present).

In a FLIC file has multiple segments and some of the segments are "continued" from other segments (see the compiler instruction continued_from), a frame may contain both a full image (the key image) and a delta image. The EGI player uses the cont_image and last_image fields to determine whether it can use the delta image (whose decoding is usually quicker than a full image), or whether it must decode the full image instead.

When creating the FLIC file, the EGI compiler assigns each picture a unique number. It stores the number of the last image in a segment in the last_image field of the SEGMENT structure. When you add a continued_from instruction to the segment, the compiler copies the last_image field of the segment that was specified in the continued_from instruction to the cont_image field of the current segment. The compiler then proceeds to create a delta image given the first image of the current segment and the last image of the "continued from" segment. A segment that is not continued from another segment has a value of 0xFFFF in the cont_image field.

The EGI player goes the opposite route. Assuming that the player just displayed the last frame of a segment, and at that moment you switch to another segment: if the last_image field of the current segment is the same as the cont_image of the next field, the player decodes the delta image of the new segment. Otherwise it decodes the key image.

 
HUFFMAN_TABLE EGI 1+
typedef struct {
  DWORD size;          /* Size of this chunk */
  WORD  type;          /* Chunk type: 0xF1FC */
  WORD  codelength;    /* Maximum length of the Huffman codes */
  WORD  numcodes;      /* The number of codes */
  BYTE  reserved[6];   /* Must be set to zero */
  /* The following three fields are repeated "numcodes" times */
  WORD  code;          /* Huffman code */
  BYTE  length;        /* Length of the Huffman code */
  BYTE  value;         /* Byte value represented by the Huffman code */
} HUFFMAN_TABLE;

See the "Compression" paper for information on the Huffman compression algorithm. This chunk is only present if bit 3 of the ext_flags of the FLIC file header is set.

 
FRAME_TYPE all

This chunk is defined by Autodesk Animator, but Pro-Motion and EGI extend it.

typedef struct {
  DWORD size;          /* Size of the chunk, including subchunks */
  WORD  type;          /* Chunk type: 0xF1FA */
  WORD  chunks;        /* Number of subchunks */
  WORD  delay;         /* Delay in milliseconds */
  BYTE  reserved[6];   /* Reserved, set to 0 */
} FRAME_TYPE;

The delay value overrules the speed field in the FLIC header; a value of zero indicates that the normal speed (from the FLIC header) applies. The delay field is an extension to the FLIC format, introduced by Cosmigo's Pro Motion.

 
COLOR_256 and COLOR_64 all

The two subchunks with types 4 and 11 are identical, except that the range of the RGB values is 0-63 for COLOR_64 (type 11) and 0-255 for COLOR_256 (type 4).

The data in the chunk is organized in packets. The first word following the chunk header is the number of packets in the chunk. Each packet consists of a 1-byte skip count, a 1-byte copy count and a series of 3-byte RGB values (the "copy count" gives the number of RGB triplets). If the copy count is zero, there are 256 RGB triplets in the packet. For example, the data to change colours 2, 7, 8 and 9 would appear as:

    2                           /* two packets */
    2,1,r,g,b                   /* skip 2 entries, change 1 entry */
    4,3,r,g,b,r,g,b,r,g,b       /* skip 4, change 3 */
 
BLACK all

All pixels in the frame have colour 0. This chunk has no data following the chunk header.

 
FLI_COPY all

The data that follows the chunk header are the pixels of an uncompressed image of the frame. The number of pixels (bytes) are exactly width*height of the frame. The first pixel is for the upper left corner of the frame.

 
BYTE_RUN (FLI_BRUN) all

The data following the chunk header is a full image that is compressed with byte oriented RLE. The first image of a segment and key frames are usually stored in a BYTE_RUN chunk.

Each line of the image is compressed separately, starting from the top of the image. The first byte of each line is the packet count, it is ignored (and set to zero) for FLC type files, because it is now possible to have more than 255 packets on a line. Instead, the width of the frame image now is the criterion for decoding: continue decompressing until the number of uncompressed pixels becomes equal to the image width.

Each RLE packet consists of a count byte and one or more data bytes. If the count byte is negative, its absolute value is the number of data bytes (following the count byte) to copy to the image: a literal run. If the count byte is positive, the single data byte that follows must be replicated in the image "count" times: a replicate run.

 
DELTA_FLI (FLI_LC) all

This chunk is used for FLI type files; the newer FLC format replaces this chunk with DELTA_FLC (see below). The chunk contains the differences (the "delta") between the current frame and the previous frame.

The first 16-bit word behind the chunk header is the line number (starting from the top of the image) for the first line in the image that differs from the previous frame. In other words, it is a line skip count. The second word is the number of lines in the chunk. The data for the lines themselves follow these two words.

Each line starts with a packet count for the line. Unlike the BYTE_RUN chunk, this value is significant because the "delta" need not to store the complete width of the frame image. The packets themselves follow the packet count. Each packet consists of a column skip count, an RLE count byte and zero or more data bytes. The column skip count is the number of pixels to skip (the number of pixels that did not change between the current frame and the previous frame) from the current position in the line. It can have a value of zero. The RLE count byte and the data bytes are similar to the BYTE_RUN encoding: if the count is positive, that number of bytes is to be copied from the data to the image (literal run); if the count is negative, its absolute value is the replication count of the one data byte that follows (replicate run).

Two pitfalls:

 
DELTA_FLC (FLI_SS2) all

This chunk is similar to the DELTA_FLI chunk, but it compresses the delta image differently. The data following the chunk header is organized into lines and each line is organized into packets. Every line starts with one or more word-sized "opcodes".

The first word following the chunk header is the number of lines in the chunk. This count does not include "skipped" lines. Each line starts with one or more opcodes. One of the opcodes (the last) is the packet count. The highest two bits of the opcode word give its type:

  Bit 15   Bit 14   Description
    0        0      Packet count for the line, it can be zero
    0        1      Undefined
    1        0      Store the opcode's low byte in the last pixel of the line
    1        1      The absolute value of the opcode is the line skip count

The RLE compression of DELTA_FLC is similar to that of DELTA_FLI, but it is word oriented. The first byte of each packet is the column skip count; the second byte is the RLE count byte. Zero or more data words follow the RLE count byte. If the count is positive, that number of words of data is copied to the image; if the count is negative, one data word follows and the absolute value of the count tells how many times that word must be replicated in the image.

The two pitfalls from the DELTA_FLI chunk apply here too (see above). A third is:

 
PSTAMP all
typedef struct {
  DWORD size;           /* Size of this chunk */
  WORD  type;           /* Chunk type: 18 */
  WORD  height;         /* Height of the postage stamp */
  WORD  width;          /* Width of the postage stamp */
  WORD  xlate;          /* Colour translation, always 1 */
} LABEL;

A "postage stamp" is a reduced image of the first frame of an animation. A postage stamp created by Autodesk Animator Pro has the preferred size of 100*63 (the actual size can vary) and uses a universal palette.

The palette is an RGB cube with 6 levels of each red, green and blue. This totals in 216 colours. An arbitrary RGB value (where each component is in the range of 0-255) is mapped into the six-cube space using:

((6*red)/256) * 36 + ((6*green)/256) * 6 + (6*blue)/256

The PSTAMP chunk embeds another chunk. This is usually a BYTE_RUN chunk or a FLI_COPY chunk (for compressed and uncompressed images respectively). If the type of the embedded chunk is 18 again (the type of PSTAMP is also 18), that chunk contains a 256-byte colour translation table. The translation table maps every palette index of the first frame to the universal six-cube colour space. To display the postage stamp, a program decodes the image of the first frame and maps every pixel of that image to the six-cube colour palette (using the translation table).

 
DTA_BRUN, DTA_COPY and DTA_LC DTA

These chunks are generated by the DTA program by Dave K. Mason for FLIC files with 15-bit, 16-bit or 24-bit colour depth. FLIC files with these formats usually have a .FLH or a .FLT extension.

In 24-bit FLIC files, pixels are made up of three bytes in the order B,G,R. In 16-bit files the colour values are packed into words (two byte pairs)e in "rrrrrggg gggbbbbb" format. 15-Bit FLIC files have pixels packed into the format "0rrrrrgg gggbbbbb".

The DTA_BRUN chunk is numbered 25 (instead of 15 for a standard BYTE_RUN). The Repeat/Copy value is still a byte, but it refers to a number of pixels to copy or repeat, not bytes.

The DTA_LC chunk is numbered 27. Internally it is like chunk type 7 (DELTA_FLC). It starts with a number-of-lines value. For each line, the packet is a signed word value. If it is negative then it represents a lines-to-skip and does not count toward the number-of-lines. Each non-negative packet begins with a skip counter. This is still a byte, but it represents a number of pixels to skip, not bytes. Next comes a repeat/copy packet. It represents a number of pixels to copy or skip, not words. (Though in a 16-bit FLIC file, the pixels are words.) The copy chunk is numbered 26, although the standard "copy" chunk type 16 (FLI_COPY)would do equally well: there is no decoding for copy chunks.

 
LABEL EGI 1+
typedef struct {
  DWORD size;           /* Size of this chunk */
  WORD  type;           /* Chunk type: 31 */
  WORD  label           /* Label of the frame (user value) */
  BYTE  reserved[2]     /* Reserved, set to zero */
} LABEL;

The EGI API function FlicPlay sends a notification message if it encounters a label subchunk in a frame. The message is sent (using SendMessage under Microsoft Windows) after decoding (and displaying) the frame.

 
KEY_IMAGE EGI 1+

The same as BYTE_RUN, but a frame that has a KEY_IMAGE chunk also contains a DELTA_FLC from a previous segment. A player can decide (based on the transition it makes from segment to segment) whether to decode the KEY_IMAGE and skip the DELTA_FLC, or to decode the DELTA_FLC and skip the KEY_IMAGE. See the SEGMENT chunk for more information.

 
KEY_PAL EGI 1+

The same as COLOR_256, but it is only present for key images.

 
BMP_MASK and MLEV_MASK EGI 1+ and EGI 2+

The chunk MLEV_MASK is defined as of EGI version 2.0; the chunk BMP_MASK exists since EGI 1.0.

The chunk starts (right after the chunk header) with four 16-bit words that give the bounding box of the mask. You can use this bounding box to speed up drawing operations, because you do not have to draw anything outside this box (all pixels are transparent outside the bounding box). The values are stored in the following order: x y width height.

The mask data starts behind the bounding box. Each line is encoded separately. A line starts with a "line skip count", which indicates how many lines remain unchanged from the previous mask. It is a two-byte value. It is zero for every line in a full mask.

The bitmap data (for the mask bitmap) comes after the line skip count. The bitmap data is compressed with the same RLE encoding as the BYTE_RUN image. This means that if the first (type) byte is positive, it is followed by a single pixel that must be replicated; if it is negative, it is followed by a series of bytes that must be copied literally. In contrast to the BYTE_RUN compression, no "packet count" byte is stored at the beginning of a scan line. Each scan line of the mask is compressed individually. Huffman and BWT compression do not apply to masks.

The data of a bitmap mask (after compression) is a 1 bit per pixel (8 pixels per byte) bitmap with the same size as the frame image. Each bit that is set ("1") represents a transparent pixel in the frame image. Each bit that is cleared ("0") represents an opaque pixel.

A multilevel mask is an 8 bits per pixel bitmap (with the same size as the frame image). Each byte in the mask represents the transparency level of the corresponding pixel in the frame image. A value of 255 is fully transparent, and 0 is fully opaque.

A frame can contain both a full image and a delta image. This occurs, for example when a segment in a FLIC file is both "continued_from" another segment and a launch point, or when the "key_frames" instruction is used. The mask for a frame that contains both a delta image and a full image is always a full mask.

 
REGION EGI 1+
typedef struct {
  DWORD size;           /* Size of this chunk */
  WORD  type;           /* Chunk type: 37 */
  WORD  number;         /* Number of rectangles that form the region */
  /* The following four fields are repeated "number" times */
  WORD  x;              /* Pixel coordinates of a rectangle */
  WORD  y;
  WORD  width;          /* Size of the region in pixels */
  WORD  height;
} REGION;

The EGI compiler stores the region of frame differences (see the dif_region instruction of the compiler's script language) by means of a grid. In the current release, the grid is composed of square tiles of 16*16 pixels. When a single pixel in a tile changes, all 256 pixels in that tile are flagged as "modified".

Two neighbouring tiles that are both flagged as "modified" are combined into a single new tile. The edges of the resulting rectangular tiles are always snapped to the grid points. Therefore, each rectangle in a region of frame differences needs not to enclose the object at pixel precision. However, no rectangle will exceed the bounding box of all differences between two frames.

The purpose of a coarse grid is to avoid a large amount of very small areas. The cost of the overhead for every call to the BitBlt function for all these areas might be higher than the cost of blitting several pixels too many.

 
WAVE EGI 2+
typedef struct {
  DWORD size;          /* size of this chunk */
  WORD  type;          /* Chunk type: 38 */
  WORD  flags;
  WORD  samplefreq;    /* sample frequency */
  DWORD overlap;       /* sample overlap (in bytes) */
  BYTE  reserved[6];   /* always zero */
} WAVE;

The flags value is a bit field.

  Bit  Description
   0   Sample size is 16-bit (otherwise 8-bit)
   1   Format is signed PCM (otherwise unsigned PCM)
   2   Audio is stereo
   3   First block of the audio stream (open/reset sound card/driver)
   4   Last block of the audio stream (close sound card/driver)

The digitized audio data follows the chunk. The format depends on the various flags. If audio is 16-bit, there are two bytes per sample, in Little Endian (Intel format). In unsigned PCM, the "silence" level is 128 for 8-bit samples and 32768 for 16-bit samples. For stereo audio the samples for the left and right channels are interleaved; the sample for the left channel precedes the sample for the right channel.

Currently, EGI only supports 8-bit unsigned PCM or 16-bit signed PCM. These are the same formats as used in the .WAV and the .VOC file formats.

An audio stream is often be stored in a single block. The audio starts at the frame in which the block occurs, and it continues to "sound" during the displaying of the next frames. Audio and animation are not necessarily synchronized. For these single block audio streams, both bits 3 and 4 in the flags field are set, and overlap is always zero.

The audio stream can also be cut in various blocks. The first block contains enough samples to get from the current frame to the first key frame. The key frame contains another audio block with enough samples to get to the next key frame, etc. Here, the bits 3 and 4 of the flags field help to glue the blocks together to a sequential audio stream. Audio and animation should be synchronized to play back correctly. (The EGI player synchronizes animation and sound by default if the sound is cut into blocks.)

To avoid gaps in the audio when synchronization is not perfect, each block contains more samples than strictly necessary. In the current implementation, EGI adds enough samples to go to one frame after each key frame. When sending a (next) block to the audio device, you should ignore the first overlap bytes from the audio data.

You can jump in the middle of an animation, and this way, you can also jump in the middle of a multiple block audio stream. In this case, to get a proper synchronization, ignore the overlap field for the first audio block that you encounter.

 
USERSTRING EGI 2+

A zero-terminated ASCII string follows the chunk header. The USERSTRING chunk allows an application to store general-purpose strings (both for copyright information as for references to other files or data) in a frame.

 

Frequent errors

Unfortunately, several utilities create FLIC files that do not completely comply with the standard. Most FLIC players attempt to detect and silently correct these errors. Below is a list of frequent errors in FLIC files.

 

References

Kent, J.; "The FLIC File format"; Dr. Dobb's Journal, March 1996 (Volume 18, issue 3).

 

© ITB CompuPhase, 1997-1998, The Netherlands
http://www.compuphase.com