Unit 12.1A · Term 1

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

Lesson Presentation

12.1A-wave-library.pdf · Slides for classroom use

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

Apply

Write a program that reads a WAV file and prints its properties (channels, sample rate, duration).

Apply

Generate a 3-second tone at 261 Hz (middle C) and save it as "middle_c.wav".

Create

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?

The sample rate in Hz — how many samples are recorded per second (e.g., 44100 for CD quality).

Q2: How do you calculate the duration of a WAV file?

Duration = number of frames ÷ frame rate. For example: 88200 frames ÷ 44100 Hz = 2 seconds.

Q3: What module helps convert between bytes and integer sample values?

The struct module — use struct.pack('<h', value) to convert int → bytes, and struct.unpack() for bytes → int.