Wave Library
Python's built-in wave module reads and writes WAV audio
files. Combined with the struct module, you can analyze sound data, modify
volume, reverse audio, and even generate tones from scratch.
Learning Objectives
- 12.6.3.1 Use commands of the Wave library to process sound files
Conceptual Anchor
The Sound Wave Analogy
Sound is a pressure wave in the air. A WAV file stores this wave as a long list
of numbers (samples). Each sample is the "height" of the wave at one moment in
time. More samples per second (sample rate) = higher quality. wave
gives you access to this raw data.
Rules & Theory
WAV File Properties
| Property | Description | Typical Value |
|---|---|---|
| Channels | 1 = mono, 2 = stereo | 1 or 2 |
| Sample Width | Bytes per sample | 2 (16-bit audio) |
| Frame Rate | Samples per second (Hz) | 44100 (CD quality) |
| Frames | Total number of samples | Varies by duration |
| Duration | Frames ÷ Frame Rate | Calculated |
Reading a WAV File
| Method | Description |
|---|---|
wave.open(file, "rb") |
Open WAV file for reading |
.getnchannels() |
Number of channels (1 or 2) |
.getsampwidth() |
Sample width in bytes |
.getframerate() |
Sample rate (e.g., 44100) |
.getnframes() |
Total number of frames |
.readframes(n) |
Read n frames as bytes |
.close() |
Close the file |
Writing a WAV File
| Method | Description |
|---|---|
wave.open(file, "wb") |
Open WAV file for writing |
.setnchannels(n) |
Set number of channels |
.setsampwidth(n) |
Set sample width in bytes |
.setframerate(n) |
Set sample rate |
.writeframes(data) |
Write audio data (bytes) |
.close() |
Close the file |
Worked Examples
1 Reading WAV File Info
import wave
with wave.open("song.wav", "rb") as wav:
channels = wav.getnchannels()
sample_width = wav.getsampwidth()
frame_rate = wav.getframerate()
n_frames = wav.getnframes()
duration = n_frames / frame_rate
print(f"Channels: {channels}")
print(f"Sample width: {sample_width} bytes")
print(f"Frame rate: {frame_rate} Hz")
print(f"Frames: {n_frames}")
print(f"Duration: {duration:.2f} seconds")2 Generating a Pure Tone (Sine Wave)
import wave
import struct
import math
# Parameters
frequency = 440 # A4 note (Hz)
duration = 2 # seconds
sample_rate = 44100 # CD quality
amplitude = 16000 # volume (max ~32767 for 16-bit)
# Generate samples
samples = []
for i in range(int(sample_rate * duration)):
t = i / sample_rate
value = int(amplitude * math.sin(2 * math.pi * frequency * t))
samples.append(struct.pack('<h', value)) # little-endian short
# Write WAV file
with wave.open("tone_440hz.wav", "wb") as wav:
wav.setnchannels(1) # mono
wav.setsampwidth(2) # 16-bit
wav.setframerate(sample_rate)
wav.writeframes(b''.join(samples))
print("Created tone_440hz.wav")3 Reversing Audio
import wave
import struct
# Read original
with wave.open("song.wav", "rb") as wav_in:
params = wav_in.getparams()
frames = wav_in.readframes(wav_in.getnframes())
# Unpack samples, reverse, repack
sample_width = params.sampwidth
fmt = '<' + 'h' * (len(frames) // sample_width)
samples = list(struct.unpack(fmt, frames))
samples.reverse()
reversed_data = struct.pack(fmt, *samples)
# Write reversed WAV
with wave.open("reversed.wav", "wb") as wav_out:
wav_out.setparams(params)
wav_out.writeframes(reversed_data)
print("Audio reversed!")4 Adjusting Volume
import wave
import struct
factor = 0.5 # 50% volume
with wave.open("song.wav", "rb") as wav_in:
params = wav_in.getparams()
frames = wav_in.readframes(wav_in.getnframes())
# Reduce each sample amplitude
fmt = '<' + 'h' * (len(frames) // params.sampwidth)
samples = struct.unpack(fmt, frames)
quieter = [max(-32768, min(32767, int(s * factor))) for s in samples]
output = struct.pack(fmt, *quieter)
with wave.open("quiet.wav", "wb") as wav_out:
wav_out.setparams(params)
wav_out.writeframes(output)
print("Volume reduced to 50%")Common Pitfalls
WAV Only!
The wave module ONLY works with .wav files. It cannot read MP3,
FLAC, or other formats. Use pydub or ffmpeg to convert other formats
first.
16-bit Range: –32768 to 32767
When modifying samples, always clamp values to the valid range. Values outside this range will cause distortion or errors.
Tasks
Write a program that reads a WAV file and prints its properties (channels, sample rate, duration).
Generate a 3-second tone at 261 Hz (middle C) and save it as "middle_c.wav".
Write a program that doubles the volume of a WAV file and saves it as "loud.wav".
Self-Check Quiz
Q1: What does getframerate() return?
Q2: How do you calculate the duration of a WAV file?
Q3: What module helps convert between bytes and integer sample values?
struct module
— use struct.pack('<h', value) to convert int → bytes, and
struct.unpack() for bytes → int.