Project Overview & Difficulty Rating
The Raspberry Pi lacks an onboard analog-to-digital converter (ADC) for audio input. To record audio on a Raspberry Pi, you must bypass this limitation by using an external ADC. The most reliable, low-noise method is an I2S MEMS microphone like the Adafruit SPH0645LM4H, configured via ALSA and Python's sounddevice library. Unlike USB microphones that introduce latency and polling overhead, I2S microphones stream digital audio directly into the Pi's hardware PCM block, yielding studio-grade timing for DIY acoustic sensors, voice assistants, or wildlife monitoring rigs.
Estimated Time: 45 minutes
Target Board: Raspberry Pi 5 (8GB variant) running Raspberry Pi OS (Bookworm/Trixie 64-bit)
Required Parts List
| Component | Exact Variant / Model | Estimated Price (2026) |
|---|---|---|
| Microcontroller | Raspberry Pi 5 (8GB RAM) | $80.00 |
| Microphone | Adafruit I2S MEMS Mic Breakout (SPH0645LM4H) | $7.95 |
| Cooling | Raspberry Pi 5 Active Cooler | $5.00 |
| Wiring | Silicone Female-to-Female Jumper Wires (26 AWG) | $4.50 |
Note: The Pi 5 Active Cooler is mandatory here. The Pi 5 SoC will aggressively thermal-throttle under load, which alters the internal PLL clock dividers and introduces severe jitter into the I2S bit-clock, resulting in corrupted audio.
Hardware Wiring & Pin Mapping
The SPH0645LM4H communicates via the I2S (Inter-IC Sound) protocol. We must connect it to the Raspberry Pi's dedicated hardware PCM pins. Do not attempt to bit-bang I2S on arbitrary GPIO pins; the Linux kernel's ALSA driver relies on the hardware PCM peripheral for precise timing.
| Pi 5 Physical Pin | BCM GPIO Number | Pi 5 Function | SPH0645 Breakout Pin |
|---|---|---|---|
| Pin 1 | N/A (Power) | 3.3V Power | VIN |
| Pin 6 | N/A (Ground) | Ground | GND |
| Pin 12 | GPIO 18 | PCM_CLK (Bit Clock) | BCLK |
| Pin 35 | GPIO 19 | PCM_FS (Frame Sync / LRCLK) | LRCL |
| Pin 38 | GPIO 20 | PCM_DIN (Data In) | DOUT |
SEL pin. Leave it unconnected (floating) to default to the left channel, or tie it to GND to force the right channel. For this mono build, leave it floating.
Software Setup & Compilable Recording Script
Before writing code, we must instruct the Pi 5's bootloader to load the I2S device tree overlay and configure ALSA to recognize the microphone as the default input device.
Step 1: Enable the I2S Device Tree Overlay
Open the Pi 5 boot configuration file. Note that on Bookworm and newer 64-bit OS versions, the path is /boot/firmware/config.txt (not /boot/config.txt).
sudo nano /boot/firmware/config.txt
Add the following lines at the bottom of the file to enable the hardware I2S block and the memory-mapped audio overlay (which fixes static noise issues common with MEMS mics):
dtparam=i2s=on
dtoverlay=i2s-mmap
Reboot the Pi: sudo reboot.
Step 2: Configure ALSA Defaults
Create a system-wide ALSA configuration file so Python doesn't accidentally try to open the HDMI audio output as a microphone.
sudo nano /etc/asound.conf
Paste the following configuration to map the I2S card to a virtual mono device:
pcm.i2s_mic {
type plug
slave {
pcm "hw:0,0"
channels 1
rate 44100
format S32_LE
}
}
pcm.default {
type plug
slave.pcm "i2s_mic"
}
Step 3: Install Python Dependencies
sudo apt update
sudo apt install libportaudio2 python3-pip
pip3 install sounddevice numpy scipy --break-system-packages
Step 4: The Python Recording Script
This script targets the Raspberry Pi 5 hardware index, records 5 seconds of audio, and includes robust error handling for common ALSA/PortAudio failures.
import sounddevice as sd
from scipy.io import wavfile
import numpy as np
import sys
import time
# =========================================================
# Target Board: Raspberry Pi 5 (8GB) / Bookworm 64-bit
# Hardware: Adafruit SPH0645LM4H I2S MEMS Mic
# Pins: BCLK=GPIO18, LRCL=GPIO19, DOUT=GPIO20
# =========================================================
DURATION = 5 # seconds
SAMPLE_RATE = 44100
OUTPUT_FILE = "pi5_i2s_recording.wav"
def find_i2s_device():
"""Queries ALSA to find the I2S hardware index."""
devices = sd.query_devices()
for i, dev in enumerate(devices):
# Look for the standard Raspberry Pi I2S ALSA card name
if 'i2s' in dev['name'].lower() or 'snd_rpi' in dev['name'].lower():
if dev['max_input_channels'] > 0:
return i
return None
def main():
device_index = find_i2s_device()
if device_index is None:
print("[FATAL] No I2S input device found. Check 'arecord -l' and config.txt.")
sys.exit(1)
print(f"[INFO] Recording {DURATION}s from device {device_index} ({sd.query_devices(device_index)['name']})...")
try:
# The SPH0645 outputs 24-bit audio padded to 32-bit (S32_LE)
# We force 1 channel as defined in our /etc/asound.conf plug
audio_data = sd.rec(
int(DURATION * SAMPLE_RATE),
samplerate=SAMPLE_RATE,
channels=1,
dtype='int32',
device=device_index
)
# Block until recording is complete
sd.wait()
# Normalize and save as 16-bit WAV for broad compatibility
audio_normalized = np.int16((audio_data / np.max(np.abs(audio_data))) * 32767)
wavfile.write(OUTPUT_FILE, SAMPLE_RATE, audio_normalized)
print(f"[SUCCESS] Audio saved to {OUTPUT_FILE}")
except sd.PortAudioError as e:
print(f"[PORTAUDIO ERROR] {e}")
print("Fix: Ensure /etc/asound.conf forces channels=1 and format=S32_LE.")
sys.exit(1)
except Exception as e:
print(f"[UNEXPECTED ERROR] {e}")
sys.exit(1)
if __name__ == "__main__":
main()
Debugging: ALSA Errors and First Checks
Audio routing on Linux is notoriously fragile. If your script fails, do not guess. Look at the exact traceback and cross-reference it with the ranked causes below.
Exact Error: sounddevice.PortAudioError: Error opening InputStream: Invalid number of channels [PaErrorCode -9998]
- Cause 1 (Most Likely): ALSA is attempting to open a stereo stream, but the SPH0645 is strictly mono. PortAudio rejects the channel count mismatch.
- Cause 2: Your
/etc/asound.confis missing or thechannels 1directive was omitted from the plug slave definition. - Fix: Verify the
asound.conffile provided in Step 2. Ensure your Pythonsd.rec()call explicitly setschannels=1.
Exact Error: ALSA lib pcm_hw.c:1829:(_snd_pcm_hw_open) Invalid value for card
- Cause 1: The I2S device tree overlay failed to load at boot, meaning the kernel never created the
snd_rpi_i2s_cardhardware node. - Cause 2: You are editing
/boot/config.txtinstead of/boot/firmware/config.txton a modern Pi 5 Bookworm image. - Fix: Check the correct config path, ensure
dtparam=i2s=onis not commented out, and reboot.
- Verify Boot Config: Run
cat /boot/firmware/config.txt | grep i2sto confirmdtparam=i2s=onis active. - Verify Hardware Detection: Run
arecord -lin the terminal. You must seecard 0: sndrpihifiberry [snd_rpi_hifiberry_dac]or a similar I2S card listed. If it says "no soundcards found", the overlay failed. - Verify Physical Wiring: BCLK (GPIO 18) and LRCL (GPIO 19) are frequently swapped on breadboards. Double-check against the pin mapping table above.
Extending and Simplifying the Build
Depending on your project constraints, you may need to pivot from the I2S MEMS approach.
How to Simplify: The USB Audio Route
If editing ALSA configs and wiring I2S clocks feels like overkill, simplify the build by purchasing a Sabrent USB External Stereo Sound Adapter (~$8). Plug it into a Pi 5 USB 3.0 port, connect a standard 3.5mm electret microphone, and use the same Python script (it will auto-detect the USB card as the default ALSA input). The trade-off is higher latency (~15ms) and a slight USB polling noise floor, which is acceptable for voice commands but poor for acoustic FFT analysis.
How to Extend: True Stereo I2S & Network Streaming
To record true stereo audio, add a second SPH0645 breakout. Wire the second mic's DOUT to GPIO 21 (PCM_DOUT). Update your /etc/asound.conf to use the route plugin to map the two physical mono streams into a single stereo ALSA device.
To extend this into an IoT edge node, replace the wavfile.write block with an MQTT publisher (using the paho-mqtt library) to stream 1-second FLAC-encoded chunks to a central home automation server for real-time acoustic anomaly detection.
Frequently Asked Questions
Can I record audio on Raspberry Pi using the 3.5mm analog jack?
No. The 3.5mm jack on the Raspberry Pi 4 and 5 is strictly an audio output (line out/headphones) driven by an onboard DAC. It does not have an ADC or a microphone bias voltage circuit. Attempting to wire a microphone directly to the analog jack will yield silence and risks damaging the Pi's audio codec chip.
Why is my I2S microphone recording pure static or white noise?
The SPH0645LM4H has a known timing quirk where it outputs data on the falling edge of the bit clock, while the Raspberry Pi's default I2S master mode expects it on the rising edge. This phase mismatch results in corrupted bits that sound like loud white noise. Adding dtoverlay=i2s-mmap to your config.txt forces the kernel to use a memory-mapped DMA buffer that corrects this timing alignment. If static persists, ensure your Pi 5 is actively cooled; thermal throttling shifts the SoC clock domains and breaks I2S synchronization.
How do I record audio on Raspberry Pi continuously without destroying my SD card?
SD cards have limited write-erase cycles. Continuously writing WAV files to /home/pi/ will kill a standard microSD card in a few months. To prevent this, mount a tmpfs RAM disk in your /etc/fstab (e.g., tmpfs /mnt/ramdisk tmpfs nodev,nosuid,size=256M 0 0). Record your audio chunks to the RAM disk, process them in memory, and only write to the SD card (or push to a network drive) when a specific acoustic trigger threshold is met.






