Getting reliable, low-latency sound from Raspberry Pi 5 requires bypassing the board's native limitations. Unlike the Pi 4, the Pi 5 completely removed the analog PWM audio jack, leaving you with HDMI, USB, Bluetooth, or the 40-pin header's I2S bus. For embedded projects, kiosks, and interactive installations where audio triggers must fire in under 5 milliseconds, I2S (Inter-IC Sound) is the only professional choice. This guide walks through wiring an I2S DAC, configuring the Bookworm OS audio stack, and debugging the exact ALSA errors that inevitably pop up on the bench.
Raspberry Pi 5 Audio Architecture: Choosing Your Output
Before soldering headers, you need to understand the trade-offs between the Pi 5's audio routing options. The shift to Raspberry Pi OS Bookworm introduced PipeWire as the default audio server, which changed how software interacts with hardware outputs. Here is how the four primary methods compare for embedded deployments in 2026.
| Audio Method | Hardware Required | Typical Latency | Max Sample Rate | CPU Overhead | Best Use Case |
|---|---|---|---|---|---|
| I2S DAC (Header) | MAX98357A / PCM5102A ($6-$15) | ~2 - 5 ms | 192 kHz / 24-bit | Negligible (Hardware DMA) | Pinball machines, kiosks, synths |
| USB Audio Card | Generic USB dongle ($10) | ~15 - 40 ms | 48 kHz / 16-bit | Low (USB polling) | Desktop replacements, basic alerts |
| HDMI Audio | Monitor with speakers ($0 extra) | ~30 - 80 ms | 192 kHz / 24-bit | Moderate (Video sync) | Media centers, digital signage |
| Bluetooth A2DP | BT Speaker ($20+) | ~150 - 300 ms | 44.1 kHz / 16-bit | High (Encoding/Stack) | Portable prototypes, non-critical |
For this build, we are targeting the Raspberry Pi 5 (8GB model) running Raspberry Pi OS Bookworm (64-bit). We will use the Adafruit MAX98357A I2S 3W Class D Amplifier Breakout. This module is ideal because it includes the DAC and a speaker driver on a single board, requires no external MCLK (Master Clock) signal, and operates directly off the Pi's 5V rail.
Hardware Build: Wiring the MAX98357A I2S DAC
I2S uses three shared lines to transmit stereo audio data. The Bit Clock (BCLK) pulses for every bit of data, the Left/Right Clock (LRCLK) toggles to indicate which channel is active, and the Serial Data (DIN) line carries the actual audio payload. For 44.1kHz 16-bit stereo audio, the BCLK runs at exactly 1.4112 MHz.
Parts List
- Raspberry Pi 5 (8GB) with active cooler
- Adafruit MAX98357A I2S Breakout (Product ID: 3006)
- 4-ohm or 8-ohm speaker (3W max)
- Silicone jumper wires (female-to-female)
- 5V 5A USB-C PD power supply (Pi 5 requirement)
Pin Mapping Table
The Pi 5's I2S0 bus maps to specific GPIO pins. Do not confuse physical pin numbers with BCM GPIO numbers. The Raspberry Pi hardware documentation defines the standard I2S overlay mapping as follows:
| MAX98357A Pin | Function | Pi 5 BCM GPIO | Pi 5 Physical Pin | Wire Color (Suggested) |
|---|---|---|---|---|
| VIN | 5V Power | 5V | Pin 2 or 4 | Red |
| GND | Ground | GND | Pin 6 | Black |
| BCLK | Bit Clock | GPIO 18 | Pin 12 | Yellow |
| LRC | Left/Right Clock | GPIO 19 | Pin 35 | Green |
| DIN | Serial Data In | GPIO 21 | Pin 40 | Blue |
| GAIN | Amplifier Gain | N/A (Jumper) | Leave unconnected for 9dB | N/A |
Wiring Steps
- De-energize the board: Unplug the Pi 5's USB-C power cable. Never hot-plug I2S connections; a slipped wire on the 5V rail will instantly fry the GPIO bank.
- Connect Power: Route 5V from Physical Pin 2 to the MAX98357A
VIN, and GND from Physical Pin 6 toGND. - Connect Data Lines: Wire BCLK to Pin 12, LRC to Pin 35, and DIN to Pin 40. Double-check LRC and DIN; swapping them is the #1 cause of 'silent but no errors' failures.
- Configure Gain: Leave the
GAINpad unconnected for the default 9dB output. Solder it to GND for 15dB if driving a large 8-ohm cabinet speaker. - Verify: Use a multimeter in continuity mode to ensure no adjacent header pins are shorted before applying power.
Software Configuration and Python Playback Code
With the hardware seated, we must tell the Pi 5's kernel to route the I2S0 bus to an audio driver. In Raspberry Pi OS Bookworm, the configuration file moved from /boot/config.txt to /boot/firmware/config.txt.
Device Tree Overlay Setup
Open the configuration file: sudo nano /boot/firmware/config.txt.
Find the line dtparam=audio=on and comment it out by adding a # at the start. The onboard PWM audio driver conflicts with I2S overlays. Next, add the HiFiBerry DAC overlay at the bottom of the file. This overlay is the standard generic driver for I2S DACs that do not require an MCLK signal.
# Disable onboard PWM audio
#dtparam=audio=on
# Enable generic I2S DAC overlay for MAX98357A
dtoverlay=hifiberry-dac
Save the file and reboot the Pi. After rebooting, run aplay -l in the terminal. You should see card 0: sndrpihifiberry listed.
Python Playback Script
We will use pygame for audio playback because it handles mixing and format conversion well, but we must force it to bypass PipeWire and talk directly to ALSA to minimize latency. Install dependencies via terminal: sudo apt update && sudo apt install python3-pygame libsdl2-mixer-2.0-0.
import os
import sys
import time
# CRITICAL: Force SDL to use ALSA directly, bypassing PipeWire routing delays
os.environ['SDL_AUDIODRIVER'] = 'alsa'
# Target the specific ALSA hardware card identified by aplay -l
os.environ['AUDIODEV'] = 'hw:sndrpihifiberry,0'
os.environ['PYGAME_HIDE_SUPPORT_PROMPT'] = 'hide'
import pygame
def init_audio():
"""Initialize pygame mixer with I2S-optimized buffer settings."""
try:
# 44.1kHz, 16-bit signed, stereo, 512 byte buffer for low latency
pygame.mixer.init(frequency=44100, size=-16, channels=2, buffer=512)
print('[INFO] Audio initialized on I2S DAC.')
except pygame.error as e:
print(f'[FATAL] Pygame audio initialization failed: {e}')
sys.exit(1)
def play_sound(file_path):
"""Load and play a WAV or OGG file with error handling."""
if not os.path.exists(file_path):
print(f'[ERROR] Audio file not found: {file_path}')
return
try:
pygame.mixer.music.load(file_path)
pygame.mixer.music.play()
# Block execution until playback finishes
while pygame.mixer.music.get_busy():
pygame.time.Clock().tick(10)
except pygame.error as e:
print(f'[ERROR] Playback failed for {file_path}: {e}')
if __name__ == '__main__':
if len(sys.argv) < 2:
print('Usage: python3 pi_audio.py ')
sys.exit(1)
init_audio()
play_sound(sys.argv[1])
pygame.mixer.quit()
Debugging: Fixing ALSA and Pygame Audio Errors
Audio on Linux is notoriously fragile. When sound from Raspberry Pi projects fails, it is almost always a mismatch between the requested ALSA device and the active audio server. Here are the first three things to check before tearing apart your wiring:
- Check Overlay Conflicts: Run
vcgencmd overlay_enabled hifiberry-dac. If it returns0, yourconfig.txtsyntax is wrong, ordtparam=audio=onis still active and hogging the I2S pins. - Verify ALSA Enumeration: Run
aplay -l. If the Pi returnsaplay: device_list:276: no soundcards found..., the kernel module failed to load. Checkdmesg | grep sndfor I2C probe failures. - Test Raw Hardware: Bypass Python entirely. Run
speaker-test -D hw:sndrpihifiberry,0 -c 2 -t sine. If you hear a tone, your wiring is perfect and the issue is strictly in your Python environment variables.
Common Error Strings and Ranked Causes
pygame.error: No available audio deviceRanked Causes:
1.
SDL_AUDIODRIVER is defaulting to PulseAudio/PipeWire, which is failing to negotiate the sample rate with the I2S DAC.2. The
AUDIODEV environment variable points to hw:0,0, but the I2S DAC enumerated as card 1 due to a USB audio device taking priority.3. The Pi is running headless and the audio service hasn't spawned a user session.
ALSA lib pcm_hw.c:1829:(_snd_hw_open) open error: No such file or directoryRanked Causes:
1. The
dtoverlay=hifiberry-dac line is missing or misspelled in /boot/firmware/config.txt.2. You are using a Pi 5 and accidentally wired the DAC to the I2S1 pins (GPIO 18/19/20) instead of I2S0, or the physical pins are mapped to a different function via a conflicting overlay.
3. The BCLK or LRCLK wire is loose, causing the DAC's PLL to fail lock during the ALSA hardware probe. (See the ALSA Device Names wiki for hardware addressing rules).
Extending and Simplifying the Build
Once you have baseline sound from Raspberry Pi 5 working, you will likely need to adapt the circuit for production or scale it back for a simpler prototype.
How to Simplify (The USB Route)
If you are building a non-time-critical project (like a weather station that speaks the temperature once an hour) and I2S wiring is proving too difficult, drop the DAC and buy a $12 USB-C to 3.5mm audio adapter (ensure it uses a standard chipset like the C-Media CM108). Bookworm's PipeWire will auto-detect it. You can then delete the dtoverlay from config.txt and remove the os.environ overrides in the Python script. Latency will jump to ~30ms, but wiring drops to a single plug.
How to Extend (Stereo DSP and Multi-Room)
The MAX98357A is a mono amplifier. To drive true stereo, you need two modules. Because I2S is a bus, you can wire the BCLK and LRCLK pins of the Pi to both MAX98357A boards in parallel. To separate the channels, tie the SD (Shutdown/Format) pin of the left amplifier to GND, and the SD pin of the right amplifier to 5V. This tells the internal DACs to latch only the left or right time-slot of the LRCLK cycle.
For networked multi-room audio, integrate the shairport-sync daemon via apt. By pointing its output directly to hw:sndrpihifiberry in its /etc/shairport-sync.conf file, you can turn your embedded I2S build into an AirPlay receiver with zero software mixing latency, bypassing PipeWire entirely for the cleanest possible analog output.






