# ESP Audio Render Example
- [中文版](./README_CN.md)
This example demonstrates how to use `esp_audio_render` to render PCM audio with or without processing, and how to mix multiple inputs into one output. It shows end‑to‑end flow: fetch compressed audio (e.g., MP3) over network, decode it using `esp_audio_codec` decoder, feed PCM into the render API, and finally output to `esp_codec_dev` (I2S codec).
## Hardware Requirements
- Recommended: [ESP32-S3-Korvo2](https://docs.espressif.com/projects/esp-adf/en/latest/design-guide/dev-boards/user-guide-esp32-s3-korvo-2.html) or [ESP32‑P4‑Function‑EV‑Board](https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32p4/esp32-p4-function-ev-board/user_guide.html)
- Other boards are supported; see [Other Board Support](#other-board-support)
## Software Requirements
- ESP‑IDF v5.4 or later
- `esp_audio_render` component
- ESP‑GMF framework (to provide format converters and optional processors)
- `esp_audio_codec` (for decoding MP3/others)
- `esp_codec_dev` (for actual audio output)
## Features Demonstrated
- **Single‑stream playback**: MP3/AAC (HTTP) → decode to PCM → render → codec
- **Multi‑stream mixing**: Decode multiple independent MP3/AAC sources and mix to one sink
- **Fixed output format configuration**: 16 kHz, 16‑bit, stereo output
- **Per‑stream processing**: ALC (Automatic Level Control) on each stream
- **Post‑mix processing**: ALC processing after mixing
- **Network audio streaming**: HTTP-based MP3/AAC file download and playback
## How it works
### Overall flow
```mermaid
flowchart LR
NET[HTTP MP3/AAC] --> DEC[esp_audio_codec Decoder]
DEC -- PCM --> STRM[esp_audio_render Stream]
STRM --> MIX[Mixer Thread]
MIX --> POST[Post Pipeline: ALC]
POST --> SINK[esp_codec_dev]
```
### Processor pipeline placement
```mermaid
flowchart LR
subgraph Per-Stream Path
IN[PCM from Decoder]
P1[Optional: CH/BIT/RATE Convert]
P2[Per-Stream ALC]
end
IN --> P1 --> P2 --> OUTQ[RingBuffer]
subgraph Mixer Thread
OUTQ --> M[ESP Audio Effects Mixer]
M --> PM[Post Pipeline: ALC]
end
PM --> WR[esp_codec_dev]
```
- **Per‑stream processing** runs inline in the `esp_audio_render_stream_write()` caller
- **When `stream_num > 1`**, the mixer thread consumes per‑stream ring buffer and runs a post‑mix pipeline
- **ALC processing** is applied both per-stream and post-mix for demonstrating audio processor capabilities
## Running the example
1. Configure Wi‑Fi and board audio codec initialization in the example's `app_main()` (or corresponding helper), then build and flash:
```bash
idf.py -p /dev/XXXXX flash monitor
```
2. The example automatically runs two test scenarios:
- **Single stream test**: Downloads and plays one MP3 file for 30 seconds
- **Multi-stream mixing test**: Downloads and mixes 8 different audio sources simultaneously
### Typical API calls
- `esp_audio_render_create()` - Creates renderer with mutex initialization
- `esp_audio_render_set_out_sample_info()` - Sets output format
- `esp_audio_render_stream_open()` - Opens stream with mutex protection
- `esp_audio_render_stream_add_procs()` - Adds processors to streams
- `esp_audio_render_stream_write()` - Writes PCM data
- `esp_audio_render_stream_close()` - Closes stream with mutex protection
- `esp_audio_render_destroy()` - Cleans up with mutex destruction
## Other Board Support
This example can leverage `gmf_app_utils` for quick board bring‑up. Check board compatibility in menuconfig under "GMF APP Configuration." For details, see the `gmf_app_utils` README.
Alternatively, you can use [esp-bsp](https://github.com/espressif/esp-bsp/tree/master) APIs:
- Use `bsp_audio_codec_microphone_init()` to replace `esp_gmf_app_get_record_handle()`
To create a project from this example, run:
idf.py create-project-from-example "espressif/esp_audio_render=0.7.1:audio_render"