Previous | Up | Home | Next

Chunks, Lists, Forms and Tags

RIFF chunks, lists and forms.

The basic building block of a RIFF file is called a chunk. A chunk is composed of a four character ASCII code indicating what type of chunk it is, followed by a length field, followed by the chunk's data. Defined in the C programming language, a chunk looks like this:

typedef unsigned long DWORD;
typedef unsigned char BYTE;
typedef DWORD FOURCC;                           /*  Four-character code */

typedef struct {
	FOURCC	chunkID;
	DWORD	chunkSize;                      /* the size of field  */
	BYTE		chunkData[chunkSize];   /* the actual data of the chunk  */
} chunk;

A list is a type of chunk which can contain nested chunks, or subchunks. Its four character code is "LIST". The type of list it is is supplied in a four character code following the size field, which is followed by a series of chunks or other lists.

typedef struct {
	FOURCC	chunkID;			/* always "LIST"  */
	DWORD	chunkSize;			/* the size of field  + 4 */
	FOURCC	listID;				/* the type of list it is  */
	BYTE	listData[chunkSize-4];		/* zero or more chunks and lists  */
} list;

A form is a special type of chunk which always appears first in a RIFF file, and contains all the other chunks and lists in the file. Its four character code is "RIFF", or in the case of the Motorola format which NIFF always uses, "RIFX". The form type, which is always "NIFF" for NIFF files, is supplied in a four character code following its length field. This is followed by a series of lists and chunks:

typedef struct {
	FOURCC	chunkID;			/* always "RIFX" */
	DWORD	chunkSize;			/* the size of field  + 4  */
	FOURCC	formID;				/* always "NIFF"  */
	BYTE	formData[chunkSize-4];		/* zero or more chunks and lists  */
} form;

The presence of the chunkSize allows programs to ignore the rest of a chunk, list or form which is not recognized. The chunkData, listData and formData fields always have an even number of bytes. A pad byte with value zero is added to the end, if necessary for the data to end on a word boundary. The value of chunkSize does not include the pad byte.

NIFF chunks and tags.

Each NIFF file chunk has a fixed-length part and a variable length part. The fixed-length part is composed of a set of required elements described by its chunk definition in Chapter 3. The variable length part is composed of a series of optional tags which may be used occasionally or only by certain programs.

A tag is a self-contained set of variable-length information composed of a one byte code indicating what type of tag it is, followed by a one byte length field, followed by the tag's data.

Defined in the C programming language, a tag looks like this:

typedef {
	BYTE tagID;
	BYTE tagSize;				/* the size of field  */
	BYTE tagData[tagSize];			/* the actual data of the tag */
} tag;

The presence of the tags' size allows programs to ignore the rest of a tag which is not recognized. The tagData field always has an even number of bytes. A pad byte with value zero is added to the end, if necessary for the data to end on a word boundary. The value of tagSize does not include the pad byte.

The tagData field must conform to the documented tag definition as shown in Chapter 3, unless it is a user-defined tag, discussed below.

Any number of tags may be appended to the required part of a chunk. NIFF-defined options, user-defined options, and future extensions can all be represented in the form of tags.

Any defined tag may be added to any chunk type; however, some combinations might be meaningless. When used on an anchor symbol chunk (see Chapter 2, Symbol Relationships), a tag applies to all symbol chunks dependent on the anchor, where meaningful. When used on a Stem chunk, a tag applies to all associated Notehead chunks.

NIFF data types.

The same data types are used in both chunk and tag definitions. Currently defined data types are described below.

Typedefs can be found in the NIFF.h C header file (Appendix A) for the following data types. Additional types used in the chunk and tag definitions are STRUCT, which refers to a set of data elements in a documented structure format, and char[x], an x byte character value.
TypeDescription
BYTEa 1 byte unsigned integer
SIGNEDBYTEa 1 byte signed integer
CHARa 1 byte character value
SHORTa 2 byte signed integer
LONGa 4 byte signed integer
FOURCCa 4 byte ASCII character value.
RATIONAL2 2 byte signed integers (numerator and denominator)
STROFFSETa 2 byte signed integer pointing to a RIFF ZSTR in the String Table chunk in the Setup Section. A RIFF ZSTR is a series of ASCII characters followed by a terminating null. -1 means a null pointer. Embedded zero bytes are not allowed within a ZSTR.
FONTPTRa 2 byte pointer to a Font Description chunk in the Font Descriptions list.
EMPTY0 bytes. This is used for chunk types for which there are no required elements, and tags whose full meaning is conveyed by the tag ID.

N.B. Time did not permit full development of an International String Table in time for NIFF 6a. This would be a Setup Section chunk that would allow character strings to be stored for fonts that require two bytes for each character code, such as Chinese, Japanese, or Korean. An associated data type would be required to reference strings in this table, as well as an International Text chunk containing a field with this data type. Other enhancements to the format to make use of this feature have not been fully investigated. It is possible that this feature could be developed in the future.

User-Defined Chunks and Tags.

NIFF users such as commercial software vendors and academic researchers can define their own NIFF chunks and tags, to provide for features of their software that are not present in the NIFF specification. NIFF users who want to define their own chunks and tags must formally register a unique two byte NIFF User ID, using a protocol yet to be developed.

User-defined chunks are identified by the four character code "user". The two byte NIFF User ID is stored in the first two bytes of the chunkData field. User-defined tags are identified by a tag ID of 255 (x'FF'). The NIFF User ID is stored in the first two bytes of the tagData field. The user defines the structure and value of the remainder of the data portion of the chunk tag. The presence of the size field allows reading programs to ignore unrecognized user-defined chunks and tags.

The Chunk Length Table in the Setup Section must include an entry for each user-defined chunk type as well as for each standard NIFF chunk type used in the file.

NIFF users should clearly document the structure and function of each user-defined chunk and tag. The details of administering a documentation library have yet to be determined.


Previous | Up | Home | Next