Skip to content

FatherDivine/bt_audio-esp32

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Supported Targets ESP32 ESP32-C2 ESP32-C3 ESP32-C5 ESP32-C6 ESP32-C61 ESP32-S2 ESP32-S3 ESP32-P4 ESP32-H2

ESP32 WiFi Audio Streaming

This project implements WiFi-based audio streaming with MP3 and AAC decoding and flexible audio output (I2S or USB) for ESP32 boards. It automatically detects the chip model and configures audio output accordingly.

Requirements

  • ESP-IDF: Version 6.0 or later
  • Python: 3.6 or later (for ESP-IDF)
  • Hardware: Any supported ESP32 board (see table below)
  • For I2S Audio: External I2S DAC (PCM5102, MAX98357A, or UDA1334A)
  • For USB Audio: ESP32-S2, S3, or P4 with USB OTG support

Features

  • Multi-ESP32 Support: Auto-detects chip model and capabilities at runtime
  • Interactive Menu: Navigate with arrow keys or number keys (1-0) in ESP-IDF monitor
  • Hardware Auto-Detection: Automatically detects SD card, external BT module, and audio capabilities
  • MP3 Decoding: Built-in MP3 decoder using minimp3 library
  • AAC Decoding: Built-in AAC/HE-AAC decoder using libhelix-aac (auto-detected from stream Content-Type)
  • HTTP Audio Streaming: Stream audio from internet radio stations and other HTTP sources
  • SD Card Playback: Play MP3 files from SD card (when SD card module is connected)
  • Bluetooth Audio Output: Route audio to BT headphones via Acxico BT 4.1 module (line-level audio → BT wireless)
  • Serial Bluetooth (HC-05): UART bridge for serial data communication (SPP profile, no audio — for inter-device comms)
  • Dual Audio Output:
    • I2S Audio: High-quality audio output via I2S interface to external DAC
    • USB Audio: USB Audio Class (UAC) device mode for S2/S3/P4 (no external DAC needed)
  • Ring Buffer: Smooth audio playback with configurable ring buffer (32KB default)
  • UART Control: Interactive menu + legacy text commands via USB-C serial connection
  • Statistics: Real-time throughput monitoring and audio buffer level tracking

Supported ESP32 Variants

Chip WiFi Audio Output USB OTG Notes
ESP32-C5 WiFi 6 (2.4/5GHz) I2S to DAC Primary target
ESP32-C6 WiFi 6 (2.4GHz) I2S to DAC Similar to C5
ESP32-S3 WiFi 4 I2S or USB Audio USB audio device mode supported
ESP32-S2 WiFi 4 I2S or USB Audio USB audio device mode supported
ESP32-P4 N/A I2S or USB Audio USB audio capable
ESP32-C3 WiFi 4 I2S to DAC Budget option
ESP32 WiFi 4 I2S to DAC Original ESP32

Hardware Requirements

For detailed setup guides, see:

Option 1: I2S Audio (All ESP32 Chips)

External DAC required. Connect one of these I2S DAC boards:

  • MAX98357A - Popular, inexpensive I2S amplifier with built-in amp
  • PCM5102 - High-quality DAC with excellent audio (see PCM5102 configuration below)
  • UDA1334A - Good alternative DAC option

I2S Wiring (Default GPIO)

DAC Pin ESP32 GPIO Description
SLK GND System Clock
BCLK GPIO 4 Bit Clock
WS/LRCK GPIO 5 Word Select (L/R Clock)
DIN/SD GPIO 6 Serial Data
VIN 3.3V or 5V Power (check DAC specs)
GND GND Ground

Note: GPIO pins are configurable via menuconfig. See safe GPIO ranges for each chip in the configuration menu.

PCM5102 DAC Configuration

The PCM5102 requires proper hardware configuration in addition to wiring:

Physical Connections:

PCM5102 Pin    →  ESP32 Pin
----------------------------------------
SCK (System Clock) →  GND
BCK (Bit Clock)    →  GPIO 4 (configurable)
LCK/LRCK (L/R)     →  GPIO 5 (configurable)  
DIN (Data)         →  GPIO 6 (configurable)
VIN/VCC            →  3.3V (some boards support 5V)
GND                →  GND

Hardware Configuration (Critical!):

PCM5102 boards have configuration pins that must be set correctly:

  • FMT (Format): Must be set to I2S mode (usually pin tied to GND)
  • FLT (Filter): Normal latency mode (pin tied to GND)
  • DEMP (De-emphasis): Disabled for modern audio (pin tied to GND)
  • XSMT (Soft Mute): Must be tied to 3.3V to unmute the DAC (connecting to GND will mute all audio)

Common PCM5102 Boards (e.g., Teyleten Robot, GY-PCM5102):

These boards often have solder jumpers (H1L-H4L) that configure the above pins:

  • Ensure jumpers are set for I2S format (check board documentation)
  • Most boards come pre-configured correctly, but verify if audio doesn't work

Audio Output:

  • Connect headphones or powered speakers to the 3.5mm stereo jack on the PCM5102
  • Some PCM5102 boards also have L/R output pins for direct speaker connection
  • The PCM5102 is a line-level output (not amplified) - use powered speakers or headphones

Verification:

  • Power LED (usually red) should illuminate when powered
  • Use oscilloscope to verify I2S signals if debugging

Option 2: USB Audio (ESP32-S2/S3/P4 Only)

No external DAC required! The ESP32 appears as a USB audio input (UAC microphone/source) device to your computer.

USB Audio Setup:

  1. Connect ESP32-S2/S3/P4 USB port to your computer
  2. Enable USB audio in menuconfig (see configuration below)
  3. Flash and run - device appears as "ESP UAC Device" (default value of UAC_TUSB_PRODUCT)
  4. Select it as the audio input / recording device in your OS
  5. Audio from the ESP32 is sent to the host over USB; optionally enable input monitoring or route this input to your speakers/headphones if you want to hear it

Note: USB audio and UART cannot use the same USB port simultaneously. Use the dedicated UART port for serial monitor while using USB audio.

Option 3: SD Card Module — HiLetgo Micro SD Adapter (Optional)

Connect an SPI-based SD card module (e.g. HiLetgo Micro SD TF Card Adapter, 6-pin SPI interface) for local MP3 file playback. WiFi streaming is automatically stopped when SD card playback starts, and vice versa.

SD Module Pin ESP32 GPIO (Default) Description
MOSI GPIO 23 SPI Master Out Slave In
MISO GPIO 19 SPI Master In Slave Out
SCK GPIO 18 SPI Clock
CS GPIO 5 Chip Select
VCC 3.3V Power
GND GND Ground

GPIO pins are configurable via idf.py menuconfigSD Card Configuration. Enable SD card support in menuconfig to activate auto-detection at boot. See SD Card Setup Guide for detailed wiring and file structure.

Option 4: Acxico Bluetooth 4.1 Audio Module (Optional)

Connect an Acxico BT 4.1 Stereo Sound Module for wireless audio output to Bluetooth headphones/speakers. The module takes analog line-level audio from the I2S DAC output and transmits it wirelessly via Bluetooth 4.1 (≥10m range). UART (RX/TX) pins provide AT command configuration (device name, MAC address, connection status, etc.).

Acxico Pin Connection Description
+5V 5V Power supply
PGND GND Power ground
LED (observe) BT status indicator
RX ESP32 TX GPIO (configurable) UART receive (AT commands from ESP32)
TX ESP32 RX GPIO (configurable) UART transmit (AT responses to ESP32)
IN_L DAC Left out Left channel line-level audio input
IN_R DAC Right out Right channel line-level audio input
AGND DAC GND Audio ground (connect to DAC analog GND)
DP USB D+ USB sound card mode (optional, for PC)
DM USB D- USB sound card mode (optional, for PC)
CON USB detect USB connector detect (optional)

Audio path: ESP32 → I2S DAC (PCM5102) → analog L/R out → Acxico IN_L/IN_R → Bluetooth → headphones

GPIO pins and baud rate are configurable via idf.py menuconfigAcxico BT Audio Module Configuration. See Acxico BT Audio Setup Guide for detailed wiring, AT commands, and troubleshooting.

Option 5: External Bluetooth Module — HC-05 (Optional)

Connect an HC-05 (or similar Classic Bluetooth) module for serial data communication (SPP profile). Note: The HC-05 does NOT support A2DP audio streaming — it is strictly a UART bridge for serial communication. Useful for inter-device communication (e.g. connecting two ESP32s wirelessly, Raspberry Pi projects, AI integrations).

HC-05 Pin ESP32 GPIO (Default) Description
RX GPIO 17 (ESP TX) UART TX from ESP32
TX GPIO 16 (ESP RX) UART RX to ESP32
VCC 5V Power
GND GND Ground

GPIO pins and baud rate are configurable via idf.py menuconfigExternal Bluetooth Module Configuration.

Software Configuration

Quick Setup

  1. Set WiFi credentials in idf.py menuconfig:

    • Example ConfigurationWiFi SSID
    • Example ConfigurationWiFi Password
  2. Configure audio stream URL:

  3. Choose audio output mode:

    For I2S audio (all chips):

    • I2S Audio Output ConfigurationEnable I2S audio output = Yes
    • Configure GPIO pins if needed

    For USB audio (S2/S3/P4 only):

    • USB Audio Output ConfigurationEnable USB Audio Device mode = Yes
    • Set sample rate (default 44100 Hz matches most MP3 streams)
    • Set channel number (2 for stereo)
    • In USB Device UAC Configuration, set the USB UAC sample rate and channel count to match these settings
    • When using USB audio, disable I2S manually: I2S Audio Output ConfigurationEnable I2S audio output = No

Build and Flash

For I2S Audio (any ESP32):

# Set target (e.g., ESP32-C5, ESP32-S3, ESP32-C6)
idf.py set-target esp32c5

# Configure project
idf.py menuconfig

# Build and flash
idf.py -p PORT flash monitor

ESP32-C5 with PSRAM (N16R4 / N16R8 boards):

The Waveshare ESP32-C5-WIFI6-KIT comes in three variants:

  • N16 — 16MB Flash, no PSRAM
  • N16R4 — 16MB Flash, 4MB PSRAM
  • N16R8 — 16MB Flash, 8MB PSRAM

If your board has PSRAM (N16R4 or N16R8), enable it for better audio quality and full TLS security:

# Set target
idf.py set-target esp32c5

# Enable PSRAM in menuconfig:
idf.py menuconfig
#   Navigate to: Component config → ESP PSRAM
#   Check: [*] Enable PSRAM
#   Set "Mode" to your module's type (Quad or Octal — check your board docs)
#   Set "Speed" to 80 MHz (or as supported by your module)

# Clean build required after changing PSRAM setting
idf.py fullclean
idf.py -p PORT flash monitor

What PSRAM enables automatically (no additional menuconfig changes):

  • ✅ Full TLS certificate verification (HTTPS security restored)
  • ✅ AAC SBR decoder (HE-AAC at full 44100 Hz instead of 22050 Hz)
  • ✅ Larger audio buffers (32KB PCM ring buffer — smoother playback)
  • ✅ Larger I2S DMA buffers (30KB — reduced audio glitches)

Without PSRAM (N16 variant), the firmware automatically uses conservative settings: smaller buffers, no SBR, TLS cert verification skipped (HTTPS encryption still active).

Note: PSRAM cannot be auto-detected at build time — it must be enabled in menuconfig because the PSRAM controller is initialized during bootloader startup. Enabling PSRAM on a board that doesn't have it will cause a boot failure, which is why it's not enabled by default.

For USB Audio (ESP32-S2/S3/P4):

# Set target to ESP32-S3 (or ESP32-S2/P4)
idf.py set-target esp32s3

# Configure project and enable USB audio
idf.py menuconfig
# Navigate to: USB Audio Output Configuration
# Enable "Enable USB Audio Device mode"

# Build and flash
idf.py -p PORT flash monitor

Important for USB Audio:

  • After flashing, disconnect and reconnect the USB cable
  • The device will enumerate as a USB audio device
  • Check your OS audio settings - "ESP32 USB Audio" should appear
  • Use a separate UART port for serial monitoring if needed

(To exit the serial monitor, type Ctrl-].)

Interactive Menu

The device features an interactive menu system accessible via the ESP-IDF serial monitor (idf.py monitor). The menu auto-detects connected hardware and shows available options.

Navigation

Input Action
/ (arrow keys) Move selection up/down
1-9, 0 Jump directly to menu item
Enter Select highlighted item
b / Backspace / ESC Go back to previous menu

Menu Structure

=== BT Audio - Main Menu ===
--------------------------------------
  > [1] WiFi Streaming
    [2] SD Card Playback      [no card]    ← greyed out if no SD card
    [3] Bluetooth Output      [no module]  ← greyed out if no HC-05
    [4] Status
    [5] Settings
    [6] About
--------------------------------------
Navigate: arrows/numbers | Enter: select | b: back
  • WiFi Streaming: Start/stop HTTP audio streams, view status
  • SD Card Playback: Play MP3 files from SD card (auto-detected at boot)
  • Bluetooth Output: Connect to BT headphones via external HC-05 module
  • Status: View system status (WiFi, stream, audio, hardware)
  • Settings: Audio output configuration
  • About: Version and hardware info

Hardware Auto-Detection

At startup, the system probes for connected hardware:

  • SD Card: SPI bus probe on configured GPIO pins
  • BT Module: Enabled via Kconfig when HC-05 is wired to UART pins
  • Audio Output: I2S or USB Audio based on chip capabilities

Items that require missing hardware are shown but disabled (greyed out).

UART Commands

Legacy text commands are still supported alongside the interactive menu. Control the device via USB-C serial connection (use dedicated UART port when USB audio is active):

Command Description
START_STREAM Start HTTP audio streaming
STOP_STREAM Stop streaming and enter deep sleep (RESET to wake)
STATUS Show streaming status and data received
AUDIO_STATUS Show audio buffer level and playback state
RESTART_WIFI Restart WiFi with current session credentials
REBOOT Reboot the device
SLEEP Enter deep sleep (RESET to wake)
HELP Display available commands
MENU Redraw the interactive menu

Example Output

Console output when streaming is active:

I (589) bt_audio: ==============================================
I (599) bt_audio: ESP32-C5 WiFi Station + Audio Streaming
I (609) bt_audio: ==============================================
I (619) bt_audio: Target: ESP32-C5-WROOM-1 (Waveshare Dev Board)
I (629) bt_audio: Features: WiFi 6, BLE 5.0, I2S Audio Output
I (639) audio: Initializing I2S audio output...
I (649) audio: I2S Config: BCLK=6, WS=7, DOUT=8, Rate=44100 Hz
I (659) audio: I2S audio output initialized successfully
I (669) audio: Ring buffer size: 32768 bytes
I (679) bt_audio: Initializing WiFi...
I (769) bt_audio: wifi_init_sta finished.
I (889) bt_audio: connected to ap SSID:MyNetwork password:****
I (899) bt_audio: Connected Channel: 6 (2.4GHz band)
I (909) bt_audio: RSSI: -52 dBm
I (919) bt_audio: WiFi connected - streaming features enabled
I (929) bt_audio: Audio output: ENABLED (I2S to external DAC)
I (939) stream: Starting stream from: http://ice1.somafm.com/groovesalad-128-mp3
I (949) stream: HTTP_EVENT_ON_CONNECTED
I (959) stream: HTTP Status = 200, Content-Length = -1
I (969) audio: Audio playback started
I (1969) stream: Total: 16.00 KB | Rate: 16.00 KB/s

Supported Stream Formats

Current Support

  • MP3 Streams - Full MP3 decoding using minimp3 library ✅
  • Raw PCM - Direct output (best quality, requires PCM stream)

Future Enhancements

  • BLE LE Audio (LC3 codec) for wireless audio
  • AAC and FLAC support via ESP-ADF integration

Compatible ESP32 Boards

Board WiFi USB Audio I2S Audio Notes
ESP32-C5 WiFi 6 (2.4/5GHz) Primary target
ESP32-C6 WiFi 6 (2.4GHz) Similar to C5
ESP32-S3 WiFi 4 Implemented USB audio device mode available
ESP32-S2 WiFi 4 Implemented USB audio device mode available
ESP32-P4 N/A Implemented USB audio capable
ESP32 WiFi 4 Original ESP32

USB Audio Implementation

USB audio device mode is fully implemented for ESP32-S2/S3/P4 using the usb_device_uac component. The device appears as a USB audio class device to the host computer, requiring no external DAC or special drivers.

Troubleshooting

For comprehensive troubleshooting guides, see:

Windows-Specific Issues

CP210x Driver "Cannot start (Code 10)" on Windows 11

Uninstall the existing driver (with "Delete driver software" checked), download the latest from Silicon Labs, install as Administrator, and reboot. See TROUBLESHOOTING_SUMMARY.md for detailed steps.

Serial Monitor Disconnects When Using USB Audio

When USB audio is enabled, TinyUSB takes over the USB-OTG port for audio. You need a separate USB-to-UART bridge (or use the board's dedicated UART port) for serial monitoring. If you only have one USB port, use I2S audio mode instead.

"Checksum mismatch" Warning After Flashing

Run these commands in order to ensure the flash matches the built binary:

idf.py fullclean
idf.py build
idf.py flash

I2S Audio Issues

No Audio Output (I2S Mode)

  1. Check I2S wiring matches configured GPIO pins
  2. Verify DAC power supply (3.3V or 5V depending on DAC)
  3. Run AUDIO_STATUS command to check buffer level
  4. Check speaker/amplifier connection to DAC

PCM5102 DAC Specific Issues

The PCM5102 is a popular high-quality I2S DAC, but requires proper configuration:

Wiring Check:

PCM5102 Pin → ESP32 GPIO
BCK/SCK     → GPIO 4 (I2S_BCLK_GPIO - configurable in menuconfig)
LRCK/WS     → GPIO 5 (I2S_WS_GPIO - configurable in menuconfig)  
DIN/DATA    → GPIO 6 (I2S_DOUT_GPIO - configurable in menuconfig)
VIN         → 3.3V (or 5V if board supports it)
GND         → GND

Critical PCM5102 Configuration:

The PCM5102 has hardware configuration jumpers/solder pads that MUST be set correctly:

  1. FLT (Filter Select): Connect to GND for normal latency (recommended)
  2. DEMP (De-emphasis): Connect to GND for de-emphasis OFF (recommended for modern audio)
  3. XSMT (Soft Mute): Must connect to 3.3V to unmute the DAC (connecting to GND or leaving at factory default will mute all audio)
  4. FMT (Format Select): Connect to GND for I2S format (REQUIRED for this code)

Common PCM5102 Board Jumper Configurations:

Many PCM5102 boards (like Teyleten Robot) have jumper pads labeled H1L, H2L, H3L, H4L:

  • H1L: Typically controls FMT - should be set to I2S mode (usually left 2 pads)
  • H2L: Typically controls DEMP - usually middle+right for de-emphasis OFF
  • H3L: Typically controls XSMT - usually middle+right for normal operation
  • H4L: Typically controls FLT - usually middle+right for normal filter

Note: Jumper configurations vary by manufacturer. Check your board's documentation.

Recommended Settings for Most Use Cases:

  • FMT = GND (I2S format) - REQUIRED
  • DEMP = GND (de-emphasis off)
  • XSMT = 3.3V (soft mute disabled — required for audio output)
  • FLT = GND (normal latency filter)

Verification Steps:

  1. Power LED should be on (red LED on most PCM5102 boards)
  2. Verify 3.3V is present on VIN pin
  3. Use oscilloscope/logic analyzer to verify BCK, WS, and DATA signals are present
  4. Check that FMT pin is set to I2S mode (most critical setting)
  5. Verify headphones/speakers are properly connected to the 3.5mm jack
  6. Try different headphones to rule out connection issues

Advanced Debugging:

# Enable verbose I2S logging in menuconfig:
Component config → Driver configurations → I2S Configuration → Log level = Verbose

# Check I2S signals with logic analyzer:
- BCK should show ~1.4 MHz clock for 44.1kHz audio (44100 * 16 * 2)
- WS should show 44.1 kHz square wave
- DATA should show audio data synchronized with WS edges

USB Audio Issues

IMPORTANT: USB Audio mode makes the ESP32 act as a USB audio source/microphone device, NOT a speaker/playback device. The audio flows FROM the ESP32 TO your computer.

USB Audio Device Not Appearing

  1. Verify you're using ESP32-S2, S3, or P4 (other chips don't have USB OTG)
  2. Check that USB audio is enabled in menuconfig:
    • USB Audio Output ConfigurationEnable USB Audio Device mode = Yes
    • USB Device UAC Configuration → Set sample rate to 44100 Hz
    • USB Device UAC Configuration → Set UAC mic channel number to 2 (stereo)
  3. Verify I2S audio is DISABLED when using USB audio:
    • I2S Audio Output ConfigurationEnable I2S audio output = No
  4. After flashing, disconnect and reconnect USB cable
  5. Try a different USB cable or port
  6. Check dmesg/system logs for USB enumeration errors:
    # On Linux:
    dmesg | tail -20
    lsusb
    # On macOS:
    system_profiler SPUSBDataType
    # On Windows:
    Device Manager → Sound, video and game controllers

No Audio from USB Device

Remember: The ESP32 appears as an audio input/recording device, not an output device!

  1. Verify device appears in OS audio settings as a recording/input device

  2. Set up audio monitoring/playback:

    On Linux (PulseAudio/PipeWire):

    # List audio sources
    pactl list sources short
    
    # Enable loopback to hear the audio (replace X with source number)
    pactl load-module module-loopback source=X
    
    # Or use pavucontrol GUI to enable recording monitor
    pavucontrol

    On macOS:

    • Open Sound Settings → Input
    • Select "ESP UAC Device" as input
    • Use Audio MIDI Setup or third-party app like Audio Hijack to monitor/route audio

    On Windows:

    • Open Sound Settings → Recording devices
    • Right-click on "ESP UAC Device" → Properties
    • Go to "Listen" tab → Check "Listen to this device"
    • Select playback device (your speakers/headphones)
  3. Check stream is active (logs should show data transfer)

  4. Try adjusting input volume in OS audio settings

  5. Verify sample rate matches (44100 Hz for most MP3 streams)

  6. Use audio recording software (Audacity, etc.) to verify audio is being received

Cannot Monitor Serial While Using USB Audio

  • USB audio uses the USB OTG port
  • Use a dedicated UART port for serial monitoring (not the same USB port)
  • Many ESP32-S3 boards have TWO USB ports:
    • USB-JTAG/Serial port for programming and serial monitor
    • USB-OTG port for USB audio
  • Check your board's documentation to identify which port is which
  • Example: On ESP32-S3-DevKitC-1, the port labeled "USB" is USB-OTG, "UART" is USB-JTAG

USB Audio Configuration Mismatch

If USB audio device appears but no audio comes through:

  1. Verify menuconfig settings match:
    USB Audio Output Configuration:
    - USB Audio sample rate = 44100 Hz
    - USB Audio channel number = 2
    
    USB Device UAC Configuration:
    - UAC sample rate = 44100 Hz
    - UAC mic channel number = 2
    - UAC Speaker channel number = 0 (disable speaker function)
    
  2. Rebuild and reflash after any menuconfig changes
  3. Check ESP32 logs for USB enumeration success messages

General Issues

Stream Connection Failed

  1. Verify WiFi credentials
  2. Check stream URL is accessible
  3. Some streams require HTTPS - ensure SSL is configured

Audio Stuttering

  1. Increase ring buffer size in menuconfig
  2. Check WiFi signal strength (RSSI)
  3. Use 5GHz band if available for less interference

References

Running the example on ESP Chips without Wi-Fi

This example can run on ESP Chips without Wi-Fi using ESP-Hosted. See the Two-Chip Solution section in the upper level README.md for information.

For any technical queries, please open an issue on GitHub. We will get back to you soon.

About

A port of bt_audio (originally on FlipperZero) for all esp32 devices, but better. Written in C using ESP-IDF via VSCode.

Resources

Stars

Watchers

Forks

Contributors

Languages