Repository navigation
A2DP Sink
This can be used e.g. to build your own Bluetooth Speaker.
Here is the simplest example which just uses the proper default settings:
#include "AudioTools.h"
#include "BluetoothA2DPSink.h"
I2SStream i2s;
BluetoothA2DPSink a2dp_sink(i2s);
void setup() {
Serial.begin(115200);
a2dp_sink.start("MyMusic");
}
void loop() {
}This creates a new Bluetooth device with the name “MyMusic” and the output will be sent to the following default I2S pins which need to be connected to an external DAC:
- bck_io_num = 14
- ws_io_num = 15
- data_out_num = 22
Please note that these default pins have changed compared to the legacy API!
You can define your own pins easily before the start.
#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() {
}You can also use the Arduino ESP32 I2S API: You do not need to install any additional library for this.
#include "ESP_I2S.h"
#include "BluetoothA2DPSink.h"
const uint8_t I2S_SCK = 5; /* Audio data bit clock */
const uint8_t I2S_WS = 25; /* Audio data left and right clock */
const uint8_t I2S_SDOUT = 26; /* ESP32 audio data output (to speakers) */
I2SClass i2s;
BluetoothA2DPSink a2dp_sink(i2s);
void setup() {
Serial.begin(115200);
i2s.setPins(I2S_SCK, I2S_WS, I2S_SDOUT);
if (!i2s.begin(I2S_MODE_STD, 44100, I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO, I2S_STD_SLOT_BOTH)) {
Serial.println("Failed to initialize I2S!");
while (1); // do nothing
}
a2dp_sink.start("MyMusic");
}
void loop() {}Please note, that this API also depends on the installed version: The example above is for ESP32 >= 3.0.0!
You can also send the output directly to the internal DAC of the ESP32 by using the AnalogAudioStream from the AudioTools:
#include "AudioTools.h"
#include "BluetoothA2DPSink.h"
AnalogAudioStream out;
BluetoothA2DPSink a2dp_sink(out);
void setup() {
Serial.begin(115200);
a2dp_sink.start("MyMusic");
}
void loop() {
}The output goes now to the DAC pins GPIO25 (Channel 1) and GPIO26 (Channel 2).
You can be notified when a packet is received. The API is using PCM data normally formatted as 44.1kHz sampling rate, two-channel 16-bit sample data.
// In the setup function:
a2dp_sink.set_on_data_received(data_received_callback);
// Then somewhere in your sketch:
void data_received_callback() {
Serial.println("Data packet received");
}Or you can access the packet:
// In the setup function:
a2dp_sink.set_stream_reader(read_data_stream);
// Then somewhere in your sketch:
void read_data_stream(const uint8_t *data, uint32_t length)
{
int16_t *samples = (int16_t*) data;
uint32_t sample_count = length/2;
// Do something with the data packet
}In the a2dp_sink.set_stream_reader() method you can provide an optional parameter that defines if you want the output to I2S to be active or deactive - So you can use this method to e.g. to switch off I2S just by calling a2dp_sink.set_stream_reader(read_data_stream, false)
You can register callbacks to receive the AVRC metadata (e.g. title and artist) and notifications (e.g. playback status and position) of the connected source. See Metadata & Notifications.
You can 'control' the connected source (e.g. your phone) with play(), pause(), stop(), next(), previous(), fast_forward() and rewind(), and synchronize the volume. See AVRC: Controlling your Phone.
- Audio Output & DACs: wiring of popular DAC boards
- Sample Rate
- Volume Control
- Performance Optimizations
- Auto Reconnect
- Custom Codecs (AAC)
- Class documentation
Getting Started
A2DP Sink (Receiver)
- Overview & Examples
- Audio Output & DACs
- Sample Rate
- Volume Control
- AVRC: Controlling your Phone
- Metadata & Notifications
- Performance Optimizations
A2DP Source (Sender)
Common
Background
Help