To record audio on a Raspberry Pi, you need an external microphone because the Pi lacks an onboard analog-to-digital converter (ADC) for audio input. While USB microphones are plug-and-play, they introduce latency and consume a USB port. The most reliable, low-latency method for embedded projects is wiring an I2S MEMS microphone directly to the Pi's GPIO header and capturing the digital audio stream via Python. This guide walks through the exact hardware, OS-level device tree overlays, and Python scripting required to get a clean WAV file from a digital MEMS mic.

Hardware Requirements and Pin Mapping

For this build, we are bypassing analog amplification entirely. MEMS (Micro-Electro-Mechanical Systems) microphones output a digital Pulse Density Modulation (PDM) or I2S signal directly. We will use an I2S variant because the Raspberry Pi's hardware I2S peripheral handles the clocking natively, offloading the CPU.

Parts List

Component Exact Variant / Model Estimated Cost
Single-Board Computer Raspberry Pi 4 Model B (4GB RAM) $55.00
Microphone Adafruit I2S MEMS Mic Breakout (SPH0645LM4H, PID: 3421) $6.95
Storage SanDisk 32GB MicroSD (Class 10, A1) $8.00
Wiring 22 AWG solid core jumper wires (female-to-female) $4.00

GPIO Pin Mapping

The I2S protocol requires three shared signal lines: Bit Clock (BCLK), Word Select / Left-Right Clock (LRCLK), and Serial Data (DIN). The SPH0645LM4H is a mono microphone, so we will tie the LRCLK pin to ground to force it into a specific channel slot, or let the Pi handle the mono-to-stereo duplication in software.

Mic Breakout Pin Raspberry Pi 4 BCM Pin Physical Header Pin Function
VIN 3.3V Power Pin 1 Power supply (do not use 5V)
GND Ground Pin 6 Common ground reference
BCLK BCM 18 (PCM_CLK) Pin 12 I2S Bit Clock
LRCLK BCM 19 (PCM_FS) Pin 35 I2S Word Select (Frame Sync)
DOUT BCM 20 (PCM_DIN) Pin 38 I2S Serial Data Output
Bench Tip: I2S clocks run at high frequencies (often 1.4MHz+ for BCLK). Avoid using long, unshielded breadboard jumper wires. Parasitic capacitance on breadboards can round off the square-wave clock edges, causing the Pi's I2S peripheral to miss bit shifts and resulting in heavy static. Keep wires under 3 inches.

OS Configuration and I2S Overlay Setup

The Raspberry Pi does not enable the I2S peripheral by default. You must load a Device Tree Overlay to tell the kernel to route the PCM clocks to the GPIO header and load the appropriate ALSA (Advanced Linux Sound Architecture) driver.

Target OS: Raspberry Pi OS (64-bit, Bookworm or newer). Note that in Bookworm, the boot partition is mounted at /boot/firmware/ instead of /boot/.

  1. Install PortAudio dependencies: Python's audio libraries rely on PortAudio. Open a terminal and run:
    sudo apt update && sudo apt install libportaudio2 python3-pip python3-numpy python3-scipy -y
  2. Install the Python audio library:
    pip3 install sounddevice --break-system-packages
  3. Edit the boot configuration:
    sudo nano /boot/firmware/config.txt
  4. Enable I2S and load the overlay: Add the following lines to the bottom of the file. We use the googlevoicehat-soundcard overlay because it natively supports the BCM 18/19/20/21 pinout and handles the SPH0645's specific timing quirks.
    dtparam=i2s=on
    dtoverlay=googlevoicehat-soundcard
  5. Disable the onboard audio driver (optional but recommended): Comment out the default audio line to prevent ALSA from defaulting to the HDMI/analog jack:
    #dtparam=audio=on
  6. Reboot the Pi:
    sudo reboot
  7. Verify ALSA detection: After rebooting, run arecord -l. You should see 'sndrpigooglevoicehat' listed as card 0 or 1.

Python Recording Script with Error Handling

This code targets the Raspberry Pi 4 Model B running Raspberry Pi OS 64-bit. It uses the sounddevice library to capture a 5-second audio stream at 32kHz (the native sweet spot for the SPH0645LM4H) and saves it as a 16-bit PCM WAV file.

import sounddevice as sd
import numpy as np
from scipy.io.wavfile import write
import time
import sys

# Hardware Pin Mapping (BCM) for I2S MEMS Microphone
# Note: sounddevice uses ALSA device indices, but these are the
# physical BCM pins configured in /boot/firmware/config.txt
HARDWARE_PIN_MAP = {
    'BCLK': 'BCM 18 (Pin 12)',
    'LRCLK': 'BCM 19 (Pin 35)',
    'DIN': 'BCM 20 (Pin 38)',
    'VCC': '3.3V (Pin 1)',
    'GND': 'GND (Pin 6)'
}

# Recording Parameters
SAMPLE_RATE = 32000  # SPH0645 native rate, avoids ALSA resampling artifacts
CHANNELS = 1         # Mono
DURATION = 5         # Seconds
DTYPE = 'int16'      # 16-bit PCM
OUTPUT_FILE = 'mems_recording.wav'

def record_audio():
    print(f"Hardware Map Verified: BCLK on {HARDWARE_PIN_MAP['BCLK']}")
    print(f"Starting {DURATION}-second recording at {SAMPLE_RATE}Hz...")
    
    try:
        # Query available devices to ensure ALSA sees the I2S mic
        devices = sd.query_devices()
        print(f"Detected Audio Devices: {len(devices)}")
        
        # Record the audio stream into a numpy array
        audio_data = sd.rec(
            int(DURATION * SAMPLE_RATE), 
            samplerate=SAMPLE_RATE, 
            channels=CHANNELS, 
            dtype=DTYPE
        )
        
        # Block until recording is complete
        sd.wait()
        print("Recording complete. Saving to disk...")
        
        # Write to WAV file
        write(OUTPUT_FILE, SAMPLE_RATE, audio_data)
        print(f"Success: Audio saved to {OUTPUT_FILE}")
        
    except sd.PortAudioError as e:
        print(f"[FATAL] PortAudio Error: {e}")
        print("Check ALSA configuration and I2S wiring.")
        sys.exit(1)
    except Exception as e:
        print(f"[ERROR] Unexpected failure: {e}")
        sys.exit(1)

if __name__ == '__main__':
    record_audio()

Debugging: 'Invalid Sample Rate' and Common Errors

When working with raw I2S on the Pi, ALSA configuration mismatches are the primary point of failure. If your script crashes immediately upon calling sd.rec(), look for this exact error string:

sounddevice.PortAudioError: Error opening InputStream: Invalid sample rate [PaErrorCode -9997]

Ranked Causes and Fixes

  1. ALSA Default Sample Rate Mismatch (Most Likely): The SPH0645LM4H hardware natively outputs at 32kHz or 48kHz depending on the BCLK frequency. If your code requests 44.1kHz (the CD-audio standard) and the ALSA plug plugin isn't configured to resample, PortAudio will throw PaErrorCode -9997. Fix: Change your Python SAMPLE_RATE to 32000 or 48000, or configure an ALSA ~/.asoundrc file to force software resampling.
  2. Missing Device Tree Overlay: If the dtoverlay=googlevoicehat-soundcard line is missing or misspelled in config.txt, the Pi falls back to the dummy HDMI audio driver, which does not support input streams. Fix: Verify the overlay with dtoverlay -l after boot.
  3. Hardware Wiring Fault on LRCLK: If the BCM 19 (LRCLK) wire is loose or broken, the Pi's I2S peripheral cannot synchronize the frame boundaries. The driver will fail to initialize the stream. Fix: Measure continuity from the mic breakout to Pin 35 with a multimeter.

The First Three Things to Check When It Fails

If you get no audio or the script hangs, run through this triage sequence:

  1. Run arecord -l: If the command returns 'no soundcards found', your OS overlay is broken. Fix config.txt.
  2. Run arecord -D hw:0,0 -f S32_LE -r 32000 -c 1 test.wav: Test the hardware directly from the CLI. If this produces a file with static, your wiring has parasitic capacitance or a bad ground. If it produces silence, your DIN (Data) pin is swapped or dead.
  3. Check I2S Voltage Levels: The Pi's GPIO is 3.3V. Ensure you are powering the MEMS mic from the 3.3V pin (Pin 1), not the 5V pin. Feeding 5V into the SPH0645 will permanently fry the internal ASIC.

Extending and Simplifying the Build

How to Extend: To capture stereo audio, add a second identical SPH0645 breakout. Wire the second mic's BCLK and LRCLK to the same BCM 18 and 19 pins, but connect its DOUT to BCM 21 (Pin 40). You will then need to write a custom ALSA asound.conf file using the multi plugin to interleave the two mono hardware streams into a single stereo virtual device. For network streaming, pipe the numpy array directly into an MQTT payload or a WebRTC socket instead of writing to disk.

How to Simplify: If you want to skip the device tree overlays and wiring entirely, purchase a pre-assembled I2S microphone HAT, such as the Adafruit Voice Bonnet. It plugs directly onto the header and includes a pre-compiled driver script. Alternatively, if GPIO is unavailable, a basic $10 USB mini-microphone (like the Vantec) will work with the exact same Python script, provided you change the sounddevice device index to match the USB audio card.

Frequently Asked Questions

How do I record audio on Raspberry Pi without a USB microphone?

You must use the GPIO header. The Raspberry Pi does not have an onboard analog-to-digital converter (ADC) or a built-in microphone. The two alternatives to USB are wiring an analog microphone to an external ADC (like the MCP3008) and reading it via SPI, or using a digital I2S MEMS microphone as shown in this guide. The I2S MEMS route is vastly superior for audio quality because it bypasses analog noise pickup on the breadboard.

Why is my Raspberry Pi audio recording full of static noise?

Static in I2S recordings is almost always a clocking issue. The SPH0645LM4H is notorious for a slight timing offset on the LRCLK falling edge, which can cause the Pi to read the data line one bit late, resulting in a harsh, digital white noise. Using the googlevoicehat-soundcard overlay usually patches this at the driver level. If static persists, shorten your jumper wires, add a 10k pull-up resistor on the BCLK line, and ensure the Pi and mic share a dedicated, short ground path.

Can I record audio and video simultaneously on Raspberry Pi?

Yes, but doing so requires careful thread management. The Pi's camera module (via libcamera or Picamera2) and the I2S audio stream both consume significant DMA (Direct Memory Access) bandwidth. To record both without dropping audio frames, run the camera capture in a separate Python thread or process, and use a library like ffmpeg via subprocess to mux the raw video feed and the ALSA audio stream into an MP4 container in real-time. For reference on Pi hardware configuration, consult the official Raspberry Pi documentation.