Stephen Travis Pope and Guido van Rossum
Computer Music Journal, Vol:l9, No:1, Spring 1995
© Massachusetts Institute of Technology.


RIFF/WAVE (or WAV) File Format

Developed by Microsoft and IBM, RIFF is a file-interchange format. It is similar in spirit and functionality to IFF, but is not compatible with it. A different byte ordering ("little-endian") is used by RIFF. The RIFF equivalent of AIFF is WAVE (or WAV after the three-character file-name extension that its files use). Its inclusion in Microsoft Windows 3.1 has secured WAVE a place as a "standard" to be addressed by sound file system implementors.
The official specifications of WAVE can be found in Microsoft (1992), which is also available via Internet as ftp.cwi.nl:/pub/audio/RIFF-format.
The file format WAVE is described as a chunked file that has a header (AIFF's form chunk), a format chunk (common chunk in AIFF), and a variety of other optional chunks as shown (in pseudo-BNF form with ANSI-C-format comments) in Figure 11.

Figure 11. RIFF WAVE format file layout.

// RIFF/WAVE File Structure
 <WAVE-form> ->
	RIFF(			// File (FORM) header; type RIFF
				// (includes size field as in AIFF/C
		"WAVE"		// Local header; type WAVE
			<fmt-ck>	// Format (common) chunk
			[<fact-ck>]	// Fact chunk
			[<cue-ck>]	// Cue (marker) points
			[<playlist-ck>	// Play list (MIDI instr.)
			[<assoc-data-list>]	// Associated (annotation)
			<wave-data>	// Wave (sample) data

)

The chunk types of RIFF/WAVE correspond quite closely to those of AIFF, and the file structure is the same. Each file has a small header (the "RIFF/ WAVE" tag) a format (common) chunk with sample attributes, and a wave (sound sample-data) chunk. The other chunks are optional, and generally come after the common chunk and before the sample-data chunk. The parentheses used in the RIFF specifications are used to denote the inclusion of one chunk within another; for example, the line ''RIFF)'' means "place a RIFF chunk header here with an ID tag and the size of all the data included up to the matching ')" As in AIFF, the "outer wrapper" on a file (the AIFF form chunk or RIFF chunk header in Figure 11 "encapsulates" all the chunks within it, and these "inner" chunks can encapsulate structures of their own, as in the example of a marker chunk containing many marker records.
The WAVE format chunk specifies the format of the sample-data chunk. The format chunk is defined as shown in Figure 12. Note that it contains a collection of "common" fields, and also allocates space in the format chunk for additional, format-specific data fields. The wFormatTag field is a sample format flag similar to the one used in the NeXT/Sun format introduced above. The legal values for this are defined in a header file, and include linear integers, - and A-law, ADPCM, and other schemes including "Microsoft PCM," "IBM -law,' "IBM ADPCM," etc. The data types WORD and DWORD used here correspond to 16- and 32-bit integers (short and long in non-MicroSoft C). The type FOURCC is used for the 32-bit, 4-character identifier constants used in IFF and RIFF files.

Figure 12. WAVE format chunk.

// RIFF/WAVE Format chunk header
<fmt-ck> ->
	fmt(	// Format chunk header and size
		<common-fields>	// Standard fields
		<format-specific-fields>	// "Other"
)

// RIFF/WAVE format chunk common field data structure
	<common-fields> ->
		struct {	// Common fields chunk
			WORD wFormatTag;	// Format flag
			WORD wChannels;	// Number of channels
			DWORD dwSamplesPerSec;	// Sampling rate
			DWORD dwAvgBytesPerSec;   // For buffer estimation
			WORD  wBlockAlign;        // Data block size
		{

The <wave-data> contains the waveform sample data. It is defined in Figure 13, which shows that a data chunk may consist of a single data block, or of a list of data and silence blocks.

Figure 13. RIFF/WAVE wave data chunk format.

// RIFF/WAVE wave data chunk-1 or more data blocks
<wave-data> -> { <data-ck> : <wave-list> }

// Raw data chunk-header and data
<data-ck> ->
	data(  /> <wave-data> )

// Wave list chunk-header, data, and silence
<wave-list> ->
	LIST("wavl" {	// Wave list chunk header
		<data-ck>	// Wave samples
		<silence-ck> }	// Silence
		// More data or silence

// Silence chunk-length in samples
<silence-ck> -> slnt( DWORD dwSamples )

The cue-point chunk identifies a series of positions in the waveform data stream. The cue chunk is just like an AIFF marker chunk, but has no name string, and the data structure used for a cue point is different. Its definition is given in Figure 14. The interpretation of the various sample, file, and block offsets depends on the disk and software being used, and can be rather complex (Microsoft 1992).

Figure 14. RIFF/WAVE cue point structure.

// Cue point data structure
<cue point> ->
	struct {
		DWORD dwName;	// Cue point name
		DWORD dwPosition;	// Sample offset of cue point
		FOURCC fccChunk;	// ID of chunk with cue point data
		DWORD dwChunkStart;	// File offset of cue point
		DWORD dwBlockStart;	// Block offset of cue point
		DWORD dwSampleOffset;	// Sample offset within the block
	}

The play-list chunk specifies a play order for a series of cue points. It can be used to loop through selected sections of a sound various numbers of times. The play list contains a number of play segments, whose data structure is given in Figure 15.

Figure 15. RIFF/WAVE play segment structure.

// RIFF/WAVE play segment structure
	<play-segment> ->
		struct {
		DWORD dwName;	// Cue point number
		DWORD dwLength;	// Loop length
		DWORD dwLoops;	// Number of repetitions
	}

The associated data list provides the ability to attach information such as labels to sections of the waveform data stream. It can also store miscellaneous annotational information, like AIFF's annotation chunk.


[ Index | Main Paragraph | Previous Paragraph | Next Paragraph ]