If you are building an embedded voice assistant, a wildlife acoustic monitor, or a smart intercom, relying on a bulky USB microphone introduces unnecessary latency, consumes a valuable USB port, and often requires a powered hub. The professional alternative for raspberry pi recording audio is tapping directly into the I2S (Inter-IC Sound) bus using a digital MEMS microphone. This bypasses the USB stack entirely, feeding raw digital audio straight into the Pi’s DMA controller.
In this guide, we will wire an Adafruit SPH0645LM4H I2S MEMS microphone to a Raspberry Pi 4 Model B, configure the ALSA audio subsystem under Raspberry Pi OS Bookworm, and write a robust Python script to capture WAV files without dropping frames.
Project Spec Sheet & Parts List
Before stripping wires, verify you have the exact hardware variants listed below. Substituting the microphone or the Pi model will change the pin mapping and device tree overlays required.
Estimated Time: 45 minutes.
Target Board: Raspberry Pi 4 Model B (4GB or 8GB) running Raspberry Pi OS Bookworm (64-bit).
| Component | Exact Model / Variant | Approx. Cost | Notes |
|---|---|---|---|
| Microcontroller | Raspberry Pi 4 Model B (4GB) | $55.00 | Pi 5 works but requires updated GPIO pinout verification for I2S. |
| Microphone | Adafruit I2S MEMS Mic (SPH0645LM4H) | $7.95 | Product ID: 3421. 24-bit I2S digital output. |
| Storage | 32GB MicroSD Card (Class 10 / A1) | $8.00 | A1 rating ensures minimum random I/O for OS stability. |
| Wiring | Female-to-Female Jumper Wires (20cm) | $4.00 | Use silicone-jacketed wires for flexibility and heat resistance. |
| Power Supply | Official Pi 4 USB-C Power Supply (5.1V / 3.0A) | $8.00 | Critical: Undervoltage causes I2S clock jitter and audio static. |
Hardware Wiring & Pin Mapping
The SPH0645LM4H communicates via the I2S protocol, which requires a Bit Clock (BCLK), a Word Select / Left-Right Clock (LRCLK), and a Serial Data line (DOUT). The Raspberry Pi 4 has dedicated hardware I2S pins mapped to specific GPIOs.
VCC pin with 3.3V (Pin 1) or 5V (Pin 2), but the data pins (BCLK, LRCLK, DOUT) are strictly 3.3V logic. Do not feed 5V into the data pins, or you will destroy the microphone's internal logic gates.
| Mic Breakout Pin | Raspberry Pi 4 GPIO | Pi Physical Pin # | Function |
|---|---|---|---|
| VCC | 3.3V Power | Pin 1 | Power input (3.3V - 5V acceptable) |
| GND | Ground | Pin 6 | Common ground reference |
| BCLK | GPIO 18 (PCM_CLK) | Pin 12 | Bit Clock (drives data shifting) |
| LRCLK | GPIO 19 (PCM_FS) | Pin 35 | Word Select (Left/Right frame sync) |
| DOUT | GPIO 20 (PCM_DIN) | Pin 38 | Serial Audio Data Out |
| SEL | Ground | Pin 9 | Tie to GND for Left Channel, 3.3V for Right |
Bench Tip: Keep the BCLK and DOUT wires as short as possible (under 10cm). I2S is a high-speed synchronous bus; long, unshielded jumper wires act as antennas and will inject electromagnetic interference (EMI) into your audio stream, manifesting as a high-frequency hiss.
Boot Configuration & ALSA Setup
By default, the Raspberry Pi routes audio to the HDMI or 3.5mm PWM jack. To enable the I2S hardware block, we must load a Device Tree Overlay.
Note: In Raspberry Pi OS Bookworm, the boot partition is mounted at /boot/firmware/, not /boot/ as in older Bullseye releases.
- Open the configuration file:
sudo nano /boot/firmware/config.txt - Find the line
dtparam=audio=onand comment it out by adding a#at the start. This disables the built-in PWM audio, which conflicts with I2S. - Add the following lines to the bottom of the file to enable the I2S overlay. We use the
googlevoicehat-soundcardoverlay because it correctly generates the master clock timing required by the SPH0645 without needing an external crystal oscillator.# Enable I2S MEMS Microphone dtparam=i2s=on dtoverlay=googlevoicehat-soundcard - Save the file (Ctrl+O, Enter) and exit (Ctrl+X).
- Reboot the Pi:
sudo reboot
After rebooting, verify the kernel loaded the audio driver by running aplay -l. You should see card 0: sndrpigooglevoicehat in the output. If you only see vc4hdmi, the overlay failed to load.
Python Recording Script with Error Handling
Capturing audio directly to disk in a single thread often causes buffer underruns (Xruns) because the SD card I/O blocks the CPU from reading the DMA buffer in time. The professional approach is to use a producer-consumer model: one thread reads the I2S stream into a queue, and the main thread writes from the queue to the WAV file.
Ensure you have the required libraries installed: pip install sounddevice numpy. For more on the underlying audio API, refer to the python-sounddevice documentation.
import sounddevice as sd
import wave
import queue
import threading
import sys
import numpy as np
# --- Configuration ---
# The SPH0645 outputs 24-bit data, but only 18 bits are valid (MSB aligned).
# We record as 32-bit integer to capture the full word, then normalize later.
SAMPLE_RATE = 44100
CHANNELS = 1
DTYPE = 'int32'
BLOCKSIZE = 1024 # Frames per buffer
RECORD_SECONDS = 10
OUTPUT_FILE = 'i2s_capture.wav'
# Queue for thread-safe audio passing
audio_queue = queue.Queue()
recording_active = True
def audio_callback(indata, frames, time, status):
"""Called by PortAudio in a separate thread for every audio block."""
if status:
print(f"[WARNING] Audio Callback Status: {status}", file=sys.stderr)
# Copy the numpy array and push to queue to prevent buffer overwriting
audio_queue.put(indata.copy())
def record_audio():
global recording_active
try:
# Device index 0 is typically the googlevoicehat I2S card
# Use `python -m sounddevice` to list exact device indices
with sd.InputStream(device=0, samplerate=SAMPLE_RATE, channels=CHANNELS,
dtype=DTYPE, blocksize=BLOCKSIZE, callback=audio_callback):
print(f"Recording {RECORD_SECONDS} seconds from I2S MEMS Mic...")
# Open WAV file for writing
with wave.open(OUTPUT_FILE, 'wb') as wf:
wf.setnchannels(CHANNELS)
wf.setsampwidth(4) # 4 bytes for int32
wf.setframerate(SAMPLE_RATE)
frames_recorded = 0
total_frames = SAMPLE_RATE * RECORD_SECONDS
while frames_recorded < total_frames:
# Get block from queue (blocks until data is available)
data = audio_queue.get()
wf.writeframes(data.tobytes())
frames_recorded += len(data)
print(f"Successfully saved to {OUTPUT_FILE}")
except sd.PortAudioError as e:
print(f"[FATAL] PortAudio Error: {e}", file=sys.stderr)
print("Check if the I2S overlay is loaded and ALSA device index is correct.")
except Exception as e:
print(f"[ERROR] Unexpected failure: {e}", file=sys.stderr)
finally:
recording_active = False
if __name__ == '__main__':
record_audio()
sox or ffmpeg) to normalize the volume.
Debugging: First Three Things to Check When It Fails
Embedded audio on Linux is notoriously fragile. If your script crashes or records silence, follow this ranked decision tree.
1. Exact Error: sounddevice.PortAudioError: Error opening InputStream: Invalid device [PaErrorCode -9996]
Cause: PortAudio cannot find the I2S sound card at device index 0, or ALSA has mapped the HDMI audio as the default device.
Fix: Run python -m sounddevice in the terminal to list all detected devices. Find the index number next to sndrpigooglevoicehat (it might be 1 or 2 if HDMI is 0). Update the device=X parameter in the Python script to match that exact integer.
2. Exact Error: arecord: main:830: audio open error: No such file or directory
Cause: The kernel module for the device tree overlay failed to load during boot, meaning the I2S hardware block was never initialized.
Fix: Run dmesg | grep -i i2s and dmesg | grep -i googlevoicehat. If you see errors about missing firmware or pinmux conflicts, you likely have a typo in /boot/firmware/config.txt. Ensure you commented out dtparam=audio=on. Re-run sudo raspi-config, go to Interface Options, and ensure I2C and SPI are disabled, as they sometimes fight for the PCM_CLK pins on certain HATs.
3. Symptom: Script runs, but the WAV file contains only static, loud clicking, or extreme white noise.
Cause: I2S clock jitter or a floating SEL pin. The Pi's internal PWM clock can sometimes introduce jitter if the CPU is heavily throttled.
Fix: First, verify the SEL pin on the microphone is firmly tied to GND. If it floats, the mic doesn't know which I2S timeslot to transmit in, resulting in digital garbage. Second, check your power supply. Run vcgencmd get_throttled. If it returns anything other than throttled=0x0, your Pi is browning out, causing the I2S bit-clock to stutter. Upgrade to a genuine 3.0A Pi power supply.
Extending and Simplifying the Build
How to Simplify: If writing Python threading code and managing ALSA overlays feels like overkill for a quick test, you can bypass Python entirely and use the native ALSA command-line tool. Once the overlay is active, simply run:
arecord -D plughw:0,0 -f S32_LE -r 44100 -c 1 -t wav -d 10 test.wav
This records 10 seconds of 32-bit audio directly to disk. It lacks the error handling of the Python script, but requires zero coding.
How to Extend: To turn this into a real-time voice recognition node, pipe the audio stream directly into a local inference engine like Vosk or OpenAI's Whisper. Instead of writing to a wave file, pass the indata bytes from the audio callback directly into the Vosk KaldiRecognizer object. For outdoor or industrial deployments, replace the jumper wires with a custom PCB and add a physical acoustic windscreen to prevent low-frequency rumble from saturating the MEMS diaphragm.
Frequently Asked Questions
How to record audio on Raspberry Pi without a USB microphone?
As demonstrated in this guide, the most robust method is using the I2S bus with a digital MEMS microphone (like the SPH0645 or INMP441). This provides digital clarity without USB latency. Alternatively, you can use an analog electret microphone connected to an external ADC (Analog-to-Digital Converter) like the MCP3008 via SPI, but this introduces quantization noise and requires complex software filtering. For plug-and-play simplicity without USB, I2S is the undisputed standard for embedded Pi audio.
Why is my Raspberry Pi I2S microphone producing static noise or a high-pitch whine?
High-pitch whining is almost always caused by power supply ripple or switching regulator noise from the Pi's internal DC-DC converters coupling into the microphone's VCC line. To fix this, insert a small ferrite bead on the VCC wire, or add a 100µF electrolytic capacitor and a 0.1µF ceramic capacitor in parallel across the VCC and GND pins on the breadboard. If the noise is a broadband "hiss," check your jumper wire lengths; I2S data lines longer than 15cm will pick up RF interference from the Pi's onboard Wi-Fi/Bluetooth antenna.
Can I use the Raspberry Pi recording audio setup for real-time voice recognition?
Yes, but you must manage latency carefully. The Python script provided uses a 1024-frame block size at 44.1kHz, which equates to roughly 23 milliseconds of audio latency per chunk. This is perfectly acceptable for local wake-word detection (like Porcupine) or offline transcription via Whisper. However, if you are streaming this audio over MQTT or WebSockets to a cloud API, you must implement a Voice Activity Detection (VAD) algorithm (like webrtcvad) to drop silent frames, otherwise, network jitter will cause the cloud buffer to overflow and drop your connection.






