If you are trying to get clean sound from a Raspberry Pi Model B, the direct answer is to bypass the onboard 3.5mm jack entirely and use an I2S DAC breakout board like the Adafruit MAX98357A (Product ID: 3006).
Let’s clear up the naming first: in 2026, "Model B" practically refers to the Raspberry Pi 4 Model B. The original 2012 Model B is obsolete, and the newer Pi 5 dropped the 3.5mm jack altogether. The Pi 4 Model B’s onboard 3.5mm audio is driven by PWM (Pulse Width Modulation), not a true DAC. This results in a notoriously high noise floor, a 60Hz hum, and terrible signal-to-noise ratio (SNR) that ruins both music playback and embedded voice-assistant projects. To get true 16-bit/24-bit digital-to-analog conversion with zero USB latency overhead, you need to route the I2S (Inter-IC Sound) bus directly from the Pi’s GPIO header to a dedicated DAC chip.
The Raspberry Pi Model B Audio Output Decision Matrix
Before soldering, you need to choose your audio routing path. Here is the decision framework for embedded Pi audio, terminating in the optimal hardware pick for custom builds.
| Audio Method | Hardware Example | Noise Floor / SNR | CPU / Bus Overhead | Best Use Case |
|---|---|---|---|---|
| Onboard 3.5mm (PWM) | Pi 4 Model B native jack | Poor (~60dB SNR, high hum) | High (PWM uses CPU cycles) | Basic system beeps only |
| USB Audio Dongle | Apple USB-C to 3.5mm adapter | Good (~95dB SNR) | Medium (USB polling latency) | Desktop media centers |
| I2S DAC HAT | HiFiBerry DAC+ Standard | Excellent (~110dB SNR) | Low (Direct hardware bus) | Audiophile / Line-out |
| I2S DAC Breakout (PICK) | Adafruit MAX98357A (PID 3006) | Great (~101dB SNR, 3.2W Amp) | Low (Direct hardware bus) | Embedded DIY, robotics, portable speakers |
Parts List & Hardware Pin Mapping
This guide targets the Raspberry Pi 4 Model B (4GB or 8GB variant) running Raspberry Pi OS (64-bit, Bookworm or newer). The pinout also applies directly to the Raspberry Pi 5.
Bill of Materials
- Microcontroller: Raspberry Pi 4 Model B (4GB+ recommended for DSP tasks)
- DAC/Amp: Adafruit MAX98357A I2S Breakout Board (PID 3006)
- Speaker: 4Ω or 8Ω passive speaker (3W max rating)
- Wiring: 5x female-to-female jumper wires (silicone stranded preferred)
GPIO Pin Mapping Table (BCM Numbering)
The I2S protocol requires three shared signal lines plus power and ground. Ensure your Pi is powered off and unplugged before wiring.
| MAX98357A Pin | Pi 4 Model B GPIO (BCM) | Pi 40-Pin Header Physical Pin | Function Description |
|---|---|---|---|
| VIN | 5V Power | Pin 2 or 4 | Power supply (3.5V - 5.5V acceptable) |
| GND | Ground | Pin 6 | Common ground reference |
| BCLK | GPIO 18 (PCM_CLK) | Pin 12 | Bit Clock (synchronizes data bits) |
| LRC | GPIO 19 (PCM_FS) | Pin 35 | Left/Right Clock (Word Select) |
| DIN | GPIO 21 (PCM_DOUT) | Pin 40 | Serial Audio Data In |
The MAX98357A has two extra pads:
GAIN and SD. Leave the SD (Shutdown) pad unconnected; the internal pull-up keeps the amp enabled. Solder the GAIN pad to GND to set the amplifier to 9dB (safest for small desktop speakers). Leaving it floating defaults to 15dB, which can clip and distort smaller 4Ω drivers.
Software Setup & ALSA Configuration
Raspberry Pi OS uses ALSA (Advanced Linux Sound Architecture) under the hood. To make the kernel recognize the I2S breakout, you must load the correct device tree overlay.
- Edit the boot configuration file. In modern Raspberry Pi OS (Bookworm and later), the config file moved to
/boot/firmware/. Open it with nano:sudo nano /boot/firmware/config.txt - Enable the I2S bus and load the overlay. Add or uncomment these lines at the bottom of the file:
Note: If you are using a generic I2S DAC without a specific overlay, usedtparam=i2s=on dtoverlay=max98357adtoverlay=hifiberry-dacinstead. See the official Raspberry Pi Device Tree Documentation for a full list of audio overlays. - Reboot the Pi to apply the device tree changes:
sudo reboot - Verify ALSA sees the hardware. Run
aplay -l. You should seecard 0: max98357aorcard 0: sndrpihifiberrylisted. - Install Python audio dependencies. We will use
sounddevice(a PortAudio wrapper) andscipyfor WAV parsing:sudo apt update sudo apt install libportaudio2 python3-scipy pip3 install sounddevice numpy
Complete Python Audio Playback Code
This script targets the Raspberry Pi 4 Model B. It dynamically queries ALSA for the I2S device, plays a WAV file if provided, and falls back to generating a 440Hz sine wave test tone if the file is missing. This guarantees you can verify your wiring without hunting for audio assets.
import numpy as np
import sounddevice as sd
import scipy.io.wavfile as wav
import sys
import os
# --- Configuration & Pin/Device Definitions ---
TARGET_DEVICE_KEYWORD = "max98357a" # Fallback: "hifiberry" or "sndrpi"
SAMPLE_RATE = 44100
DEFAULT_WAV_FILE = "test_audio.wav"
def find_i2s_device():
"""Queries ALSA/PortAudio to find the I2S DAC index."""
devices = sd.query_devices()
for i, dev in enumerate(devices):
if TARGET_DEVICE_KEYWORD in dev['name'].lower() and dev['max_output_channels'] > 0:
return i
# Fallback: Look for generic I2S/HifiBerry names
for i, dev in enumerate(devices):
if ('hifiberry' in dev['name'].lower() or 'sndrpi' in dev['name'].lower()) and dev['max_output_channels'] > 0:
return i
return None
def generate_sine_wave(freq=440.0, duration=3.0, sr=SAMPLE_RATE):
"""Generates a fallback test tone if no WAV file is present."""
t = np.linspace(0, duration, int(sr * duration), False)
# Generate stereo sine wave (MAX98357A is mono, but ALSA often expects stereo streams)
wave = np.sin(2 * np.pi * freq * t)
return np.column_stack((wave, wave)) * 0.5 # 50% volume to protect speakers
def main():
device_idx = find_i2s_device()
if device_idx is None:
print("[FATAL] Could not find I2S audio device in ALSA.")
print("Run 'aplay -l' to verify the dtoverlay loaded correctly.")
sys.exit(1)
print(f"[INFO] Targeting Audio Device {device_idx}: {sd.query_devices(device_idx)['name']}")
audio_data = None
sr = SAMPLE_RATE
# Attempt to load WAV file, fallback to sine wave
if os.path.exists(DEFAULT_WAV_FILE):
print(f"[INFO] Loading {DEFAULT_WAV_FILE}...")
sr, audio_data = wav.read(DEFAULT_WAV_FILE)
if audio_data.ndim == 1:
audio_data = np.column_stack((audio_data, audio_data)) # Mono to Stereo
else:
print(f"[WARN] {DEFAULT_WAV_FILE} not found. Generating 440Hz test tone.")
audio_data = generate_sine_wave()
# Normalize data to float32 [-1.0, 1.0] for PortAudio
if audio_data.dtype != np.float32:
max_val = np.iinfo(audio_data.dtype).max if np.issubdtype(audio_data.dtype, np.integer) else 1.0
audio_data = (audio_data / max_val).astype(np.float32)
try:
print("[INFO] Starting audio stream...")
sd.play(audio_data, samplerate=sr, device=device_idx, blocking=True)
print("[INFO] Playback complete.")
except sd.PortAudioError as e:
print(f"[ERROR] PortAudio failed: {e}")
print("Check if another process (like PulseAudio/PipeWire) is hogging the ALSA device.")
sys.exit(2)
except Exception as e:
print(f"[ERROR] Unexpected failure: {e}")
sys.exit(3)
if __name__ == "__main__":
main()
Debugging: "ALSA: Couldn't open audio device" & Other Failures
When working with ALSA and I2S on the Pi, things will break. Here are the first three things to check when audio fails, followed by a breakdown of specific error strings.
The First Three Checks
- Verify the Device Tree Overlay: Run
vcdbg log msg 2>&1 | grep dtor simplyaplay -l. If the MAX98357A doesn't show up as a sound card, yourconfig.txtsyntax is wrong, or you edited the wrong file (remember, it's/boot/firmware/config.txton modern OS). - Check BCLK/LRCLK Swap: If your code runs without errors but you hear only harsh white noise or static, you have almost certainly swapped the BCLK (GPIO 18) and LRCLK (GPIO 19) wires. The DAC is misinterpreting the clock timing.
- Kill Audio Daemons: Raspberry Pi OS runs PipeWire or PulseAudio by default, which can lock the ALSA hardware device. Run
systemctl --user stop pipewire pulseaudiobefore running raw Python ALSA scripts.
Exact Error Strings & Ranked Causes
| Exact Error String | Ranked Causes (Most Likely First) | Fix |
|---|---|---|
sounddevice.PortAudioError: Error opening OutputStream: Invalid device [PaErrorCode -9996] |
1. Device index not found. 2. dtoverlay missing in config.txt.3. Targeting an input-only device. |
Run python3 -m sounddevice to print all devices. Update the TARGET_DEVICE_KEYWORD in the script to match the exact string ALSA reports. |
ALSA lib pcm_dmix.c:1032:(snd_pcm_dmix_open) unable to open slave |
1. PipeWire/PulseAudio has exclusive lock. 2. Another script is actively playing audio. |
Stop the audio daemon (systemctl --user stop pipewire) or configure PortAudio to use the plug ALSA device instead of hw. |
ValueError: could not broadcast input array from shape (X,) into shape (Y,) |
1. WAV file is mono, but PortAudio is trying to map it to a 2-channel (stereo) I2S stream. | The provided code handles this via np.column_stack, but if writing your own, ensure you duplicate mono arrays into a 2D stereo matrix before passing to sd.play(). |
Extending and Simplifying the Build
Once you have clean I2S audio output, you will inevitably want to tweak the system. Here is how to scale the project up or down based on your final application.
How to Extend (Scale Up)
- Add Hardware Volume Control: The MAX98357A lacks a digital volume register; it only has hardware gain pads. To add software volume control without eating CPU cycles in Python, insert an ALSA
softvolplugin in your~/.asoundrcfile. This creates a virtual mixer control that ALSA handles at the kernel level before passing bits to the I2S bus. - Integrate a DSP: If you are building a smart speaker or room-correction system, route the I2S output through an ADAU1701 SigmaDSP chip before the amplifier. This allows you to apply EQ, crossovers, and limiters in hardware.
- Add I2S Input (Microphone): To make this a two-way voice assistant, wire an INMP441 MEMS microphone to the I2S input pins (GPIO 19/20) and use the
dtoverlay=googlevoicehat-soundcardoverlay, which supports simultaneous I2S playback and capture.
How to Simplify (Scale Down)
If wiring five GPIO pins and debugging ALSA device tree overlays feels like overkill for a simple kiosk or notification speaker, abandon I2S and use a USB Audio Adapter. A $10 generic CM108-based USB sound card will show up as a standard USB audio class device. It requires zero config.txt edits, works instantly with PipeWire, and bypasses the Pi's noisy onboard PWM circuitry entirely. However, you sacrifice the ultra-low latency and hardware synchronization that I2S provides for robotics and DSP applications.
For any embedded project requiring reliable, low-latency, and noise-free audio on the Raspberry Pi 4 Model B, the I2S route via the MAX98357A remains the undisputed benchmark. Wire it correctly, verify your device tree overlays, and let the hardware bus do the heavy lifting.






