What Is WAV?
WAV (Waveform Audio File Format) is an uncompressed audio format developed jointly by Microsoft and IBM in 1991 as part of the Resource Interchange File Format (RIFF) specification. It is the foundational audio format of the Windows ecosystem and the universal standard for uncompressed professional audio storage.
WAV's core proposition is absolute simplicity: audio samples are stored in memory order with minimal overhead. There are no encoding transforms, no perceptual models, no quality tradeoffs — a WAV file is a direct, byte-for-byte representation of the PCM (Pulse Code Modulation) audio signal. This makes WAV the preferred "master" format in professional audio, broadcast, and sound design workflows.
RIFF Container Structure
WAV is a RIFF file — Resource Interchange File Format. RIFF organizes data into chunks, each with a four-character code (FourCC), a 32-bit length, and data:
struct RIFFChunk {
char id[4]; // FourCC identifier
uint32 size; // size of data field in bytes
char data[]; // chunk data
};
A WAV file is a RIFF chunk whose id is "RIFF" and data begins with "WAVE", followed by sub-chunks:
RIFF (4 bytes) + size (4 bytes) + "WAVE" (4 bytes)
├── fmt chunk — format descriptor
├── data chunk — PCM sample data
└── [optional chunks: LIST, cue , bext, smpl, fact...]
The fmt Chunk
The "fmt " (note trailing space) chunk describes the audio format:
Offset Size Field
0 2 AudioFormat: 1=PCM, 3=IEEE Float, 6=A-law, 7=µ-law, 0xFFFE=Extensible
2 2 NumChannels: 1=mono, 2=stereo, up to 18 for surround
4 4 SampleRate: e.g., 44100, 48000, 96000, 192000
8 4 ByteRate: SampleRate × NumChannels × BitsPerSample / 8
12 2 BlockAlign: NumChannels × BitsPerSample / 8 (bytes per sample frame)
14 2 BitsPerSample: 8, 16, 24, or 32
[16 2 ExtraParamSize: for non-PCM formats]
[18 ...] ExtraParams: for WAVE_FORMAT_EXTENSIBLE
WAVE_FORMAT_EXTENSIBLE (0xFFFE): An extension of the fmt chunk for files with more than 2 channels or non-standard configurations. It adds a channel mask (mapping speakers to channels), the actual bit depth (valid bits per sample), and a GUID identifying the true format.
The data Chunk
The "data" chunk contains raw PCM samples, interleaved by channel for multi-channel audio:
For stereo 16-bit: L0_lo L0_hi R0_lo R0_hi L1_lo L1_hi R1_lo R1_hi ...
Sample 0 Left Sample 0 Right Sample 1 Left...
Samples are in little-endian byte order (LSB first). For 24-bit audio:
Sample data: [byte_lo][byte_mid][byte_hi] per sample, packed without padding
Optional Chunks
| Chunk | Purpose |
|---|---|
LIST |
Metadata container (artist, title, etc.) using INFO sub-chunks |
cue |
Cue points/markers for loop start/end, regions |
bext |
Broadcast WAV Extension (BWF) — timecode, originator, description |
smpl |
Sampler data (loop points, MIDI note, pitch) for hardware samplers |
fact |
Required for non-PCM formats; stores sample count |
ID3 |
Embedded ID3v2 tags (non-standard but common) |
JUNK |
Padding to align data chunk to block boundaries |
PCM Sample Formats
8-bit PCM (Unsigned)
Range: 0 to 255. Silence = 128 (center). Rarely used — 48 dB dynamic range, very noisy. Historical use in phone audio and early computer sound.
16-bit PCM (Signed)
Range: −32,768 to +32,767. Silence = 0. The CD standard (44,100 Hz, 16-bit stereo = 1,411 kbps). Provides 96 dB theoretical dynamic range. The most common WAV format for consumer audio.
24-bit PCM (Signed)
Range: −8,388,608 to +8,388,607. Provides 144 dB theoretical dynamic range. The standard for professional recording, DAW sessions, and audio mastering. 24-bit at 48 kHz is the delivery standard for film/TV.
24-bit storage: 3 bytes per sample, little-endian
Byte layout: [low byte][mid byte][high byte]
No padding between samples within a channel
32-bit Float (IEEE 754)
WAVE_FORMAT_IEEE_FLOAT (AudioFormat = 3). Full 32-bit float range with ±infinity. Used internally by DAWs and audio plugins for headroom above 0 dBFS. Allows mixing without clipping in the processing chain. Not ideal for final delivery (no standard playback guarantee).
32-bit Integer (Signed)
Range: −2,147,483,648 to +2,147,483,647. Provides 192 dB theoretical dynamic range — far beyond any real-world use case. Sometimes used in high-precision scientific audio.
Sample Rate Standards
| Sample Rate | Use Case |
|---|---|
| 8,000 Hz | Telephone quality, speech compression |
| 11,025 Hz | Quarter CD — old multimedia |
| 22,050 Hz | Half CD — old game audio |
| 44,100 Hz | CD quality — consumer standard |
| 48,000 Hz | Professional video/film standard |
| 88,200 Hz | Double CD — archival audio |
| 96,000 Hz | High-definition audio, professional music |
| 176,400 Hz | Quad CD |
| 192,000 Hz | High-definition audio, scientific recording |
Film production uses 48 kHz. Music production often records at 96 kHz for headroom during processing, then downsamples to 44.1 kHz for CD/streaming delivery. DSD/SACD uses higher rates still (2.8 MHz, 5.6 MHz).
Broadcast WAV (BWF)
The Broadcast Wave Format (BWF, EBU Tech 3285) extends WAV with the bext chunk for professional broadcast workflows:
bext chunk fields:
Description[256] — program title or description
Originator[32] — creator name
OriginatorReference[32]
OriginationDate[10] — "YYYY:MM:DD"
OriginationTime[8] — "HH:MM:SS"
TimeReference[8] — timecode in samples (from midnight)
Version[2] — BWF version (0, 1, or 2)
UMID[64] — Unique Material Identifier (SMPTE 330M)
LoudnessValue[2] — integrated loudness (BWF v2)
LoudnessRange[2] — loudness range (BWF v2)
MaxTruePeakLevel[2] — (BWF v2)
MaxMomentaryLoudness[2]
MaxShortTermLoudness[2]
Reserved[180]
CodingHistory[] — processing history (variable length)
BWF is the standard in broadcast production — every radio station, TV studio, and film sound department uses BWF for file exchange. The TimeReference field embeds the audio start time within a recording session, enabling frame-accurate synchronization with video.
Dithering and Bit Depth Reduction
When reducing bit depth (e.g., 24-bit master → 16-bit delivery), quantization noise is introduced. Dithering adds a small amount of random noise before quantization to prevent the systematic distortion that creates audible artifacts (especially in quiet passages):
# FFmpeg: 24-bit to 16-bit with TPDF dither
ffmpeg -i master_24bit.wav -sample_fmt s16 -af "dither" output_16bit.wav
# sox: 24-bit to 16-bit with noise shaping (RPDF + noise shaping)
sox master.wav -b 16 output.wav rate -v 44100 dither -s
Noise-shaped dithering (like POW-r) shifts the dither energy into frequencies above 15 kHz where it's least audible. This is the professional standard for mastering.
Common WAV Workflows
Recording and DAW Export
# FFmpeg: convert from any format to WAV master
ffmpeg -i input.mp3 -c:a pcm_s24le -ar 48000 master.wav
# ffmpeg: 16-bit CD-quality WAV
ffmpeg -i input.flac -c:a pcm_s16le -ar 44100 output_cd.wav
# ffmpeg: check WAV properties
ffprobe -v quiet -print_format json -show_streams input.wav
Python (wave module — stdlib)
import wave
# Read WAV info
with wave.open('audio.wav', 'r') as w:
print(f"Channels: {w.getnchannels()}")
print(f"Sample width: {w.getsampwidth()} bytes ({w.getsampwidth()*8}-bit)")
print(f"Sample rate: {w.getframerate()} Hz")
print(f"Frames: {w.getnframes()}")
print(f"Duration: {w.getnframes()/w.getframerate():.2f}s")
# Create a 440Hz sine wave WAV
import struct, math
sample_rate = 44100
duration = 2.0
frequency = 440.0
samples = int(sample_rate * duration)
with wave.open('sine.wav', 'w') as w:
w.setnchannels(1)
w.setsampwidth(2) # 16-bit
w.setframerate(sample_rate)
for i in range(samples):
value = int(32767 * math.sin(2 * math.pi * frequency * i / sample_rate))
w.writeframes(struct.pack('<h', value))
Splitting and Merging
# Split stereo WAV to two mono files
ffmpeg -i stereo.wav -map_channel 0.0.0 left.wav -map_channel 0.0.1 right.wav
# Merge two mono WAV to stereo
ffmpeg -i left.wav -i right.wav -filter_complex "[0:a][1:a]amerge=inputs=2" stereo.wav
# Trim a WAV (start at 10s, duration 30s)
ffmpeg -i full.wav -ss 10 -t 30 clip.wav
# Concatenate WAV files
ffmpeg -i "concat:part1.wav|part2.wav|part3.wav" combined.wav
WAV vs FLAC vs AIFF
| Feature | WAV | FLAC | AIFF |
|---|---|---|---|
| Compression | None | Lossless (~50-60% smaller) | None |
| File size | Largest | Smallest lossless | Same as WAV |
| Max bit depth | 32-bit | 32-bit | 32-bit |
| Max channels | 18 (WAVE_EXT) | 8 | 2 (standard), more with AIFC |
| Metadata | Limited (LIST chunks) | Rich (Vorbis Comment) | Limited (MARK/INST chunks) |
| Streaming | Yes | Yes (seekable) | Yes |
| Mac compatibility | Good | Good | Native (Logic, GarageBand) |
| Broadcast standard | BWF extension | No | No |
| DAW support | Universal | Universal | Universal |
| Best for | Windows/broadcast | Storage/archival | Mac/Logic workflows |
When to Use WAV
Use WAV when:
- Maximum compatibility across all software is required
- Working in broadcast production (use BWF with bext chunk)
- Exporting from a DAW for mastering (lossless, no decode step)
- Real-time audio playback where decode latency is unacceptable
- Intermediate format in audio processing pipelines
Prefer FLAC when:
- Long-term archival where storage matters (50% smaller than WAV)
- Streaming lossless audio (FLAC is streamable and seekable)
- Maximum metadata support needed
Prefer AIFF when:
- Working in Logic Pro or GarageBand on Mac
- Need native Apple ecosystem compatibility with loop/region markers
WAV's persistence across 30+ years of audio technology evolution reflects an essential truth: sometimes the simplest format is the most durable, and "raw PCM in a RIFF wrapper" will never go obsolete.
Related conversions
Audio format pairs that come up most often: