espp/audio

1.4.1

Latest
uploaded 4 hours ago
I2S audio playback and recording component in C++, with codec adapters (ES8388, ES7210), shared by the espp BSPs

Readme

# Audio Component

[![Badge](https://components.espressif.com/components/espp/audio/badge.svg)](https://components.espressif.com/components/espp/audio)

The `audio` component provides `espp::Audio`, I2S audio playback and recording
for one I2S port with 16-bit PCM: a TX channel for playback, an RX channel for
recording, or both, full duplex on the same clocks, in standard (Philips) mode.
An instance that only records can instead receive TDM (e.g. an ES7210 with four
microphones, `HardwareConfig::recording_tdm_slots`) or a PDM microphone;
`HardwareConfig::recording_slots` picks the slots the recording callback receives.

It owns the machinery the espp BSPs used to copy into each board:

- the I2S channels and their DMA rings, sized so the TX ring outlasts the
  playback task's bounded wait (see `codec/include/i2s_tx_feed.hpp`),
- the playback stream buffer and task, which always writes whole blocks so the
  TX ring never runs dry (an idle ring pops at the start of the next sound),
- the recording task, which drains the RX ring continuously and hands the
  samples to a callback while recording,
- volume, mute and microphone gain: in the codec, or volume and mute in
  software when there is no codec (e.g. a MAX98357A amplifier),
- sample rate changes (the I2S clocks and the codecs), and
- a complete unwind when `initialize()` fails, `deinitialize()` and the
  destructor.

## Codecs

Chip-specific setup goes through the small `espp::AudioCodec` interface
(`start()` / `stop()` / `set_sample_rate()` / `set_volume()` / `set_mute()` /
`set_gain()`). `espp::Audio` calls it only from initialization, teardown and
its setters, never per sample. This component provides adapters on the
drivers in the `codec` component:

- `espp::Es8311Codec`: the ES8311 mono codec, for playback and recording
  (the ESP32-P4 ES8311 boards: ESP32-P4-ETH, ESP32-P4 Function EV Board,
  ESP32-P4 Module Dev Kit, ESP32-P4-NANO, ESP32-P4-WIFI6-DEV-KIT,
  ESP32-P4-WIFI6-POE-ETH; ESP32-S3-BOX).
- `espp::Es8388Codec`: the ES8388 DAC, for playback (M5Stack Tab5).
- `espp::Es7210Codec`: the ES7210 microphone ADC, for recording (M5Stack Tab5,
  ESP32-S3-BOX, LilyGo T-Deck).

Each adapter takes the register read / write functions, e.g.
`espp::make_i2c_addressed_write(device)` for an `espp::I2c` device. A chip that
handles both directions is passed as both `HardwareConfig::output_codec` and
`HardwareConfig::input_codec`.

## Configuration

`espp::Audio::Config` has two parts:

- `AppConfig` (`config.app`): what an application chooses - the sample rate
  (and, for an instance that only records, `recording_sample_rate`), which
  directions run, the playback buffer and the playback / recording tasks.
- `HardwareConfig` (`config.hardware`): how the board is wired - the I2S port
  and pins, channel counts, the recording format and slots, the MCLK multiple
  and the codecs.

plus the initial volume / mute / microphone gain, `on_playback_block` and the
log level. The BSPs take only the `AppConfig`, as their `AudioConfig`
(`using AudioConfig = espp::Audio::AppConfig;`), and fill in the
`HardwareConfig` for their board.

## Board-specific parts

Amplifier enable pins, IO expanders and buttons stay in the BSP.
`Config::on_playback_block` is called once per playback block with whether it
carried audio, so a BSP can follow playback activity (the M5Stack Tab5 pauses
its battery charger with it). A board whose microphones are on a separate I2S
port uses two instances, one for playback and one for recording (the LilyGo
T-Deck, and the original M5Stack Cardputer's PDM microphone); such a BSP's
`microphone_audio()` returns the recording one.

## BSP audio API

The BSPs that use this component expose the same audio methods, which forward
to it:

| Method | |
|---|---|
| `initialize_audio()` / `initialize_audio(const AudioConfig &)` | set up playback and / or recording (`AudioConfig` is `espp::Audio::AppConfig`) |
| `default_audio_config()` | the board's defaults (rate, directions, task stacks / cores), to start an `AudioConfig` from |
| `deinitialize_audio()`, `is_audio_initialized()` | tear down / query |
| `audio()` | the `espp::Audio` instance |
| `enable_audio(bool)` | the speaker amplifier |
| `play_audio(std::span<const uint8_t>)` / `play_audio(const uint8_t *, size_t)` | queue audio, returns the bytes queued |
| `clear_audio()` | drop the queued audio |
| `volume()`, `mute()` / `is_muted()` | output level |
| `audio_sample_rate()`, `audio_buffer_size()` | rate (get / set), block size |
| `start_audio_recording(callback)` / `stop_audio_recording()` | recording |
| `microphone_volume()` | microphone gain |

Older names are kept as `[[deprecated]]` methods that forward to these.

## Example

The [example](./example) plays a tone through an I2S amplifier with no codec
(software volume and mute).

Links

Supports all targets

Maintainer

  • William Emfinger <waemfinger@gmail.com>
To add this component to your project, run:

idf.py add-dependency "espp/audio^1.4.1"

download archive

Stats

  • Archive size
    Archive size ~ 30.06 KB
  • Downloaded in total
    Downloaded in total 0 times
  • Downloaded this version
    This version: 0 times

Badge

espp/audio version: 1.4.1
|