Access class documentation and Wiki
mainDetailed technical documentation is available through the following resources:
- Class Documentation: Detailed API reference for classes and methods.
- Wiki: General information, guides, and change history.
repository·main·Indexed 25 days ago
https://github.com/pschatzmann/esp32-a2dpA Bluetooth A2DP library for Arduino and ESP-IDF that enables the ESP32 to function as either an audio receiver (Sink) or an audio sender (Source). It decodes SBC format into a PCM data stream (44.1kHz, 16-bit, two-channel) and supports AVRCP metadata and notifications. The library integrates with the arduino-audio-tools library for output API management and supports adding AAC or other codecs via decoders.
Detailed technical documentation is available through the following resources:
For Arduino users, you can install the library by downloading it as a ZIP file and using the 'Include Library -> ZIP Library' feature in the Arduino IDE. Alternatively, you can clone the repository directly into your Arduino libraries folder using Git.
Note: If you intend to use the provided examples, you must also install the arduino-audio-tools library.
cd ~/Documents/Arduino/libraries
git clone https://github.com/pschatzmann/ESP32-A2DP.git
git clone https://github.com/pschatzmann/arduino-audio-tools.gitUse the BluetoothA2DPSink class to build a Bluetooth speaker or receiver. The library decodes SBC format into a PCM data stream (44.1kHz, 16-bit, two-channel).
It is highly recommended to use the AudioTools library for a version-independent output API. You can also output to any class inheriting from Arduino Print or use the internal ESP32 I2S API.
#include "AudioTools.h"
#include "BluetoothA2DPSink.h"
I2SStream i2s;
BluetoothA2DPSink a2dp_sink(i2s);
void setup() {
Serial.begin(115200);
a2dp_sink.start("MyMusic");
}
void loop() {
}Use BluetoothA2DPSource to stream audio from the ESP32 to a Bluetooth speaker. You must provide a callback function that supplies the PCM data (44.1kHz, 16-bit, two-channel).
set_data_callback(callback): Provides data in bytes.set_data_callback_in_frames(callback): Provides data in frames.start(name): Connects to a specific Bluetooth device name. You can also pass a std::vector<const char*> of names to attempt connection to multiple devices in order.#include "BluetoothA2DPSource.h"
BluetoothA2DPSource a2dp_source;
int32_t get_sound_data(uint8_t *data, int32_t byteCount) {
// Generate or fetch PCM data here
return byteCount; // Return effective length in bytes
}
void setup() {
a2dp_source.set_data_callback(get_sound_data);
a2dp_source.start("MyMusic");
}
void loop() {}When using I2SStream from the AudioTools library, you can define custom pins before calling start().
Default Pins (New API):
bck_io_num = 14ws_io_num = 15data_out_num = 22Note: These default pins differ from the legacy API.
#include "AudioTools.h"
#include "BluetoothA2DPSink.h"
I2SStream i2s;
BluetoothA2DPSink a2dp_sink(i2s);
void setup() {
Serial.begin(115200);
auto cfg = i2s.defaultConfig();
cfg.pin_bck = 14;
cfg.pin_ws = 15;
cfg.pin_data = 22;
i2s.begin(cfg);
a2dp_sink.start("MyMusic");
}
void loop() {
}To bypass external I2S DACs and use the ESP32's built-in DAC, use AnalogAudioStream from the AudioTools library. The output will be sent to GPIO25 (Channel 1) and GPIO26 (Channel 2).
#include "AudioTools.h"
#include "BluetoothA2DPSink.h"
AnalogAudioStream out;
BluetoothA2DPSink a2dp_sink(out);
void setup() {
Serial.begin(115200);
a2dp_sink.start("MyMusic");
}
void loop() {
}add_decoder(). Each decoder creates its own stream endpoint and automatically decodes the codec into PCM.You can intercept the PCM audio stream using callbacks. The data is typically 44.1kHz, two-channel, 16-bit.
set_on_data_received(callback) to be notified when a packet arrives.set_stream_reader(callback) to access the raw byte buffer. You can pass false as a second argument to set_stream_reader to disable I2S output while reading data.// To be notified of arrival:
a2dp_sink.set_on_data_received(data_received_callback);
void data_received_callback() {
Serial.println("Data packet received");
}
// To access the actual PCM data:
a2dp_sink.set_stream_reader(read_data_stream);
void read_data_stream(const uint8_t *data, uint32_t length) {
int16_t *samples = (int16_t*) data;
uint32_t sample_count = length/2;
// Process samples...
}The library supports retrieving metadata (title, artist, etc.) and playback notifications via AVRCP.
set_avrc_metadata_callback. Use set_avrc_metadata_attribute_mask to filter which attributes are received (e.g., ESP_AVRC_MD_ATTR_TITLE).set_avrc_rn_playstatus_callback, set_avrc_rn_play_pos_callback, or set_avrc_rn_track_change_callback to monitor playback status, position, and track changes.void avrc_metadata_callback(uint8_t data1, const uint8_t *data2) {
Serial.printf("AVRC metadata rsp: attribute id 0x%x, %s\n", data1, data2);
}
a2dp_sink.set_avrc_metadata_callback(avrc_metadata_callback);
// Optional: filter attributes
a2dp_sink.set_avrc_metadata_attribute_mask(ESP_AVRC_MD_ATTR_TITLE | ESP_AVRC_MD_ATTR_PLAYING_TIME);
a2dp_sink.start("BT");