File Description: WAVE or RIFF WAVE sound file
File Extension: Commonly .wav, sometimes .wave
File Byte Order: Little-endian
Prof. Peter Kabal, MMSP Lab, ECE, McGill University: Last update: 2022-09-27
The WAVE file specifications came from Microsoft. The WAVE file format use RIFF chunks, each chunk consisting of a chunk identifier, chunk length and chunk data.
The European Broadcast Union (EBU) has standardized on an extension to the WAVE format that they call Broadcast WAVE format (BWF). It is aimed at carrying PCM or MPEG audio data. In its simplest form, it adds a <bext> chunk with additional metadata. Full documentation is available on line from the EBU.
The data in WAVE files can be of many different types. Data format codes are listed in the following:
Wave files have a master RIFF chunk which includes a WAVE identifier followed by sub-chunks. The data is stored in little-endian byte order.
Field | Length | Contents | |
---|---|---|---|
ckID |
4 | Chunk ID:
|
|
cksize |
4 | Chunk size: 4+n |
|
WAVEID |
4 | WAVE ID:
|
|
WAVE chunks | n |
Wave chunks containing format information and sampled data |
The fmt
specifies the format of the data. There are 3 variants
of the Format chunk for sampled data. These differ in the extensions to the
basic fmt
chunk.
Field | Length | Contents | |
---|---|---|---|
ckID |
4 | Chunk ID:
|
|
cksize |
4 | Chunk size: 16, 18 or 40 | |
wFormatTag |
2 | Format code | |
nChannels |
2 | Number of interleaved channels | |
nSamplesPerSec |
4 | Sampling rate (blocks per second) | |
nAvgBytesPerSec |
4 | Data rate | |
nBlockAlign |
2 | Data block size (bytes) | |
wBitsPerSample |
2 | Bits per sample | |
cbSize |
2 | Size of the extension (0 or 22) | |
wValidBitsPerSample |
2 | Number of valid bits | |
dwChannelMask |
4 | Speaker position mask | |
SubFormat |
16 | GUID, including the data format code |
The standard format codes for waveform data are given below. The references above give more format codes for compressed data, a good fraction of which are now obsolete.
Format Code | PreProcessor Symbol | Data |
---|---|---|
0x0001 |
WAVE_FORMAT_PCM |
PCM |
0x0003 |
WAVE_FORMAT_IEEE_FLOAT |
IEEE float |
0x0006 |
WAVE_FORMAT_ALAW |
8-bit ITU-T G.711 A-law |
0x0007 |
WAVE_FORMAT_MULAW |
8-bit ITU-T G.711 µ-law |
0xFFFE |
WAVE_FORMAT_EXTENSIBLE |
Determined by SubFormat |
The first part of the Format chunk is used to describe PCM data.
wBitsPerSample
). The original
documentation (Revision 1) specified that the number of bits per sample is to
be rounded up to the next multiple of 8 bits. This rounded-up value is the
container size. This information is redundant in that the container size (in
bytes) for each sample can also be determined from the block size divided by
the number of channels (nBlockAlign
/ nChannels
).
An extended Format chunk is used for non-PCM data. The
cbSize
field gives the size of the extension.
wBitsPerSample
) should be
set to 8 bits.fact
chunk.The WAVE_FORMAT_EXTENSIBLE
format code indicates that there is
an extension to the Format chunk. The extension has one field which declares the
number of valid
bits/sample (wValidBitsPerSample
). Another
field (dwChannelMask
) contains bits which indicate the mapping from
channels to loudspeaker positions. The last field (SubFormat
) is a
16-byte globally unique identifier (GUID).
WAVE_FORMAT_EXTENSIBLE
format, the original
bits/sample field (wBitsPerSample
) must match the container size
(8 * nBlockAlign / nChannels
). This means that
wBitsPerSample
must be a multiple of 8. Reduced precision within the
container size is now specified by
wValidBitsPerSample
.wValidBitsPerSample
) is
informational only. The data is correctly represented in the precision of the
container size. The number of valid bits can be any value from 1 to the
container size in bits.WAVE_FORMAT_PCM
. The remaining 14 bytes contain
a fixed string,
\x00\x00\x00\x00\x10\x00\x80\x00\x00\xAA\x00\x38\x9B\x71
.The WAVE_FORMAT_EXTENSIBLE
format should be used whenever:
All (compressed) non-PCM formats must have a fact
chunk
(Rev. 3 documentation). The chunk contains at least one value, the number of
samples in the file.
Field | Length | Contents | |
---|---|---|---|
ckID |
4 | Chunk ID:
|
|
cksize |
4 | Chunk size: minimum 4 | |
dwSampleLength |
4 | Number of samples (per channel) |
is required for all new new WAVE formats, but
is not requiredfor the standard
WAVE_FORMAT_PCM
file. One presumes that files with IEEE float
data (introduced after the Rev. 3 documention) need a fact
chunk.number of samplesfor multichannel data. The implication in the Rev. 3 documentation is that it should be interpreted to be
number of samples per channel. The statement in the Rev. 3 documentation is:
TheWith no mention of the number of channels in this computation, this implies thatnSamplesPerSec
field from the wave format header is used in conjunction with thedwSampleLength
field to determine the length of the data in seconds.
dwSampleLength
is the number of samples per channel.fact
chunk should be
used for (including those with PCM) WAVE_FORMAT_EXTENSIBLE
files. One example of a WAVE_FORMAT_EXTENSIBLE
with PCM data from Microsoft, does not have a fact
chunk.The data
chunk contains the sampled data.
Field | Length | Contents | |
---|---|---|---|
ckID |
4 | Chunk ID:
|
|
cksize |
4 | Chunk size: n |
|
sampled data | n |
Samples | |
pad byte | 0 or 1 | Padding byte if n is odd |
Consider sampled data with the following parameters,
Nc
channelsNs
. Each
block consists of Nc
samples.F
(blocks per second)M
bytes longField | Length | Contents | ||
---|---|---|---|---|
ckID |
4 | Chunk ID:
|
||
cksize |
4 | Chunk size: 4 + 24 + (8 + M*Nc*Ns +
(0 or 1) |
||
WAVEID |
4 | WAVE ID:
|
||
ckID |
4 | Chunk ID:
|
||
cksize |
4 | Chunk size: 16 | ||
wFormatTag |
2 | WAVE_FORMAT_PCM |
||
nChannels |
2 | Nc |
||
nSamplesPerSec |
4 | F |
||
nAvgBytesPerSec |
4 | F*M*Nc |
||
nBlockAlign |
2 | M*Nc |
||
wBitsPerSample |
2 | rounds up to 8*M |
||
ckID |
4 | Chunk ID:
|
||
cksize |
4 | Chunk size: M*Nc*Ns |
||
sampled data | M*Nc*Ns |
Nc*Ns channel-interleaved
M -byte samples |
||
pad byte | 0 or 1 | Padding byte if M*Nc*Ns is odd |
data
chunk). Some programs (naively) assume that for PCM
data, the preamble in the file header is exactly 44 bytes long (as in the
table above) and that the rest of the file contains sound data. This is not a
safe assumption.Field | Length | Contents | ||
---|---|---|---|---|
ckID |
4 | Chunk ID:
|
||
cksize |
4 | Chunk size: 4 + 26 + 12 + (8 + M*Nc*Ns
+ (0 or 1)) |
||
WAVEID |
4 | WAVE ID:
|
||
ckID |
4 | Chunk ID: ; |
||
cksize |
4 | Chunk size: 18 | ||
wFormatTag |
2 | Format code | ||
nChannels |
2 | Nc |
||
nSamplesPerSec |
4 | F |
||
nAvgBytesPerSec |
4 | F*M*Nc |
||
nBlockAlign |
2 | M*Nc |
||
wBitsPerSample |
2 | 8*M (float data) or 16 (log-PCM data) |
||
cbSize |
2 | Size of the extension: 0 | ||
ckID |
4 | Chunk ID:
|
||
cksize |
4 | Chunk size: 4 | ||
dwSampleLength |
4 | Nc*Ns |
||
ckID |
4 | Chunk ID:
|
||
cksize |
4 | Chunk size:
M*Nc*Ns |
||
sampled data | M*Nc*Ns |
Nc*Ns channel-interleaved
M -byte samples |
||
pad byte | 0 or 1 | Padding byte if
M*Nc*Ns is odd |
fmt
chunk does not have the extension size
field (cbSize
) or a fact
chunk is not present.Field | Length | Contents | ||
---|---|---|---|---|
ckID |
4 | Chunk ID:
|
||
cksize |
4 | Chunk size:
4 + 48 + 12 + (8 + M*Nc*Ns + (0
or 1 ) |
||
WAVEID |
4 | WAVE ID:
|
||
ckID |
4 | Chunk ID:
|
||
cksize |
4 | Chunk size: 40 | ||
wFormatTag |
2 | WAVE_FORMAT_EXTENSIBLE |
||
nChannels |
2 | Nc |
||
nSamplesPerSec |
4 | F |
||
nAvgBytesPerSec |
4 | F * M*Nc |
||
nBlockAlign |
2 | M*Nc |
||
wBitsPerSample |
2 | 8 * M |
||
cbSize |
2 | Size of the extension: 22 | ||
wValidBitsPerSample |
2 | at most 8*M |
||
dwChannelMask |
4 | Speaker position mask | ||
SubFormat |
16 | GUID (first two bytes are the data format code) | ||
ckID |
4 | Chunk ID:
|
||
cksize |
4 | Chunk size: 4 | ||
dwSampleLength |
4 | Nc*Ns |
||
ckID |
4 | Chunk ID:
|
||
cksize |
4 | Chunk size:
M*Nc*Ns |
||
sampled data | M*Nc*Ns |
Nc*Ns channel-interleaved
M -byte samples |
||
pad byte | 0 or 1 | Padding byte if M*Nc*Ns
is odd |
fact
chunk can normally be omitted if the sampled data is
in PCM format.WAVE_FORMAT_EXTENSIBLE
format code. For instance a file with
24-bit data declared as a standard
FORMAT_PCM
format code will not play, but a file with 24-bit
data declared as a WAVE_FORMAT_EXTENSIBLE
file with a WAVE_FORMAT_PCM
subcode can be played.