Code Monkey home page Code Monkey logo

esp32-a2dp's Introduction

A Simple Arduino Bluetooth Music Receiver and Sender for the ESP32

The ESP32 is a microcontroller that provides an API for Bluetooth A2DP which can be used to receive sound data e.g. from your Mobile Phone and makes it available via a callback method. The output is a PCM data stream, decoded from SBC format. The documentation can be found here.

esp32

I2S is an electrical serial bus interface standard used for connecting digital audio devices together. It is used to communicate PCM audio data between integrated circuits in an electronic device.

So we can just feed the input from Bluetooth to the I2S output: An example for this from Espressif can be found on Github.

Unfortunately this example did not make me happy so I decided to convert it into a simple Arduino Library that is very easy to use from an Arduino Software IDE.

Supported Bluetooth Protocols

As the name of this libariy implies, it supports the A2DP Bluetooth protocol which only provides audio streaming!

It also supports Audio/Video Remote Control Profile (AVRCP) together with A2DP.

The Hands-Free Profile (HFP), Headset Profile (HSP) and stand alone AVRCP without A2DP are not supported!

I2S API / Dependencies

Espressif is retiring the legacy I2S API: So with Arduino 3.0.0 my old I2S integration will not be available any more. The legacy syntax is still working as long as you don't upgrade.

In order to support a unique output API which is version independent, it is recommended to install and use the AudioTools library. So the documentation and all the examples have been updated to use this new approach.

However you can also output to any other class which inherits from Arduino Print: e.g. the Arduino ESP32 I2SClass.

A2DP Sink (Music Receiver)

This can be used e.g. to build your own Bluetooth Speaker.

A Simple I2S Example (A2DS Sink) using default Pins

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() {
    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!

Defining Pins

You can define your own pins easily before the start.

#include "AudioTools.h"
#include "BluetoothA2DPSink.h"

I2SStream i2s;
BluetoothA2DPSink a2dp_sink(i2s);

void setup() {
    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() {
}

Output Using the ESP32 I2S API

You can also use the Arduino ESP32 I2S API: You do not need to install any additional library for this.

#include "I2S.h"
#include "BluetoothA2DPSink.h"

BluetoothA2DPSink a2dp_sink(I2S);

void setup() {
    I2S.setSckPin(14);
    I2S.setFsPin(15);
    I2S.setDataPin(22); 
    if (!I2S.begin(I2S_PHILIPS_MODE, 44100, 16)) {
      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!

Output to the Internal DAC

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() {
    a2dp_sink.start("MyMusic");
}

void loop() {
}

The output goes now to the DAC pins GPIO25 (Channel 1) and GPIO26 (Channel 2).

Accessing the Sink Data Stream with Callbacks

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)

Support for Metadata

You can register a method which will be called when the system receives any AVRC metadata (esp_avrc_md_attr_mask_t). Here is an example

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);
a2dp_sink.start("BT");

By default you should get the most important information, however you can adjust this by calling the set_avrc_metadata_attribute_mask method e.g if you just need the title and playing time you can call:

set_avrc_metadata_attribute_mask(ESP_AVRC_MD_ATTR_TITLE | ESP_AVRC_MD_ATTR_PLAYING_TIME);

before you start the A2DP sink. Note that data2 is actually a char* string, so even though ESP_AVRC_MD_ATTR_PLAYING_TIME is documented as the milliseconds of media duration you'll need to parse it before doing math on it. See the metadata example for more.

Support for Notifications

Similarly to the avrc_metadata_callback, ESP IDF v4+ supports selected esp_avrc_rn_param_t callbacks like set_avrc_rn_playstatus_callback, set_avrc_rn_play_pos_callback and set_avrc_rn_track_change_callback which can be used to obtain esp_avrc_playback_stat_t playback playback status,uint32_t play_pos playback position and uint8_t elm_id track change flag respectively. See the playing_status_callbacks example for more details.

Support for AVRC Commands

I have added the following AVRC commmands, that you can use to 'control' your A2DP Source:

  • play();
  • pause();
  • stop();
  • next();
  • previous();
  • fast_forward();
  • rewind();

A2DP Source (Music Sender)

This can be used to feed e.g. your Bluetooth Speaker with your audio data.

Sending Data from a A2DS Data Source with a Callback

We can also generate sound and send it e.g. to a Bluetooth Speaker.

The supported audio codec in ESP32 A2DP is SBC: The API is using PCM data normally formatted as 44.1kHz sampling rate, two-channel 16-bit sample data.

When you start the BluetoothA2DPSource, you need to pass the Bluetooth name that you want to connect to and a 'call back function' that generates the sound data:

#include "BluetoothA2DPSource.h"

BluetoothA2DPSource a2dp_source;

// callback 
int32_t get_sound_data(Frame *data, int32_t frameCount) {
    // generate your sound data 
    // return the effective length (in frames) of the generated sound  (which usually is identical with the requested len)
    // 1 frame is 2 channels * 2 bytes = 4 bytes
    return frameCount;
}

void setup() {
  a2dp_source.start("MyMusic", get_sound_data);  
}

void loop() {
}

In the examples you can find an implentation that generates sound with the help of the sin() function. You can also inticate multiple alternative Bluetooth names. The system just connects to the first one which is available:

void setup() {
  static std::vector<char*> bt_names = {"MyMusic","RadioPlayer","MusicPlayer"};
  a2dp_source.start(bt_names, get_sound_data); 
} 

Sending Data from a A2DS Data Source with Recorded Data

You can also provide the data directly as simple array of uint8_t:

#include "BluetoothA2DPSource.h"

extern const uint8_t StarWars10_raw[];
extern const unsigned int StarWars10_raw_len;

BluetoothA2DPSource a2dp_source;
SoundData *music = new OneChannelSoundData((int16_t*)StarWars30_raw, StarWars30_raw_len/2);

void setup() {
  a2dp_source.start("RadioPlayer");  
  a2dp_source.write_data(music);
}

void loop() {
}

The array can be prepared e.g. in the following way:

  • Open any sound file in Audacity.
    • Select Tracks -> Resample and select 44100
    • Export -> Export Audio -> Header Raw ; Signed 16 bit PCM
  • Convert to c file e.g. with "xxd -i file_example_WAV_1MG.raw file_example_WAV_1MG.c"
    • add the const qualifier to the generated array definition. E.g const unsigned char file_example_WAV_1MG_raw[] = {

You might want to compile with the Partition Scheme: Huge App!

In the example above we provide the data with one channel. This has the advantage that it uses much less space then a 2 channel recording, which you could use in the following way:

SoundData *data = new TwoChannelSoundData((Frame*)StarWars10_raw,StarWars10_raw_len/4);

In the constructor you can pass additional parameters:

TwoChannelSoundData(Frame *data, int32_t frameCount, bool loop=false);
OneChannelSoundData(int16_t *data, int32_t frameCount, bool loop=false, ChannelInfo channelInfo=Both);
OneChannel8BitSoundData(int8_t *data, int32_t frameCount, bool loop=false, ChannelInfo channelInfo=Both);

Logging

This library uses the ESP32 logger that you can activate in Arduino in - Tools - Core Debug Log.

Architecture / Dependencies

The current code is purely dependent on the ESP-IDF (which is also provided by the Arduino ESP32 core). There are no other dependencies and this includes the Arduino API!

Therefore we support:

This restriction limits however the provided examples.

Before you clone the project, please read the following information which can be found in the Wiki.

Digital Sound Processing

You can use this library stand alone, but it is part of my audio-tools project. So you can easily enhance this functionality with sound effects, use filters, use alternative audio sinks or audio sources, do FFT etc. Here is a simple example how you can analyse the audio data with FFT.

Documentation

Support

I spent a lot of time to provide a comprehensive and complete documentation. So please read the documentation first and check the issues and discussions before posting any new ones on Github.

Open issues only for bugs and if it is not a bug, use a discussion: Provide enough information about

  • the selected scenario/sketch
  • what exactly you are trying to do
  • your hardware
  • your software versions
    • ESP32 version from the Board Manager
    • version of the ESP32-A2DP library

to enable others to understand and reproduce your issue.

Finally above all don't send me any e-mails or post questions on my personal website!

Show and Tell

Get some inspiration from projects that were using this library and share your projects with the community.

Installation

For Arduino you can download the library as zip and call include Library -> zip library. Or you can git clone this project into the Arduino libraries folder e.g. with

cd  ~/Documents/Arduino/libraries
git clone https://github.com/pschatzmann/ESP32-A2DP.git
git clone https://github.com/pschatzmann/arduino-audio-tools.git

For the provided examples, you will need to install the audio-tools library as well.

For other frameworks see the Wiki

Change History

The Change History can be found in the Wiki

Sponsor Me

This software is totally free, but you can make me happy by rewarding me with a treat

esp32-a2dp's People

Contributors

adam-puleo avatar alexus2033 avatar anisjonischkeit avatar ant0nisk avatar arthurkoba avatar ashthespy avatar cfint avatar clarkbremer avatar daniilantonenko avatar degnarraer avatar designer2k2 avatar domints avatar dugujiujian1999 avatar jmsunseri avatar johnymielony avatar lemio avatar leventebajczi avatar martinroger avatar mishaux avatar mitchjs avatar paulhayes avatar pschatzmann avatar rbuehlma avatar ryandavis avatar storoj avatar tv4you2016 avatar zyphlar avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

esp32-a2dp's Issues

Platformio

Anyone have success when running under platformio?
I have tried and get this error:

rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:8896
load:0x40080400,len:5828
entry 0x400806ac

Works great under Arduino but personal prefrence would be to have in platformio.

Regards,

Aidan

Error compiling

Hey! I faced such a problem, when I tried to compile the project, I get an error control reaches end of non-void function, also Error compiling for board ESP32 Dev Module. Please help in this matter. Thank you.

Examples don't compile

Hey there...
It's pretty cool you put in the work to "port" the A2DP API from Espressif to Arduino. I wanted to quickly try and flash it on an ESP32 Wemos D1 mini using the Arduino IDE of course (Version 1.8.13 on Windows). Unfortunately both receiver examples (the only ones I tried) fail to compile. Perhaps I'm missing something. Are there any dependencies that I'm not aware of? I looked through your description, but didn't see any obvious dependencies mentioned.

Preparing simple c array for bt_music_sender_write

Hi, I'm trying to run the bt_music_sender_write, however I got an error:

"Sketch` uses 2230311 bytes (170%) of program storage space. Maximum is 1310720 bytes."

I tried to downsize the sample StarWars.h file, but I don't know how to do it right. Instead, I tried following your instructions on how to prepare my own simple c array, but I don't know how/where this step should be done:

  • Convert to c file e.g. with "xxd -i file_example_WAV_1MG.raw file_example_WAV_1MG.c"

How should I convert the raw file to c file? (sorry for the dumb question)
Also, how do you get the length just like what is written in the end of StarWars.h file?

Thank you very much!

Regards,
rmond18

How to use 'esp_a2d_media_ctrl' command?

Hi, Thank you very much for the work you made.

I use this library to use the BT speaker function, and I want to add some control functions.
I want to stop or restart music playing directly from the firmware.

I confirmed that esp_a2d_media_ctrl exists in esp_a2dp_api.h.
So, I was trying to use the function. When playing, enter the following command to stop
esp_a2d_media_ctrl(ESP_A2D_MEDIA_CTRL_SUSPEND)

In case of STOP or SUSPEND, execute the following to start playback.
esp_a2d_media_ctrl(ESP_A2D_MEDIA_CTRL_START)

Unfortunately, neither of these works.
Commands such as esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE) work.

Why can't command like play/pause music work? Is there any solution that you help me?

using external bluetooth

I am trying to use WiFi as well as A2DP library, but not able to use Bluetooth simultaneously. Therefore I used FreeRTOS but still both are not working there with I have to suspend one task and if not connected with Wifi or Bluetooth then resume the other. Therefore I wish to use external Bluetooth module with this a2dp library, so how do I use this? How can I configure external Bluetooth with this library.

ESP32 internal DAC playing music with noise

Hi Everyone!

I'm using a DEVKIT V1 (ESP32 WROOM 32) to test my project, but when i start a BT connection with my Android using the internal DAC of ESP32 i hear a lot of noise when music played (of course, if they is not playing too).

My question is, this "issue" is caused by internal DAC or my "hardware"?

I'm using exemple codes only, with a P2 jack removed of a motherboard and connected in GPIO25, GPIO26 and GND pins, my board are powered with a 5v~1A power supply on VIN/GND pins and nothing more, I'm not using any amplifier, only my headphone connected on P2...

A2dp source disconnects bluetooth connection after some seconds

I'm using Ultimate Ears WONDERBOOM with a2dp source. My plan is to prepare the WonderBoom (turn power on and press the button on top of it to pair) then wait for ESP32 to wake-up from deep sleep. The ESP32 wakes up when a timer expires and a2dp source finds the WonderBoom fine, connects and the music starts playing. But after some seconds well closer to 30 the bluetooth connection drops. I suppose it is somehow related to pairing or a2dp source finding the WonderBoom "too early".
If I wait for the ESP32 to wake up and then turn on the WonderBoom and press the pairing button the connection stays on without problems.

how to stream live audio with bt_music_sender or bt_music_sender_write

When i tested the original bt_music_sender_write with sloeber i had some problems.
i had to change:
extern const uint8_t StarWars10_raw[]; --> into extern const uint8_t StarWars30_raw[];
extern const unsigned int StarWars10_raw_len; --> into extern const unsigned int StarWars30_raw_len;

BluetoothA2DPSource a2dp_source;
//SoundData data = new TwoChannelSoundData((Channels)StarWars10_raw,StarWars10_raw_len/4);
SoundData data = new OneChannelSoundData((int16_t)StarWars30_raw, StarWars30_raw_len/2);

Now i get error --> code is to big

I had to downsize audio file to get it working.
Now i can send small audio file to BT-speaker with bt_music_sender_write.

the question is how to stream audio from input pin to my BT-speaker?

Adding record feature in A2DP sink

Is it possible to add a feature where a microSD card is connected and can record a the received data by the A2DP sink with a push button control?

I have found this which do the the feature that I said but I'm not sure how to integrate it with the A2DP sink code, but I'm currently trying. Do you have any tips?

Thank you very much!

Using bt_music_sender_write example but with input from SD card?

Hi,

I'm a beginner to ESP32 and such, and your lib is a great help.
I'm trying to make a MP3 player that read from SD card and output audio to bluetooth speaker.
How can I modify your bt_music_sender_write example to do this? Specifically, how should I read raw data from storage instead of predefined const variable (which makes sketch size big as you mentioned in README).
I'm using a M5Stack device, and trying to achieve this with this example: https://github.com/dsiberia9s/mp3-player-m5stack/blob/master/mp3-player-m5stack.ino
In the example above, they uses lib https://github.com/earlephilhower/ESP8266Audio, is it possible to integrate this lib with yours?

Best regards,
Cuong.

Watch Dog timer resets everytime

The example for bt_music_sender seems to work with my ESP32 TTGO T-Display module. However if I modify the example even slightly, the tones break up and eventually the ESP32 crashes with a watch dog timer issue. In this case, I wanted to generate different frequency tones for each ear.

#define FREQ1 120
#define FREQ2 500

BluetoothA2DPSource a2dp_source;

// The supported audio codec in ESP32 A2DP is SBC. SBC audio stream is encoded
// from PCM data normally formatted as 44.1kHz sampling rate, two-channel 16-bit sample data
int32_t get_data_channels(Channels *channels, int32_t channel_len) {
static double m_time = 0.0;
double m_amplitude = 8000.0; // -32,768 to 32,767
double m_deltaTime = 1.0 / 44100.0;
double m_phase = 0.0;
double double_Pi = PI * 2.0;
// fill the channel data
for (int sample = 0; sample < channel_len; ++sample) {
double angle = double_Pi * FREQ1 * m_time + m_phase;
double angle2 = double_Pi * FREQ2 * m_time + m_phase;
channels[sample].channel1 = m_amplitude * sin(angle);
channels[sample].channel2 = m_amplitude * sin(angle2);
m_time += m_deltaTime;
}

return channel_len;

}

void setup() {
a2dp_source.start("BT One", get_data_channels);
}`

This crashes everytime

ASSERT_PARAM(1 0), in lc_task.c at line 2984
Guru Meditation Error: Core 0 panic'ed (Interrupt wdt timeout on CPU0)
Core 0 register dump:
PC : 0x400877b2 PS : 0x00060234 A0 : 0x8002dbb4 A1 : 0x3ffcaa40
A2 : 0x00000001 A3 : 0x00000000 A4 : 0x00000000 A5 : 0x60008054
A6 : 0x3ffbdd44 A7 : 0x60008050 A8 : 0x800877ad A9 : 0x3ffcaa20
A10 : 0x00000004 A11 : 0x00000000 A12 : 0x6000804c A13 : 0xffffffff
A14 : 0x00000000 A15 : 0xfffffffb SAR : 0x00000004 EXCCAUSE: 0x00000005
EXCVADDR: 0x00000000 LBEG : 0x400876e5 LEND : 0x400876ec LCOUNT : 0x00000000

Backtrace: 0x400877b2:0x3ffcaa40 0x4002dbb1:0x3ffcaa60 0x40024f79:0x3ffcaac0 0x4001a637:0x3ffcaae0 0x40019d11:0x3ffcab10 0x40055b4d:0x3ffcab30 0x40163917:0x3ffcab50 0x40163e6d:0x3ffcab70 0x4008dbbd:0x3ffcaba0

Any ideas on how to solve this?

Implementing metadata on Arduino IDE

Hello, recently I've discovered this awesome library which helped me make my project a lot easier. As adding an OLED display and an ADC took only a few lines of code. The thing is that I don't know how to implement the "send_metadata_cmd" as well as CASE "ESP_AVRC_CT_METADATA_RSP_EVT" so that I could store these attributes to some variables on Arduino IDE.

Adding this code: esp_avrc_ct_send_metadata_cmd(0, ESP_AVRC_MD_ATTR_TITLE); to void loop() compiled successfully, but I just can't confirm it works as I mentioned above.

If someone already tried this, I would really appreciate the help, as I just can't seem to find answers.

Best regards,
Greg

BT Sink to ESP32 internal DAC just hear static?

I have been trying to sink to internal DAC using "bt_music_receiver_to_dac.ino" I was able to connect my phone to ESP32 via BT, but I only hear a buzzing sound. I am using a simple LM386 for AMP, and I testes the AMP works when I use a simple dacWrite() function. (I am only using G26 at the moment)

BTW, isn't DAC output for ESP32 are G25/G26 (not G26/G27)?

I also added the code from "bt_music_receiver_with_metadata.ino", a2dp_sink.set_avrc_metadata_callback(avrc_metadata_callback) and the avrc_metadata_callback() callback routine to verify indeed my phone is sending data after connection.

here is the debug output (sorry, it is a bit long) all the way to endless "audio_data_callback(): audio_data_callback" and I can't seem to find out what's wrong.

12:19:43.695 -> [D][BluetoothA2DPSink.cpp:151] start(): start
12:19:43.742 -> [I][BluetoothA2DPSink.cpp:156] start(): Device name will be set to 'MyMusic'
12:19:43.742 -> [D][BluetoothA2DPSink.cpp:717] init_nvs(): init_nvs
12:19:43.742 -> [D][BluetoothA2DPSink.cpp:731] get_last_connection(): get_last_connection
12:19:43.742 -> [D][BluetoothA2DPSink.cpp:217] init_bluetooth(): init_bluetooth
12:19:43.833 -> [I][BluetoothA2DPSink.cpp:222] init_bluetooth(): controller initialized
12:19:44.157 -> [I][BluetoothA2DPSink.cpp:231] init_bluetooth(): bluedroid initialized
12:19:44.250 -> [I][BluetoothA2DPSink.cpp:239] init_bluetooth(): bluedroid enabled
12:19:44.250 -> [D][BluetoothA2DPSink.cpp:321] app_task_start_up(): app_task_start_up
12:19:44.250 -> [D][BluetoothA2DPSink.cpp:859] app_task_handler_2(): app_task_handler_2
12:19:44.250 -> [D][BluetoothA2DPSink.cpp:832] app_task_handler(): app_task_handler
12:19:44.250 -> [D][BluetoothA2DPSink.cpp:294] app_task_handler(): app_task_handler
12:19:44.250 -> [D][BluetoothA2DPSink.cpp:246] app_work_dispatch(): app_work_dispatch event 0x0, param len 0
12:19:44.298 -> [D][BluetoothA2DPSink.cpp:278] app_send_msg(): app_send_msg
12:19:44.298 -> [D][BluetoothA2DPSink.cpp:301] app_task_handler(): app_task_handler, sig 0x1, 0x0
12:19:44.298 -> [W][BluetoothA2DPSink.cpp:304] app_task_handler(): app_task_handler, APP_SIG_WORK_DISPATCH sig: 1
12:19:44.298 -> [D][BluetoothA2DPSink.cpp:269] app_work_dispatched(): app_work_dispatched
12:19:44.298 -> [D][BluetoothA2DPSink.cpp:173] operator()(): av_hdl_stack_evt_2
12:19:44.298 -> [D][BluetoothA2DPSink.cpp:577] av_hdl_stack_evt(): av_hdl_stack_evt evt 0
12:19:44.298 -> [D][BluetoothA2DPSink.cpp:582] av_hdl_stack_evt(): av_hdl_stack_evt av_hdl_stack_evt BT_APP_EVT_STACK_UP
12:19:44.345 -> [D][BluetoothA2DPSink.cpp:591] av_hdl_stack_evt(): AVRCP controller initialized!
12:19:44.345 -> [D][BluetoothA2DPSink.cpp:610] av_hdl_stack_evt(): connect_to_last_device
12:19:44.345 -> [D][BluetoothA2DPSink.cpp:785] connect_to_last_device(): connect_to_last_device
12:19:44.345 -> [D][BluetoothA2DPSink.cpp:615] av_hdl_stack_evt(): esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE)
12:19:44.345 -> [D][BluetoothA2DPSink.cpp:869] app_a2d_callback_2(): app_a2d_callback_2
12:19:44.345 -> [I][BluetoothA2DPSink.cpp:190] start(): Output will go to DAC pins
12:19:44.392 -> [D][BluetoothA2DPSink.cpp:844] app_a2d_callback(): app_a2d_callback
12:19:44.392 -> [D][BluetoothA2DPSink.cpp:632] app_a2d_callback(): app_a2d_callback
12:19:44.392 -> [D][BluetoothA2DPSink.cpp:644] app_a2d_callback(): app_a2d_callback ESP_A2D_CONNECTION_STATE_EVT
12:19:44.392 -> [D][BluetoothA2DPSink.cpp:246] app_work_dispatch(): app_work_dispatch event 0x0, param len 16
12:19:44.392 -> [D][BluetoothA2DPSink.cpp:278] app_send_msg(): app_send_msg
12:19:44.392 -> [D][BluetoothA2DPSink.cpp:301] app_task_handler(): app_task_handler, sig 0x1, 0x0
12:19:44.392 -> [W][BluetoothA2DPSink.cpp:304] app_task_handler(): app_task_handler, APP_SIG_WORK_DISPATCH sig: 1
12:19:44.439 -> [D][BluetoothA2DPSink.cpp:269] app_work_dispatched(): app_work_dispatched
12:19:44.439 -> [D][BluetoothA2DPSink.cpp:636] operator()(): av_hdl_a2d_evt_2
12:19:44.439 -> [D][BluetoothA2DPSink.cpp:397] av_hdl_a2d_evt(): av_hdl_a2d_evt evt 0
12:19:44.439 -> [D][BluetoothA2DPSink.cpp:401] av_hdl_a2d_evt(): av_hdl_a2d_evt ESP_A2D_CONNECTION_STATE_EVT
12:19:44.439 -> [I][BluetoothA2DPSink.cpp:406] av_hdl_a2d_evt(): A2DP connection state: Connecting, [xx:xx:xx:xx:xx:xx]
12:19:44.439 -> [I][BluetoothA2DPSink.cpp:437] av_hdl_a2d_evt(): ESP_A2D_CONNECTION_STATE_CONNECTING
12:19:45.370 -> Not connected
12:19:47.234 -> [D][BluetoothA2DPSink.cpp:869] app_a2d_callback_2(): app_a2d_callback_2
12:19:47.234 -> [D][BluetoothA2DPSink.cpp:844] app_a2d_callback(): app_a2d_callback
12:19:47.234 -> [D][BluetoothA2DPSink.cpp:632] app_a2d_callback(): app_a2d_callback
12:19:47.281 -> [D][BluetoothA2DPSink.cpp:653] app_a2d_callback(): app_a2d_callback ESP_A2D_AUDIO_CFG_EVT
12:19:47.281 -> [D][BluetoothA2DPSink.cpp:246] app_work_dispatch(): app_work_dispatch event 0x2, param len 16
12:19:47.281 -> [D][BluetoothA2DPSink.cpp:278] app_send_msg(): app_send_msg
12:19:47.281 -> [D][BluetoothA2DPSink.cpp:301] app_task_handler(): app_task_handler, sig 0x1, 0x2
12:19:47.281 -> [W][BluetoothA2DPSink.cpp:304] app_task_handler(): app_task_handler, APP_SIG_WORK_DISPATCH sig: 1
12:19:47.281 -> [D][BluetoothA2DPSink.cpp:269] app_work_dispatched(): app_work_dispatched
12:19:47.330 -> [D][BluetoothA2DPSink.cpp:636] operator()(): av_hdl_a2d_evt_2
12:19:47.330 -> [D][BluetoothA2DPSink.cpp:397] av_hdl_a2d_evt(): av_hdl_a2d_evt evt 2
12:19:47.330 -> [D][BluetoothA2DPSink.cpp:461] av_hdl_a2d_evt(): av_hdl_a2d_evt ESP_A2D_AUDIO_CFG_EVT
12:19:47.330 -> [I][BluetoothA2DPSink.cpp:465] av_hdl_a2d_evt(): a2dp audio_cfg_cb , codec type 0
12:19:47.330 -> [I][BluetoothA2DPSink.cpp:477] av_hdl_a2d_evt(): a2dp audio_cfg_cb , sample_rate 44100
12:19:47.330 -> [I][BluetoothA2DPSink.cpp:488] av_hdl_a2d_evt(): configure audio player 21-15-2-35
12:19:47.330 -> 
12:19:47.330 -> [I][BluetoothA2DPSink.cpp:489] av_hdl_a2d_evt(): audio player configured, samplerate=44100
12:19:47.612 -> [D][BluetoothA2DPSink.cpp:869] app_a2d_callback_2(): app_a2d_callback_2
12:19:47.612 -> [D][BluetoothA2DPSink.cpp:844] app_a2d_callback(): app_a2d_callback
12:19:47.612 -> [D][BluetoothA2DPSink.cpp:632] app_a2d_callback(): app_a2d_callback
12:19:47.612 -> [D][BluetoothA2DPSink.cpp:644] app_a2d_callback(): app_a2d_callback ESP_A2D_CONNECTION_STATE_EVT
12:19:47.612 -> [D][BluetoothA2DPSink.cpp:246] app_work_dispatch(): app_work_dispatch event 0x0, param len 16
12:19:47.612 -> [D][BluetoothA2DPSink.cpp:278] app_send_msg(): app_send_msg
12:19:47.612 -> [D][BluetoothA2DPSink.cpp:301] app_task_handler(): app_task_handler, sig 0x1, 0x0
12:19:47.659 -> [W][BluetoothA2DPSink.cpp:304] app_task_handler(): app_task_handler, APP_SIG_WORK_DISPATCH sig: 1
12:19:47.659 -> [D][BluetoothA2DPSink.cpp:269] app_work_dispatched(): app_work_dispatched
12:19:47.659 -> [D][BluetoothA2DPSink.cpp:636] operator()(): av_hdl_a2d_evt_2
12:19:47.659 -> [D][BluetoothA2DPSink.cpp:397] av_hdl_a2d_evt(): av_hdl_a2d_evt evt 0
12:19:47.659 -> [D][BluetoothA2DPSink.cpp:401] av_hdl_a2d_evt(): av_hdl_a2d_evt ESP_A2D_CONNECTION_STATE_EVT
12:19:47.659 -> [I][BluetoothA2DPSink.cpp:406] av_hdl_a2d_evt(): A2DP connection state: Connected, [xx:xx:xx:xx:xx:xx]
12:19:47.659 -> [I][BluetoothA2DPSink.cpp:428] av_hdl_a2d_evt(): ESP_A2D_CONNECTION_STATE_CONNECTED
12:19:47.706 -> [D][BluetoothA2DPSink.cpp:756] set_last_connection(): set_last_connection
12:19:47.753 -> [D][BluetoothA2DPSink.cpp:874] app_rc_ct_callback_2(): app_rc_ct_callback_2
12:19:47.753 -> [D][BluetoothA2DPSink.cpp:850] app_rc_ct_callback(): app_rc_ct_callback
12:19:47.753 -> [D][BluetoothA2DPSink.cpp:355] app_rc_ct_callback(): app_rc_ct_callback
12:19:47.753 -> [D][BluetoothA2DPSink.cpp:372] app_rc_ct_callback(): app_rc_ct_callback ESP_AVRC_CT_CONNECTION_STATE_EVT
12:19:47.753 -> [D][BluetoothA2DPSink.cpp:246] app_work_dispatch(): app_work_dispatch event 0x0, param len 12
12:19:47.753 -> [D][BluetoothA2DPSink.cpp:278] app_send_msg(): app_send_msg
12:19:47.753 -> [D][BluetoothA2DPSink.cpp:301] app_task_handler(): app_task_handler, sig 0x1, 0x0
12:19:47.801 -> [W][BluetoothA2DPSink.cpp:304] app_task_handler(): app_task_handler, APP_SIG_WORK_DISPATCH sig: 1
12:19:47.801 -> [D][BluetoothA2DPSink.cpp:874] app_rc_ct_callback_2(): app_rc_ct_callback_2
12:19:47.801 -> [D][BluetoothA2DPSink.cpp:269] app_work_dispatched(): app_work_dispatched
12:19:47.801 -> [D][BluetoothA2DPSink.cpp:359] operator()(): av_hdl_avrc_evt_2
12:19:47.801 -> [D][BluetoothA2DPSink.cpp:532] av_hdl_avrc_evt(): av_hdl_avrc_evt evt 0
12:19:47.801 -> [I][BluetoothA2DPSink.cpp:538] av_hdl_avrc_evt(): AVRC conn_state evt: state 1, [xx:xx:xx:xx:xx:xx]
12:19:47.801 -> [D][BluetoothA2DPSink.cpp:506] av_new_track(): av_new_track
12:19:47.849 -> [D][BluetoothA2DPSink.cpp:850] app_rc_ct_callback(): app_rc_ct_callback
12:19:47.849 -> [D][BluetoothA2DPSink.cpp:355] app_rc_ct_callback(): app_rc_ct_callback
12:19:47.849 -> [D][BluetoothA2DPSink.cpp:384] app_rc_ct_callback(): app_rc_ct_callback ESP_AVRC_CT_REMOTE_FEATURES_EVT
12:19:47.849 -> [D][BluetoothA2DPSink.cpp:246] app_work_dispatch(): app_work_dispatch event 0x5, param len 12
12:19:47.849 -> [D][BluetoothA2DPSink.cpp:278] app_send_msg(): app_send_msg
12:19:47.849 -> [D][BluetoothA2DPSink.cpp:301] app_task_handler(): app_task_handler, sig 0x1, 0x5
12:19:47.849 -> [W][BluetoothA2DPSink.cpp:304] app_task_handler(): app_task_handler, APP_SIG_WORK_DISPATCH sig: 1
12:19:47.896 -> [D][BluetoothA2DPSink.cpp:269] app_work_dispatched(): app_work_dispatched
12:19:47.896 -> [D][BluetoothA2DPSink.cpp:359] operator()(): av_hdl_avrc_evt_2
12:19:47.896 -> [D][BluetoothA2DPSink.cpp:532] av_hdl_avrc_evt(): av_hdl_avrc_evt evt 5
12:19:47.896 -> [I][BluetoothA2DPSink.cpp:565] av_hdl_avrc_evt(): AVRC remote features 24b
12:19:48.175 -> [D][BluetoothA2DPSink.cpp:874] app_rc_ct_callback_2(): app_rc_ct_callback_2
12:19:48.175 -> [D][BluetoothA2DPSink.cpp:850] app_rc_ct_callback(): app_rc_ct_callback
12:19:48.175 -> [D][BluetoothA2DPSink.cpp:355] app_rc_ct_callback(): app_rc_ct_callback
12:19:48.222 -> [D][BluetoothA2DPSink.cpp:367] app_rc_ct_callback(): app_rc_ct_callback ESP_AVRC_CT_METADATA_RSP_EVT
12:19:48.222 -> [D][BluetoothA2DPSink.cpp:344] app_alloc_meta_buffer(): app_alloc_meta_buffer
12:19:48.222 -> [D][BluetoothA2DPSink.cpp:246] app_work_dispatch(): app_work_dispatch event 0x2, param len 12
12:19:48.222 -> [D][BluetoothA2DPSink.cpp:278] app_send_msg(): app_send_msg
12:19:48.222 -> [D][BluetoothA2DPSink.cpp:301] app_task_handler(): app_task_handler, sig 0x1, 0x2
12:19:48.222 -> [W][BluetoothA2DPSink.cpp:304] app_task_handler(): app_task_handler, APP_SIG_WORK_DISPATCH sig: 1
12:19:48.269 -> [D][BluetoothA2DPSink.cpp:269] app_work_dispatched(): app_work_dispatched
12:19:48.269 -> [D][BluetoothA2DPSink.cpp:359] operator()(): av_hdl_avrc_evt_2
12:19:48.269 -> [D][BluetoothA2DPSink.cpp:532] av_hdl_avrc_evt(): av_hdl_avrc_evt evt 2
12:19:48.269 -> [I][BluetoothA2DPSink.cpp:550] av_hdl_avrc_evt(): AVRC metadata rsp: attribute id 0x1, SongName
12:19:48.269 -> [D][BluetoothA2DPSink.cpp:874] app_rc_ct_callback_2(): app_rc_ct_callback_2
12:19:48.269 -> [D][BluetoothA2DPSink.cpp:850] app_rc_ct_callback(): app_rc_ct_callback
12:19:48.269 -> [D][BluetoothA2DPSink.cpp:355] app_rc_ct_callback(): app_rc_ct_callback
12:19:48.316 -> [D][BluetoothA2DPSink.cpp:367] app_rc_ct_callback(): app_rc_ct_callback ESP_AVRC_CT_METADATA_RSP_EVT
12:19:48.316 -> [D][BluetoothA2DPSink.cpp:344] app_alloc_meta_buffer(): app_alloc_meta_buffer
12:19:48.316 -> [D][BluetoothA2DPSink.cpp:246] app_work_dispatch(): app_work_dispatch event 0x2, param len 12
12:19:48.316 -> [D][BluetoothA2DPSink.cpp:278] app_send_msg(): app_send_msg
12:19:48.316 -> [D][BluetoothA2DPSink.cpp:301] app_task_handler(): app_task_handler, sig 0x1, 0x2
12:19:48.316 -> [W][BluetoothA2DPSink.cpp:304] app_task_handler(): app_task_handler, APP_SIG_WORK_DISPATCH sig: 1
12:19:48.316 -> [D][BluetoothA2DPSink.cpp:269] app_work_dispatched(): app_work_dispatched
12:19:48.365 -> [D][BluetoothA2DPSink.cpp:359] operator()(): av_hdl_avrc_evt_2
12:19:48.365 -> [D][BluetoothA2DPSink.cpp:532] av_hdl_avrc_evt(): av_hdl_avrc_evt evt 2
12:19:48.365 -> [I][BluetoothA2DPSink.cpp:550] av_hdl_avrc_evt(): AVRC metadata rsp: attribute id 0x2, Artist
12:19:48.365 -> [D][BluetoothA2DPSink.cpp:874] app_rc_ct_callback_2(): app_rc_ct_callback_2
12:19:48.365 -> [D][BluetoothA2DPSink.cpp:850] app_rc_ct_callback(): app_rc_ct_callback
12:19:48.365 -> [D][BluetoothA2DPSink.cpp:355] app_rc_ct_callback(): app_rc_ct_callback
12:19:48.365 -> [D][BluetoothA2DPSink.cpp:367] app_rc_ct_callback(): app_rc_ct_callback ESP_AVRC_CT_METADATA_RSP_EVT
12:19:48.411 -> [D][BluetoothA2DPSink.cpp:344] app_alloc_meta_buffer(): app_alloc_meta_buffer
12:19:48.411 -> [D][BluetoothA2DPSink.cpp:246] app_work_dispatch(): app_work_dispatch event 0x2, param len 12
12:19:48.411 -> [D][BluetoothA2DPSink.cpp:278] app_send_msg(): app_send_msg
12:19:48.411 -> [D][BluetoothA2DPSink.cpp:301] app_task_handler(): app_task_handler, sig 0x1, 0x2
12:19:48.411 -> [W][BluetoothA2DPSink.cpp:304] app_task_handler(): app_task_handler, APP_SIG_WORK_DISPATCH sig: 1
12:19:48.411 -> [D][BluetoothA2DPSink.cpp:269] app_work_dispatched(): app_work_dispatched
12:19:48.458 -> [D][BluetoothA2DPSink.cpp:359] operator()(): av_hdl_avrc_evt_2
12:19:48.458 -> [D][BluetoothA2DPSink.cpp:532] av_hdl_avrc_evt(): av_hdl_avrc_evt evt 2
12:19:48.458 -> [I][BluetoothA2DPSink.cpp:550] av_hdl_avrc_evt(): AVRC metadata rsp: attribute id 0x4, Imagine
12:19:48.458 -> [D][BluetoothA2DPSink.cpp:874] app_rc_ct_callback_2(): app_rc_ct_callback_2
12:19:48.458 -> [D][BluetoothA2DPSink.cpp:850] app_rc_ct_callback(): app_rc_ct_callback
12:19:48.458 -> [D][BluetoothA2DPSink.cpp:355] app_rc_ct_callback(): app_rc_ct_callback
12:19:48.458 -> [D][BluetoothA2DPSink.cpp:367] app_rc_ct_callback(): app_rc_ct_callback ESP_AVRC_CT_METADATA_RSP_EVT
12:19:48.505 -> [D][BluetoothA2DPSink.cpp:344] app_alloc_meta_buffer(): app_alloc_meta_buffer
12:19:48.505 -> [D][BluetoothA2DPSink.cpp:246] app_work_dispatch(): app_work_dispatch event 0x2, param len 12
12:19:48.505 -> [D][BluetoothA2DPSink.cpp:278] app_send_msg(): app_send_msg
12:19:48.505 -> [D][BluetoothA2DPSink.cpp:301] app_task_handler(): app_task_handler, sig 0x1, 0x2
12:19:48.505 -> [W][BluetoothA2DPSink.cpp:304] app_task_handler(): app_task_handler, APP_SIG_WORK_DISPATCH sig: 1
12:19:48.505 -> [D][BluetoothA2DPSink.cpp:269] app_work_dispatched(): app_work_dispatched
12:19:48.505 -> [D][BluetoothA2DPSink.cpp:359] operator()(): av_hdl_avrc_evt_2
12:19:48.553 -> [D][BluetoothA2DPSink.cpp:532] av_hdl_avrc_evt(): av_hdl_avrc_evt evt 2
12:19:48.553 -> [I][BluetoothA2DPSink.cpp:550] av_hdl_avrc_evt(): AVRC metadata rsp: attribute id 0x20, 
12:19:53.678 -> [D][BluetoothA2DPSink.cpp:869] app_a2d_callback_2(): app_a2d_callback_2
12:19:53.678 -> [D][BluetoothA2DPSink.cpp:844] app_a2d_callback(): app_a2d_callback
12:19:53.678 -> [D][BluetoothA2DPSink.cpp:632] app_a2d_callback(): app_a2d_callback
12:19:53.678 -> [D][BluetoothA2DPSink.cpp:648] app_a2d_callback(): app_a2d_callback ESP_A2D_AUDIO_STATE_EVT
12:19:53.678 -> [D][BluetoothA2DPSink.cpp:246] app_work_dispatch(): app_work_dispatch event 0x1, param len 16
12:19:53.726 -> [D][BluetoothA2DPSink.cpp:278] app_send_msg(): app_send_msg
12:19:53.726 -> [D][BluetoothA2DPSink.cpp:301] app_task_handler(): app_task_handler, sig 0x1, 0x1
12:19:53.726 -> [W][BluetoothA2DPSink.cpp:304] app_task_handler(): app_task_handler, APP_SIG_WORK_DISPATCH sig: 1
12:19:53.726 -> [D][BluetoothA2DPSink.cpp:269] app_work_dispatched(): app_work_dispatched
12:19:53.726 -> [D][BluetoothA2DPSink.cpp:636] operator()(): av_hdl_a2d_evt_2
12:19:53.726 -> [D][BluetoothA2DPSink.cpp:397] av_hdl_a2d_evt(): av_hdl_a2d_evt evt 1
12:19:53.726 -> [D][BluetoothA2DPSink.cpp:444] av_hdl_a2d_evt(): av_hdl_a2d_evt ESP_A2D_AUDIO_STATE_EVT
12:19:53.772 -> [D][BluetoothA2DPSink.cpp:664] audio_data_callback(): audio_data_callback
12:19:53.772 -> [I][BluetoothA2DPSink.cpp:446] av_hdl_a2d_evt(): A2DP audio state: Started
12:19:53.772 -> [D][BluetoothA2DPSink.cpp:664] audio_data_callback(): audio_data_callback
12:19:53.772 -> [D][BluetoothA2DPSink.cpp:664] audio_data_callback(): audio_data_callback
12:19:53.772 -> [D][BluetoothA2DPSink.cpp:664] audio_data_callback(): audio_data_callback
12:19:53.772 -> [D][BluetoothA2DPSink.cpp:664] audio_data_callback(): audio_data_callback

WiFi coexistence

Have you been able to get A2DP to coexist with WiFi? The ESP32 docs say it is possible, but I haven't succeeded so far. I haven't tried a simple test case yet - I have been trying to shoe-horn A2DP into an existing, fairly complex application, but just knowing if someone has succeeded would be useful.

HFP Support

Hello.
Great work, it works very smoothly with a PCM5102 board.
Would it be possible for the library to be compatible with the HFP protocol to hear phone calls from a smartphone?
Thanks !

Humming sound with PAM8403/PAM8610

Hello,

I tried A2DP using PAM8403 and PAM8610 (Stereo Mini Class-D 3W+3W PAM8403 Audio Amplifier) to use esp32 Bluetooth to connect with mobile and play songs. But there is much humming sound in it. I tried adding capacitors onto PAM8403, but nothing work.

I am using an example code for now as now below,

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  static const i2s_config_t i2s_config = {
    .mode = (i2s_mode_t) (I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN),
    .sample_rate = 44100, // corrected by info from bluetooth
    .bits_per_sample = (i2s_bits_per_sample_t) 16, /* the DAC module will only take the 8bits from MSB */
    .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
    .communication_format = I2S_COMM_FORMAT_I2S_MSB,
    .intr_alloc_flags = 0, // default interrupt priority
    .dma_buf_count = 8,
    .dma_buf_len = 64,
    .use_apll = false
  };

  a2dp_sink.set_i2s_config(i2s_config);
  a2dp_sink.start("MyMusic");

}

Well, I am not sure if I can use a Class D Amplifier for the same purpose.

If any advice or suggestion can help, I will be grateful to them.

TIA

Having trouble with defining pins

Hello there,
I was fiddling arround trying to use diffrent pins, because i am using some for i2c.
Now i couldn't get it to work properly, (changing the pins to the ones i defined)
I did it this way, i believe this is wrong but i don't know a nother way myself.

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "BluetoothA2DPSink.h"
#define SCREEN_WIDTH 128 // OLED display width in pixels
#define SCREEN_HEIGHT 32 // OLED display height in pixels
#define OLED_RESET     4 // Reset pin # 
#define SCREEN_ADDRESS 0x3C // 0x3D for 128x64, 0x3C for 128x32 (some x64 models also use 0x3C)

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
**BluetoothA2DPSink set_pin_config;**
BluetoothA2DPSink a2dp_sink;

bool is_active = true;

void avrc_metadata_callback(uint8_t data1, const uint8_t *data2) {
  Serial.printf("0x%x, %s\n", data1, data2);
}

   char message[]="arikarikarikarikarik";
   int x, minX;
   
  void setup(){
  Serial.begin(9600);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setTextWrap(false);
  x = display.width();
  minX = -12 * strlen(message);  // 12 = 6 pixels/character * text size 2
  **a2dp_sink.set_pin_config(bck_io_num = 4, .ws_io_num = 15, .data_out_num = 2)**
  Serial.begin(115200);
  a2dp_sink.set_avrc_metadata_callback(avrc_metadata_callback);
  a2dp_sink.start("audio");  
  }

  void loop(){
       
   display.clearDisplay();
   display.setCursor(0,0);
   display.setTextSize(1);
   display.print("scrolltext"); // display song author
   display.setTextSize(2);
   display.setCursor(-x,10); // (x,10) -> right to left (-x,10) left to right
   display.print(message);
   display.display();
   x=x-1; // scroll speed, to increase change x=x-2; to x=x-1 // to increase change x=x-1; to x=x-2 for example
   if(x < minX) x= display.width();
}

This is what i put on the beginning as you can see in the code shown above.
BluetoothA2DPSink set_pin_config;
This in the setup
a2dp_sink.set_pin_config(bck_io_num = 4, .ws_io_num = 15, .data_out_num = 2)

Sorry for asking this, as this is probably a dumb question.. i got it to work by changing pins in the library, but i would like to do it in the code itself.
Hope you have a wonderfull day, and thanks for the awesome library!!

  • Arik

Errors in bt_music_sender_write example

There seem to be a couple of errors in the bt_music_sender_write:

You define StarWars10_raw and StarWars10_raw_len in your sketch, but your example data is called StarWars30!

Please check your example data sample again. On my test system (M5Stack M5Paper and M5 Atom Echo) your original example data plays twice as fast as it should.

After following your instructions to create my own stereo 44100 16-bit PCM sample data (from a random star wars ringtone sample) in audacity and converting with xxd, my sample plays at the right speed as TwoChannelSoundData.

How to send passthrough command and get callback infomation

thank you pschatzmann so much for your library which is so simple and nice !
now I can connect my android phone to ESP32+PCM5102 and enjoy the music , the great thing is that AVRCP info can show in the serial monitor such as title,artist,palying time ,etc. and my phone controled ESP32 very well.
my question is:

  1. how can I get the callback infomation such as the current playing time that lead me to calculate the progress of the music.this means the callback infomations may invole the stauts such as palying,pause,stop,new track,etc.
  2. how can I get the callback infomations of my phone's bluetooth address or name?
  3. I want to control the ESP32 from the serial monitor or arduino button,such as paly,stop,next,prev ,etc
    I know that might use the passthrough function. I love arduino very much but my poor C++ skill doesn't support me to write out very comlex sketch.
    can everybody help me?THX a lot!

Metadata + more

Hello, first of all thank you so much for your library which is so simple and nice !

I'd like to know if it is possible to retrieve the metadata (ie. title and artist) from the bluetooth ?

Also, at least on my iPhone I usually get a "headphones" symbol in the status bar when I connect a bluetooth speaker. Here I got nothing, would it be possible to have it ? I guess I would have to tell the phone what type of bluetooth device is connected.

Finally, but maybe that's too much to ask, with some bluetooth devices, my iPhone is capable of showing the battery level. Since my project is battery powered and I already know the level, would it be possible to send that as well ?

Best regards,
Mael

Output to VS1053.

Is it possible to output the stream using the VS1053?
I have a web radio with ESP32/VS1053 and it would be very interesting to add BT mode for playing from a smartphone.

Removing SIN() from Sample Bluetooth Source program

Using an ESP32.

Following a suggestion I saw in the WDT reset issue, I modified the Bluetooth Source program only enough to create the sound array in Setup() and then copy the array every time get_data_channels() is called.

The original program does compile and work. The modified does not. I'm hoping another set of eyes will spot what I can't see.

Here's the original program that does work:

#include "BluetoothA2DPSource.h"
#include <math.h> 

const double frequency1=440.0;

BluetoothA2DPSource a2dp_source;

// The supported audio codec in ESP32 A2DP is SBC. SBC audio stream is encoded
// from PCM data normally formatted as 44.1kHz sampling rate, two-channel 16-bit sample data
int32_t get_data_channels(Channels *channels, int32_t channel_len) {
    static double m_time = 0.0;
    double m_amplitude = 10000.0;  // -32,768 to 32,767
    double m_deltaTime = 1.0 / 44100.0;
    double m_phase = 0.0;
    double double_Pi = PI * 2.0;
    // fill the channel data
    for (int sample = 0; sample < channel_len; ++sample) {
        double angle1 = double_Pi * frequency1 * m_time + m_phase;
        channels[sample].channel1 = m_amplitude * sin(angle1);
        channels[sample].channel2 = channels[sample].channel1;
        m_time += m_deltaTime;
    }

    return channel_len;
}


void setup() {
  a2dp_source.start("PLT_M70", get_data_channels);  
}

void loop() {
}

Here is my attempt to implement the suggested solution. It gives me a strange sound:

#include "BluetoothA2DPSource.h"
#include <math.h> 

const double frequency=440.0;
Channels Sounds[128];

BluetoothA2DPSource a2dp_source;

// The supported audio codec in ESP32 A2DP is SBC. SBC audio stream is encoded
// from PCM data normally formatted as 44.1kHz sampling rate, two-channel 16-bit sample data
int32_t get_data_channels(Channels *channels, int32_t channel_len)
    {
    for (int i = 0 ; i < channel_len ; i++)
        {
        channels[i].channel1=Sounds[i].channel1;
        channels[i].channel2=Sounds[i].channel2;
        }
        
    return channel_len;
    }

void MakeTones()
    {
    static double m_time = 0.0;
    double m_amplitude   = 10000.0;  // -32,768 to 32,767
    double m_deltaTime   = 1.0 / 44100.0;
    double m_phase       = 0.0;
    double double_Pi     = PI * 2.0;
    
    // fill the channel data
    for (int sample = 0; sample < 128; ++sample)
        {
        double angle1  = double_Pi * frequency * m_time + m_phase;
        Sounds[sample].channel1 = m_amplitude * sin(angle1);
        Sounds[sample].channel2 = Sounds[sample].channel1;
        
        m_time += m_deltaTime;
        }
    }

void setup()
    {
    MakeTones();
    a2dp_source.start("PLT_M70", get_data_channels);  
    }

void loop()
    {
    }


Thanks.

Chuck Bland

How to calibrate volume levels?

I'm using this library on an ESP32 and streaming audio from my phone. My question is how would you adjust the volume so that it has a better range of values available? The lowest volume level on my phone is pretty loud right now, is this adjustable in the code?
Thanks for your work on this library @pschatzmann !

bluetooth devices with address starting 00 will not auto reconnect

the function in BluetoothA2DPSink.cpp

bool BluetoothA2DPSink::has_last_connection() {
return last_connection[0] != 0;
}

will return false if the address begins with 00 so will not attempt to reconnect.
I worked around it by checking each byte and returning on the first non zero, but you may want to use a different solution

Using my own .h data

Hello! I am trying to use my own .h in the bt_music_sender_write to send the audio, but I'm not sure how to convert to h. I tried the steps below, but it only plays noise. I tried another app that converts directly to .raw, and then a bin2h converter. It converts the audio and it actually looks it can work, because it has the same format, but then it only sounds noise. Could you help me to get my mp3 files into h? :)

Pin code feature.

Is there any kind of BT paring pin code facility built in to this library?

If I connect my phone, for example then turn off bt on it the esp32 will start advertising its availability... and anyone can connect.

Noise when playing using an Android phone.

I am testing in several ways.
There was a (very strong) noise problem during testing.

I connected to ESP32-BT (with PCM5102 module) through my phone (Galaxy S10). When I play music, it sounds great.
However, during music playback, if I make a phone call or receive a call, the music that was playing is paused, and (very strong) noise occurs on the speaker connected to PCM5102 module. When you end the call, the music plays again and the noise disappears.

Interestingly, it only happens on Android phones. Other phones (iPhone SE) do not cause such a problem.

Can I solve this problem?

Trying to stop the Bluetooth Broadcast

Hello there!

I am trying to call "a2dp_sink.app_task_shut_down()" on the vanilla example and it seems like its an protected call.

The goal here is to make it stop at some point and NOT broadcast any BT sink so my I2S receiver would be available to do another things. Should I try to unprotect it?

I always feel like its a bummer and an inconvenience to bother people like you with this issues, but I will be very glad to whom (or the author) could help me on this (I will name my cat after you).

How can I reconnect after end()

my test skedue as bellow:
#include "BluetoothA2DPSink.h"

BluetoothA2DPSink a2dp_sink;

void setup() {
//a2dp_sink.start("MyMusic");
Serial.begin(115200);
}

void loop() {
if(Serial.available()){
command = Serial.readStringUntil('#');
if(command.equals("on")){
a2dp_sink.start("MyMusic",true);
Serial.println("STARTING...");
}
if(command.equals("off")){
a2dp_sink.end(false);
Serial.println("STOPING...");
}
}
}

I could start the A2DP by start() function,and stopped by end() as well,but when I restarted A2DP by start(),my mobil could not connect "MyMusic" anymore unless a hard reset.
How can I restart A2DP link in loop() without any hard reset?
thanks a lot for any help!

Bluetooth A2DP Source - Can I use I2S as input?

Hello,

thank you so much for this excellent library. I do have a question. Can I use I2S incoming data as source and then send it via Bluetooth to a speaker? I was looking at the "bt_music_sender.ino" example and I guess I have to modify the get_data_channels() function. Any hint or code would be very appreciated.

Best regards
Mike

Enable/Disable pairing mode

Is it possible to have an option to enable and disable the pairing for new devices? I would like to implement a button which allows a device to pair but do not allow any other devices to pair during normal operation.

Looking at the API, this does not seem to be possible currently but I'm not sure whether it is a technical limitation or simply missing some API functions?

In any case, thanks for this great library. It's indeed really simple to use.

Support for Metadata only work in Arduino Framework 1.0.4

Hi,

Let me know if someone is facing in this problem.
I'm using the sketch bt_music_receiver_metadata.ino as example.
The support for Metadata (and also AVRC Commands) only works in Arduino Framework 1.0.4. Above this version as 1.0.5 and 1.0.6 has this issue.
Debbuging look like callback 'app_rc_ct_callback()' is not working for newest version of Arduino Framework.
Also I tried in Visual Studio Platformio with Arduino Framework and only work in the version 3.0.0(framework 1.0.4), above this version same issue.

Follow the debbuging for 1.0.4:
[D][BluetoothA2DPSink.cpp:122] start(): start
[I][BluetoothA2DPSink.cpp:127] start(): Device name will be set to 'ESP32_SPEAKER'
[D][BluetoothA2DPSink.cpp:174] init_bluetooth(): init_bluetooth
[I][BluetoothA2DPSink.cpp:179] init_bluetooth(): controller initialized
[I][BluetoothA2DPSink.cpp:188] init_bluetooth(): bluedroid initialized
[I][BluetoothA2DPSink.cpp:196] init_bluetooth(): bluedroid enabled
[D][BluetoothA2DPSink.cpp:274] app_task_start_up(): app_task_start_up
[D][BluetoothA2DPSink.cpp:681] app_task_handler_2(): app_task_handler_2
[D][BluetoothA2DPSink.cpp:250] app_task_handler(): app_task_handler
[D][BluetoothA2DPSink.cpp:203] app_work_dispatch(): app_work_dispatch event 0x0, param len 0
[D][BluetoothA2DPSink.cpp:235] app_send_msg(): app_send_msg
[D][BluetoothA2DPSink.cpp:254] app_task_handler(): app_task_handler, sig 0x1, 0x0
[W][BluetoothA2DPSink.cpp:257] app_task_handler(): app_task_handler, APP_SIG_WORK_DISPATCH sig: 1
[D][BluetoothA2DPSink.cpp:226] app_work_dispatched(): app_work_dispatched
[D][BluetoothA2DPSink.cpp:141] operator()(): operator()
[D][BluetoothA2DPSink.cpp:508] av_hdl_stack_evt(): av_hdl_stack_evt av_hdl_stack_evt BT_APP_EVT_STACK_UP
[D][BluetoothA2DPSink.cpp:693] app_a2d_callback_2(): app_a2d_callback_2
[D][BluetoothA2DPSink.cpp:545] app_a2d_callback(): app_a2d_callback
[D][BluetoothA2DPSink.cpp:548] app_a2d_callback(): app_a2d_callback ESP_A2D_CONNECTION_STATE_EVT
[D][BluetoothA2DPSink.cpp:203] app_work_dispatch(): app_work_dispatch event 0x0, param len 16
[D][BluetoothA2DPSink.cpp:235] app_send_msg(): app_send_msg
[D][BluetoothA2DPSink.cpp:254] app_task_handler(): app_task_handler, sig 0x1, 0x0
[W][BluetoothA2DPSink.cpp:257] app_task_handler(): app_task_handler, APP_SIG_WORK_DISPATCH sig: 1
[D][BluetoothA2DPSink.cpp:226] app_work_dispatched(): app_work_dispatched
[D][BluetoothA2DPSink.cpp:693] app_a2d_callback_2(): app_a2d_callback_2
[D][BluetoothA2DPSink.cpp:539] operator()(): operator()
[D][BluetoothA2DPSink.cpp:348] av_hdl_a2d_evt(): av_hdl_a2d_evt evt 0
[D][BluetoothA2DPSink.cpp:352] av_hdl_a2d_evt(): av_hdl_a2d_evt ESP_A2D_CONNECTION_STATE_EVT
[I][BluetoothA2DPSink.cpp:356] av_hdl_a2d_evt(): A2DP connection state: Connecting, [00:57:c1:43:a8:5b]
[I][BluetoothA2DPSink.cpp:380] av_hdl_a2d_evt(): ESP_A2D_CONNECTION_STATE_CONNECTING
[D][BluetoothA2DPSink.cpp:545] app_a2d_callback(): app_a2d_callback
[D][BluetoothA2DPSink.cpp:557] app_a2d_callback(): app_a2d_callback ESP_A2D_AUDIO_CFG_EVT
[D][BluetoothA2DPSink.cpp:203] app_work_dispatch(): app_work_dispatch event 0x2, param len 16
[D][BluetoothA2DPSink.cpp:235] app_send_msg(): app_send_msg
[D][BluetoothA2DPSink.cpp:254] app_task_handler(): app_task_handler, sig 0x1, 0x2
[W][BluetoothA2DPSink.cpp:257] app_task_handler(): app_task_handler, APP_SIG_WORK_DISPATCH sig: 1
[D][BluetoothA2DPSink.cpp:226] app_work_dispatched(): app_work_dispatched
[D][BluetoothA2DPSink.cpp:539] operator()(): operator()
[D][BluetoothA2DPSink.cpp:348] av_hdl_a2d_evt(): av_hdl_a2d_evt evt 2
[D][BluetoothA2DPSink.cpp:403] av_hdl_a2d_evt(): av_hdl_a2d_evt ESP_A2D_AUDIO_CFG_EVT
[I][BluetoothA2DPSink.cpp:407] av_hdl_a2d_evt(): a2dp audio_cfg_cb , codec type 0
[I][BluetoothA2DPSink.cpp:426] av_hdl_a2d_evt(): configure audio player 21-15-2-35

[I][BluetoothA2DPSink.cpp:427] av_hdl_a2d_evt(): audio player configured, samplerate=44100
[D][BluetoothA2DPSink.cpp:693] app_a2d_callback_2(): app_a2d_callback_2
[D][BluetoothA2DPSink.cpp:545] app_a2d_callback(): app_a2d_callback
[D][BluetoothA2DPSink.cpp:548] app_a2d_callback(): app_a2d_callback ESP_A2D_CONNECTION_STATE_EVT
[D][BluetoothA2DPSink.cpp:203] app_work_dispatch(): app_work_dispatch event 0x0, param len 16
[D][BluetoothA2DPSink.cpp:235] app_send_msg(): app_send_msg
[D][BluetoothA2DPSink.cpp:254] app_task_handler(): app_task_handler, sig 0x1, 0x0
[W][BluetoothA2DPSink.cpp:257] app_task_handler(): app_task_handler, APP_SIG_WORK_DISPATCH sig: 1
[D][BluetoothA2DPSink.cpp:226] app_work_dispatched(): app_work_dispatched
[D][BluetoothA2DPSink.cpp:539] operator()(): operator()
[D][BluetoothA2DPSink.cpp:348] av_hdl_a2d_evt(): av_hdl_a2d_evt evt 0
[D][BluetoothA2DPSink.cpp:352] av_hdl_a2d_evt(): av_hdl_a2d_evt ESP_A2D_CONNECTION_STATE_EVT
[I][BluetoothA2DPSink.cpp:356] av_hdl_a2d_evt(): A2DP connection state: Connected, [00:57:c1:43:a8:5b]
[I][BluetoothA2DPSink.cpp:374] av_hdl_a2d_evt(): ESP_A2D_CONNECTION_STATE_CONNECTED
[D][BluetoothA2DPSink.cpp:699] app_rc_ct_callback_2(): app_rc_ct_callback_2
[D][BluetoothA2DPSink.cpp:307] app_rc_ct_callback(): app_rc_ct_callback (<-here callback is working)
[D][BluetoothA2DPSink.cpp:324] app_rc_ct_callback(): app_rc_ct_callback ESP_AVRC_CT_CONNECTION_STATE_EVT
[D][BluetoothA2DPSink.cpp:203] app_work_dispatch(): app_work_dispatch event 0x0, param len 12
[D][BluetoothA2DPSink.cpp:235] app_send_msg(): app_send_msg
[D][BluetoothA2DPSink.cpp:254] app_task_handler(): app_task_handler, sig 0x1, 0x0
[W][BluetoothA2DPSink.cpp:257] app_task_handler(): app_task_handler, APP_SIG_WORK_DISPATCH sig: 1
[D][BluetoothA2DPSink.cpp:226] app_work_dispatched(): app_work_dispatched
[D][BluetoothA2DPSink.cpp:311] operator()(): operator()
[D][BluetoothA2DPSink.cpp:461] av_hdl_avrc_evt(): av_hdl_avrc_evt evt 0
[I][BluetoothA2DPSink.cpp:467] av_hdl_avrc_evt(): AVRC conn_state evt: state 1, [00:57:c1:43:a8:5b]
[D][BluetoothA2DPSink.cpp:699] app_rc_ct_callback_2(): app_rc_ct_callback_2
[D][BluetoothA2DPSink.cpp:439] av_new_track(): av_new_track
[D][BluetoothA2DPSink.cpp:307] app_rc_ct_callback(): app_rc_ct_callback
[D][BluetoothA2DPSink.cpp:336] app_rc_ct_callback(): app_rc_ct_callback ESP_AVRC_CT_REMOTE_FEATURES_EVT
[D][BluetoothA2DPSink.cpp:203] app_work_dispatch(): app_work_dispatch event 0x5, param len 12
[D][BluetoothA2DPSink.cpp:235] app_send_msg(): app_send_msg
[D][BluetoothA2DPSink.cpp:254] app_task_handler(): app_task_handler, sig 0x1, 0x5
[W][BluetoothA2DPSink.cpp:257] app_task_handler(): app_task_handler, APP_SIG_WORK_DISPATCH sig: 1
[D][BluetoothA2DPSink.cpp:226] app_work_dispatched(): app_work_dispatched
[D][BluetoothA2DPSink.cpp:311] operator()(): operator()
[D][BluetoothA2DPSink.cpp:461] av_hdl_avrc_evt(): av_hdl_avrc_evt evt 5
[I][BluetoothA2DPSink.cpp:494] av_hdl_avrc_evt(): AVRC remote features 49
[D][BluetoothA2DPSink.cpp:699] app_rc_ct_callback_2(): app_rc_ct_callback_2
[D][BluetoothA2DPSink.cpp:307] app_rc_ct_callback(): app_rc_ct_callback
[D][BluetoothA2DPSink.cpp:319] app_rc_ct_callback(): app_rc_ct_callback ESP_AVRC_CT_METADATA_RSP_EVT
[D][BluetoothA2DPSink.cpp:296] app_alloc_meta_buffer(): app_alloc_meta_buffer
[D][BluetoothA2DPSink.cpp:203] app_work_dispatch(): app_work_dispatch event 0x2, param len 12
[D][BluetoothA2DPSink.cpp:235] app_send_msg(): app_send_msg
[D][BluetoothA2DPSink.cpp:254] app_task_handler(): app_task_handler, sig 0x1, 0x2
[W][BluetoothA2DPSink.cpp:257] app_task_handler(): app_task_handler, APP_SIG_WORK_DISPATCH sig: 1
[D][BluetoothA2DPSink.cpp:226] app_work_dispatched(): app_work_dispatched
[D][BluetoothA2DPSink.cpp:311] operator()(): operator()
[D][BluetoothA2DPSink.cpp:699] app_rc_ct_callback_2(): app_rc_ct_callback_2
[D][BluetoothA2DPSink.cpp:461] av_hdl_avrc_evt(): av_hdl_avrc_evt evt 2
[I][BluetoothA2DPSink.cpp:479] av_hdl_avrc_evt(): AVRC metadata rsp: attribute id 0x1, LOVE A RIDDLE
[D][BluetoothA2DPSink.cpp:307] app_rc_ct_callback(): app_rc_ct_callback
[D][BluetoothA2DPSink.cpp:319] app_rc_ct_callback(): app_rc_ct_callback ESP_AVRC_CT_METADATA_RSP_EVT
[D][BluetoothA2DPSink.cpp:296] app_alloc_meta_buffer(): app_alloc_meta_buffer
[D][BluetoothA2DPSink.cpp:203] app_work_dispatch(): app_work_dispatch event 0x2, param len 12
[D][BluetoothA2DPSink.cpp:235] app_send_msg(): app_send_msg
[D][BluetoothA2DPSink.cpp:254] app_task_handler(): app_task_handler, sig 0x1, 0x2
[D][BluetoothA2DPSink.cpp:699] app_rc_ct_callback_2(): app_rc_ct_callback_2
[W][BluetoothA2DPSink.cpp:257] app_task_handler(): app_task_handler, APP_SIG_WORK_DISPATCH sig: 1
[D][BluetoothA2DPSink.cpp:307] app_rc_ct_callback(): app_rc_ct_callback
[D][BluetoothA2DPSink.cpp:226] app_work_dispatched(): app_work_dispatched
[D][BluetoothA2DPSink.cpp:311] operator()(): operator()
[D][BluetoothA2DPSink.cpp:319] app_rc_ct_callback(): app_rc_ct_callback ESP_AVRC_CT_METADATA_RSP_EVT
[D][BluetoothA2DPSink.cpp:461] av_hdl_avrc_evt(): av_hdl_avrc_evt evt 2
[I][BluetoothA2DPSink.cpp:479] av_hdl_avrc_evt(): AVRC metadata rsp: attribute id 0x2, KOTOKO
[D][BluetoothA2DPSink.cpp:571] audio_data_callback(): audio_data_callback
[D][BluetoothA2DPSink.cpp:296] app_alloc_meta_buffer(): app_alloc_meta_buffer
[D][BluetoothA2DPSink.cpp:203] app_work_dispatch(): app_work_dispatch event 0x2, param len 12
[D][BluetoothA2DPSink.cpp:235] app_send_msg(): app_send_msg
[D][BluetoothA2DPSink.cpp:571] audio_data_callback(): audio_data_callback
[D][BluetoothA2DPSink.cpp:254] app_task_handler(): app_task_handler, sig 0x1, 0x2
[W][BluetoothA2DPSink.cpp:257] app_task_handler(): app_task_handler, APP_SIG_WORK_DISPATCH sig: 1
[D][BluetoothA2DPSink.cpp:226] app_work_dispatched(): app_work_dispatched
[D][BluetoothA2DPSink.cpp:311] operator()(): operator()
[D][BluetoothA2DPSink.cpp:571] audio_data_callback(): audio_data_callback
[D][BluetoothA2DPSink.cpp:461] av_hdl_avrc_evt(): av_hdl_avrc_evt evt 2
[I][BluetoothA2DPSink.cpp:479] av_hdl_avrc_evt(): AVRC metadata rsp: attribute id 0x4, KOTOKO Anime song’s complete album “The Fable”
[D][BluetoothA2DPSink.cpp:571] audio_data_callback(): audio_data_callback
[D][BluetoothA2DPSink.cpp:699] app_rc_ct_callback_2(): app_rc_ct_callback_2
[D][BluetoothA2DPSink.cpp:307] app_rc_ct_callback(): app_rc_ct_callback
[D][BluetoothA2DPSink.cpp:571] audio_data_callback(): audio_data_callback
[D][BluetoothA2DPSink.cpp:319] app_rc_ct_callback(): app_rc_ct_callback ESP_AVRC_CT_METADATA_RSP_EVT
[D][BluetoothA2DPSink.cpp:296] app_alloc_meta_buffer(): app_alloc_meta_buffer
[D][BluetoothA2DPSink.cpp:571] audio_data_callback(): audio_data_callback
[D][BluetoothA2DPSink.cpp:203] app_work_dispatch(): app_work_dispatch event 0x2, param len 12
[D][BluetoothA2DPSink.cpp:235] app_send_msg(): app_send_msg
[D][BluetoothA2DPSink.cpp:254] app_task_handler(): app_task_handler, sig 0x1, 0x2
[D][BluetoothA2DPSink.cpp:571] audio_data_callback(): audio_data_callback
[W][BluetoothA2DPSink.cpp:257] app_task_handler(): app_task_handler, APP_SIG_WORK_DISPATCH sig: 1
[D][BluetoothA2DPSink.cpp:226] app_work_dispatched(): app_work_dispatched
[D][BluetoothA2DPSink.cpp:311] operator()(): operator()
[D][BluetoothA2DPSink.cpp:571] audio_data_callback(): audio_data_callback
[D][BluetoothA2DPSink.cpp:461] av_hdl_avrc_evt(): av_hdl_avrc_evt evt 2
[I][BluetoothA2DPSink.cpp:479] av_hdl_avrc_evt(): AVRC metadata rsp: attribute id 0x20, J-Pop
[D][BluetoothA2DPSink.cpp:571] audio_data_callback(): audio_data_callback
[D][BluetoothA2DPSink.cpp:693] app_a2d_callback_2(): app_a2d_callback_2
[D][BluetoothA2DPSink.cpp:545] app_a2d_callback(): app_a2d_callback
[D][BluetoothA2DPSink.cpp:552] app_a2d_callback(): app_a2d_callback ESP_A2D_AUDIO_STATE_EVT
[D][BluetoothA2DPSink.cpp:571] audio_data_callback(): audio_data_callback
[D][BluetoothA2DPSink.cpp:203] app_work_dispatch(): app_work_dispatch event 0x1, param len 16
[D][BluetoothA2DPSink.cpp:235] app_send_msg(): app_send_msg
[D][BluetoothA2DPSink.cpp:571] audio_data_callback(): audio_data_callback
[D][BluetoothA2DPSink.cpp:254] app_task_handler(): app_task_handler, sig 0x1, 0x1
[W][BluetoothA2DPSink.cpp:257] app_task_handler(): app_task_handler, APP_SIG_WORK_DISPATCH sig: 1
[D][BluetoothA2DPSink.cpp:226] app_work_dispatched(): app_work_dispatched
[D][BluetoothA2DPSink.cpp:571] audio_data_callback(): audio_data_callback
[D][BluetoothA2DPSink.cpp:539] operator()(): operator()
[D][BluetoothA2DPSink.cpp:348] av_hdl_a2d_evt(): av_hdl_a2d_evt evt 1
[D][BluetoothA2DPSink.cpp:386] av_hdl_a2d_evt(): av_hdl_a2d_evt ESP_A2D_AUDIO_STATE_EVT
[D][BluetoothA2DPSink.cpp:571] audio_data_callback(): audio_data_callback
[I][BluetoothA2DPSink.cpp:388] av_hdl_a2d_evt(): A2DP audio state: Started
[D][BluetoothA2DPSink.cpp:571] audio_data_callback(): audio_data_callback
[D][BluetoothA2DPSink.cpp:571] audio_data_callback(): audio_data_callback
END

Debbugin for 1.0.5 and 1.0.6:
[D][BluetoothA2DPSink.cpp:122] start(): start
[I][BluetoothA2DPSink.cpp:127] start(): Device name will be set to 'ESP32_SPEAKER'
[D][BluetoothA2DPSink.cpp:174] init_bluetooth(): init_bluetooth
[I][BluetoothA2DPSink.cpp:179] init_bluetooth(): controller initialized
[I][BluetoothA2DPSink.cpp:188] init_bluetooth(): bluedroid initialized
[I][BluetoothA2DPSink.cpp:196] init_bluetooth(): bluedroid enabled
[D][BluetoothA2DPSink.cpp:274] app_task_start_up(): app_task_start_up
[D][BluetoothA2DPSink.cpp:203] app_work_dispatch(): app_work_dispatch event 0x0, param len 0
[D][BluetoothA2DPSink.cpp:681] app_task_handler_2(): app_task_handler_2
[D][BluetoothA2DPSink.cpp:250] app_task_handler(): app_task_handler
[D][BluetoothA2DPSink.cpp:235] app_send_msg(): app_send_msg
[D][BluetoothA2DPSink.cpp:254] app_task_handler(): app_task_handler, sig 0x1, 0x0
[W][BluetoothA2DPSink.cpp:257] app_task_handler(): app_task_handler, APP_SIG_WORK_DISPATCH sig: 1
[D][BluetoothA2DPSink.cpp:226] app_work_dispatched(): app_work_dispatched
[D][BluetoothA2DPSink.cpp:141] operator()(): operator()
[D][BluetoothA2DPSink.cpp:508] av_hdl_stack_evt(): av_hdl_stack_evt av_hdl_stack_evt BT_APP_EVT_STACK_UP
[D][BluetoothA2DPSink.cpp:693] app_a2d_callback_2(): app_a2d_callback_2
[D][BluetoothA2DPSink.cpp:545] app_a2d_callback(): app_a2d_callback
[D][BluetoothA2DPSink.cpp:548] app_a2d_callback(): app_a2d_callback ESP_A2D_CONNECTION_STATE_EVT
[D][BluetoothA2DPSink.cpp:203] app_work_dispatch(): app_work_dispatch event 0x0, param len 16
[D][BluetoothA2DPSink.cpp:235] app_send_msg(): app_send_msg
[D][BluetoothA2DPSink.cpp:254] app_task_handler(): app_task_handler, sig 0x1, 0x0
[W][BluetoothA2DPSink.cpp:257] app_task_handler(): app_task_handler, APP_SIG_WORK_DISPATCH sig: 1
[D][BluetoothA2DPSink.cpp:226] app_work_dispatched(): app_work_dispatched
[D][BluetoothA2DPSink.cpp:693] app_a2d_callback_2(): app_a2d_callback_2
[D][BluetoothA2DPSink.cpp:539] operator()(): operator()
[D][BluetoothA2DPSink.cpp:348] av_hdl_a2d_evt(): av_hdl_a2d_evt evt 0
[D][BluetoothA2DPSink.cpp:352] av_hdl_a2d_evt(): av_hdl_a2d_evt ESP_A2D_CONNECTION_STATE_EVT
[D][BluetoothA2DPSink.cpp:545] app_a2d_callback(): app_a2d_callback
[I][BluetoothA2DPSink.cpp:356] av_hdl_a2d_evt(): A2DP connection state: Connecting, [00:57:c1:43:a8:5b]
[D][BluetoothA2DPSink.cpp:557] app_a2d_callback(): app_a2d_callback ESP_A2D_AUDIO_CFG_EVT
[I][BluetoothA2DPSink.cpp:380] av_hdl_a2d_evt(): ESP_A2D_CONNECTION_STATE_CONNECTING
[D][BluetoothA2DPSink.cpp:203] app_work_dispatch(): app_work_dispatch event 0x2, param len 16
[D][BluetoothA2DPSink.cpp:235] app_send_msg(): app_send_msg
[D][BluetoothA2DPSink.cpp:254] app_task_handler(): app_task_handler, sig 0x1, 0x2
[D][BluetoothA2DPSink.cpp:693] app_a2d_callback_2(): app_a2d_callback_2
[W][BluetoothA2DPSink.cpp:257] app_task_handler(): app_task_handler, APP_SIG_WORK_DISPATCH sig: 1
[D][BluetoothA2DPSink.cpp:545] app_a2d_callback(): app_a2d_callback
[D][BluetoothA2DPSink.cpp:226] app_work_dispatched(): app_work_dispatched
[D][BluetoothA2DPSink.cpp:548] app_a2d_callback(): app_a2d_callback ESP_A2D_CONNECTION_STATE_EVT
[D][BluetoothA2DPSink.cpp:539] operator()(): operator()
[D][BluetoothA2DPSink.cpp:203] app_work_dispatch(): app_work_dispatch event 0x0, param len 16
[D][BluetoothA2DPSink.cpp:348] av_hdl_a2d_evt(): av_hdl_a2d_evt evt 2
[D][BluetoothA2DPSink.cpp:235] app_send_msg(): app_send_msg
[D][BluetoothA2DPSink.cpp:403] av_hdl_a2d_evt(): av_hdl_a2d_evt ESP_A2D_AUDIO_CFG_EVT
[I][BluetoothA2DPSink.cpp:407] av_hdl_a2d_evt(): a2dp audio_cfg_cb , codec type 0
[I][BluetoothA2DPSink.cpp:426] av_hdl_a2d_evt(): configure audio player 21-15-2-35

[I][BluetoothA2DPSink.cpp:427] av_hdl_a2d_evt(): audio player configured, samplerate=44100
[D][BluetoothA2DPSink.cpp:254] app_task_handler(): app_task_handler, sig 0x1, 0x0
[W][BluetoothA2DPSink.cpp:257] app_task_handler(): app_task_handler, APP_SIG_WORK_DISPATCH sig: 1
[D][BluetoothA2DPSink.cpp:226] app_work_dispatched(): app_work_dispatched
[D][BluetoothA2DPSink.cpp:539] operator()(): operator()
[D][BluetoothA2DPSink.cpp:348] av_hdl_a2d_evt(): av_hdl_a2d_evt evt 0
[D][BluetoothA2DPSink.cpp:352] av_hdl_a2d_evt(): av_hdl_a2d_evt ESP_A2D_CONNECTION_STATE_EVT
[I][BluetoothA2DPSink.cpp:356] av_hdl_a2d_evt(): A2DP connection state: Connected, [00:57:c1:43:a8:5b]
[I][BluetoothA2DPSink.cpp:374] av_hdl_a2d_evt(): ESP_A2D_CONNECTION_STATE_CONNECTED
[D][BluetoothA2DPSink.cpp:693] app_a2d_callback_2(): app_a2d_callback_2 (<-here app_rc_ct_callback() never is call)
[D][BluetoothA2DPSink.cpp:545] app_a2d_callback(): app_a2d_callback
[D][BluetoothA2DPSink.cpp:552] app_a2d_callback(): app_a2d_callback ESP_A2D_AUDIO_STATE_EVT
[D][BluetoothA2DPSink.cpp:203] app_work_dispatch(): app_work_dispatch event 0x1, param len 16
[D][BluetoothA2DPSink.cpp:235] app_send_msg(): app_send_msg
[D][BluetoothA2DPSink.cpp:254] app_task_handler(): app_task_handler, sig 0x1, 0x1
[W][BluetoothA2DPSink.cpp:257] app_task_handler(): app_task_handler, APP_SIG_WORK_DISPATCH sig: 1
[D][BluetoothA2DPSink.cpp:226] app_work_dispatched(): app_work_dispatched
[D][BluetoothA2DPSink.cpp:539] operator()(): operator()
[D][BluetoothA2DPSink.cpp:348] av_hdl_a2d_evt(): av_hdl_a2d_evt evt 1
[D][BluetoothA2DPSink.cpp:386] av_hdl_a2d_evt(): av_hdl_a2d_evt ESP_A2D_AUDIO_STATE_EVT
[I][BluetoothA2DPSink.cpp:388] av_hdl_a2d_evt(): A2DP audio state: Started
[D][BluetoothA2DPSink.cpp:571] audio_data_callback(): audio_data_callback
[D][BluetoothA2DPSink.cpp:571] audio_data_callback(): audio_data_callback
END

Thank you pschatzmann for great jog!

Metadata and controls examples

Hello everyone,
I'm new on the esp32 and his code so i can't understand much...
So i see that functions to control the device connected have been added but I can't see how to use them.
I also see that we can obtain metadata but i don't know how to get them.
Sorry to understand nothing :/ and thank you for your help.

PLAY_STATUS_CHANGE event added but no show

Hi there,
Thanks for your code and your work. I'd like to add more functionality, particulary PLAY_STATUS_CHANGE event.

  1. In BluetoothA2DPSink.cpp I added in av_notify_evt_handler()
    case ESP_AVRC_RN_PLAY_STATUS_CHANGE:
    ESP_LOGD(BT_AV_TAG, "%s ESP_AVRC_RN_PLAY_STATUS_CHANGE %d", func, event_id);
    av_track_status_change();
    break;
  2. in av_hdl_avrc_evt() added
    case ESP_AVRC_CT_PLAY_STATUS_RSP_EV:

code compiles ok but no show PLAY_STATUS_CHANGE event in debug.

!=!= mistake?

Sorry if I'm wrong, but this !=!= is OK?

if (i2s_driver_uninstall(i2s_port)!=!= ESP_OK){
ESP_LOGE(BT_AV_TAG,"Failed to uninstall i2s");
}

A2DP source using ADC(DMA) to sink

thanks for the article/code "Sending Sound from an ESP32 to a Bluetooth Sink".
I wanted to use your code to send data flow like below:

mobile-->microphone---ADC (DMA, using I2S ) source esp32 ----bluetooth speaker(sink)

So i defined the I2S function as below
`{
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN),
.sample_rate = 44100,
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
.channel_format = I2S_CHANNEL_FMT_ALL_LEFT,
.communication_format = I2S_COMM_FORMAT_I2S_MSB,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 8,
.dma_buf_len = 1024,
.use_apll = false
};

//install and start i2s driver
i2s_driver_install(i2s_num, &i2s_config, 0, NULL);
i2s_set_adc_mode(ADC_UNIT_1, ADC1_CHANNEL_0);
analogReadResolution(12);
adc1_config_width(ADC_WIDTH_BIT_12);
adc1_config_channel_atten(ADC1_CHANNEL_0, ADC_ATTEN_DB_0);

vTaskDelay(5000/portTICK_RATE_MS);
i2s_adc_enable(I2S_NUM_0);

}`

changed the get_data callback function as below:
`size_t bytes_read;
int16_t audio[len/2];
i2s_read(I2S_NUM_0, (void*) audio, len, &bytes_read, portMAX_DELAY);

int countt = 0;
int16_t raw = 0;
for(int i=0; i<len/2; i++){
    raw = (audio[i] & 0xfff)*16 ;  
    audio[i] = raw;
}
memcpy(data, audio, len);`

Getting data with noise.
can you suggest some pointers or any other better approach for this.

one more observation, connection between source and sink gets disconnected frequently.

thanks a lot.

Cannot reconnect to BT sink

I use the BluetoothA2DPSink class to create a BT sink, which works perfectly when first connected. However, after disconnecting I cannot seem to reconnect from either a laptop (Arch Linux, BlueZ 5.55, Thinkpad E490) or a phone (Samsung Galaxy A50). I have not tested with other devices, but I reckon that would be the same. The BT connection is in the ESP_A2D_CONNECTION_STATE_DISCONNECTED state at this point, and a manual reconnection attempt yields no debug info on the console.

I have solved the issue by performing a full restart (using esp_restart()) every time a device disconnects, and also inhibiting connection to the last known device on startup (as otherwise disconnecting would be impossible), but this is very hacky and I would much rather use a solution to the actual problem itself.

The code I am using:

#include "BluetoothA2DPSink.h"
BluetoothA2DPSink a2dp_sink;
void setup() {
   static const i2s_config_t i2s_config = {
      .mode = (i2s_mode_t) (I2S_MODE_MASTER | I2S_MODE_TX),
      .sample_rate = 44100,
      .bits_per_sample = (i2s_bits_per_sample_t) 16,
      .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
      .communication_format = I2S_COMM_FORMAT_I2S_MSB,
      .intr_alloc_flags = 0,
      .dma_buf_count = 8,
      .dma_buf_len = 64,
      .use_apll = false
  };
  static const i2s_pin_config_t pin_config = {
      .bck_io_num = 26,
      .ws_io_num = 25,
      .data_out_num = 27,
      .data_in_num = I2S_PIN_NO_CHANGE
  };
  a2dp_sink.set_i2s_config(i2s_config);  
  a2dp_sink.set_pin_config(pin_config);
  a2dp_sink.set_on_data_received(data_received_callback);
  a2dp_sink.start("Proba");
}
void loop(){}

Expanding 16-bit PCM to 32-bit PCM

Hi. @pschatzmann. Thank you for your contribution.

A few years ago, I managed to modify the ESP-IDF a2dp_sink sample for an external DAC to get a very clean sound from the external DAC.
I thought about applying the fix at that time to this library.
And I forked your library and made some modifications.

I considered sending a pull request to your library, but couldn't figure out a good fix.
Could you take a look at my fix? Please tell me even when you have time.

The modified part is BluetoothA2DPSink :: audio_data_callback ().
I used i2s_write_expand () to extend the input of 16-bit sampling to 32-bit sampling. Replaced i2s_write () with i2s_write_expand ().

However, I didn't understand the relationship between the source below and i2s_write ().
https://github.com/riraosan/ESP32-A2DP/blob/f93979c5e5212bd46fc9c806957d79f49f1f9384/src/BluetoothA2DPSink.cpp#L687-L698
This is the i2s setting part of the application class. I have confirmed that this application can output sound from an external DAC.

Under what conditions should I write code that uses i2s_write () and i2s_write_expand () properly?

Getting SPDIF output

Hi!
I'm trying to get audio from bluetooth and output it as SPDIF signal.
I found a library that uses I2S to do that.
My issue is that I need int16_t samples for each channel but I found in BluetoothA2DPSink.cpp file that function audio_data_callback gets uint8_t stream as input.
How to derive from it 16 bit samples for each stereo channels?

Audio distortion at bad bluetooth connection

Hello!

Thank you for this awesome library!

The problem:
If my phone sends music to the esp32 and I go away from the esp32(but it not disconnect) or I cover my phone antenna with my hands the sound will be distorted. Is it related to the code? Is it possible that the phone doesn't send signal? Can I detect if the bluetooth doesn't get data and stop the i2s interface?

Best regards

Very noising sound (on M5Stack)

Hi and thank you for your really nice job.

I'm trying the sketch to stream data from bluetooth directly to the internal DAC of my M5Stack (which includes everything for audio). But the sound is loud and not clean at all.

I tried to play with the i2s config but the values you defined looks good.

Any idea? Regards.

Volume state & control

When playing musing from my (Android) mobile, I'm able change the volume on the mobile. It would be great, if this was also possible on the ESP (as a sink).

I tried to implement a volume control by adding these two functions:

void BluetoothA2DPSink::volumeUp(){
    executeAVRCCommand(ESP_AVRC_PT_CMD_VOL_UP);
}

void BluetoothA2DPSink::volumeDown(){
    executeAVRCCommand(ESP_AVRC_PT_CMD_VOL_DOWN);
}

Unfortunately, that does not work.

Is it possible to control and may be even receive the current volume?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.