RIFF File Structure

The Resource Interchange File Format (RIFF) is a tagged-file specification designed for the storage of multimedia data. Data types ranging from C++ objects to full-motion video can be stored based on the RIFF specification, and new data types can be added.

The zip file riff.zip contains several examples of RIFF files, a Microsoft-provided executable program for displaying RIFF file structures, and a simple C++ program that also displays RIFF file chunks.

Table 1 shows several file formats based on the RIFF specification.

Table 1: Form types.

CPPO APPS Software International C++ Object Format
PAL Palette File Format
RDIB Device Independent Bitmap Format
RMID MIDI Audio Format
RMMP Multimedia Movie File Format
WAVE Waveform Audio Format

RIFF provides a standard storage method for different types of multimedia data. Applications can ignore types of data in a RIFF file that they can't process, preventing software from becoming obsolete because of the introduction of a new variation of a data type. The specification's only major limitation is that, in its current version, the data area of a RIFF file may not exceed four gigabytes. Given the current state of the art of most PCs, this limitation isn't serious, but it may become so in a future that promises giant files such as those of full-length digital HDTV movies. Already, four gigabytes will only hold a few hours of uncompressed CD-quality audio.

RIFF Internals

The basis of the RIFF specification is a data structure known as the "chunk," which contains a unique chunk-type identifier, an integer value that holds the size of the chunk's data area and the data itself.

The following C data structures describes the organization of a chunk.

typedef unsigned long DWORD; 
typedef unsigned char BYTE; 
typedef DWORD FOURCC;    // Four-character code 
typedef struct { 
     FOURCC ckID;        // The unique chunk identifier 
     DWORD ckSize;       // The size of field <ckData> 
     BYTE ckData[ckSize];     // The actual data of the chunk 
} CK; 

RIFF and LIST chunks have an extra field at the beginning of their data area.

typedef struct { 
     FOURCC ckID; 
     DWORD ckSize; 
     union { 
          FOURCC fccType;          // RIFF form type 
          BYTE ckData[ckSize]; 
     } ckData; 

These examples assume that there is no padding between fields in either structure. Therefore, chunk data in a non-RIFF or LIST chunk starts at an offset of 8 bytes into the chunk (12 bytes in the case of RIFF or LIST chunks). Chunks are padded at the end to WORD (16-bit) boundaries, however.

Chunks contain data such as ASCII text, waveform data, or bitmaps; certain chunks (currently only RIFF or LIST chunks) may contain nested subchunks. The data-area size includes the size of these subchunks (if any). By splitting a file into several variable-length chunks, RIFF allows for greater flexibility than file formats defined around fixed-length and position fields.

The first chunk in a RIFF file must be a RIFF chunk with a chunk ID consisting of the four-character code RIFF. The first chunk may alternatively be a RIFX chunk--the X indicates that all integers in the file are in Motorola format. In the present version of the RIFF specification, only one RIFF or RIFX chunk is allowed per file.

The RIFF chunk contains at least one other chunk, with the number of chunks varying depending on the form type (file format) of the file and on the number of optional chunks that are present in the file. These chunks are known as "subchunks" of the RIFF chunk.

RIFF chunks have a special code at the start of the data area that specifies the form type--the type of data in the file and its format. A RIFF form is also defined by:

LIST Chunks

LIST chunks are the only chunks apart from RIFF chunks that may contain their own subchunks (although this may change). LIST chunks are usually subchunks of RIFF chunks themselves. Like RIFF chunks, LIST chunks have a four-character code in the first four bytes of their data area. This code specifies the list type (analogous to a RIFF chunk's form type) of the LIST chunk.

For example, a LIST chunk of list type INFO may contain subchunks such as INAM (the name of the data stored in the file) and ICRD (creation date). LIST chunks of type INFO are optional in current RIFF forms, but their use is recommended. The LIST chunks' subchunks can store much more information about the file than is available from the filename and date stamp. These LIST subchunks share a common format: Each contains one ASCIIZ (NULL terminated) string.

As long as LIST chunks are stored in the correct place (according to the applicable RIFF form), correctly written applications that cannot process LIST chunks will ignore their presence. Table 2 describes the layout of a typical RIFF file containing a LIST chunk. The table shows the layout of a simple WAVE form file as stored on disk. The "fmt" and "data" chunks are subchunks of the RIFF chunk.

Table 2: Example RIFF file.

Data type Description
FOURCC Chunk type (for example, "RIFF")
DWORD Chunk size
FOURCC Form type (for example, "WAVE")
FOURCC Chunk type (for example, "fmt")
DWORD Chunk size
BYTE[Chunk size] Chunk contents (for example, waveform format)
FOURCC Chunk type (for example, "data")
DWORD Chunk size
BYTE[Chunk size] Chunk contents (for example, waveform data)

Maintained by John Loomis, last updated 5 Jan 2001