"basic-generator-a2dp" example not working #1694
-
Problem DescriptionAs stated in the wiki, I've started my exploration by using examples. I've changed the name of the device, also changed log level to I've added a simple Device DescriptionI'm using ESP Wroom, esp32 core 3.0.4 (Wiki mentions 2.0.17 being latest, is v3 supported?). Board is unknown chinese but I found some ref online mentioning "hw-394" and that the profile to use should be ESP32-WROOM-DA board. Sketch/**
* @file basic-generator-a2dp.ino
* @author Phil Schatzmann
* @brief We send a test sine signal to a bluetooth speaker
* @copyright GPLv3
*/
#include "AudioTools.h"
#include "AudioLibs/A2DPStream.h"
const char* name = "Bose Color II SoundLink"; // Replace with your bluetooth speaker name
SineWaveGenerator<int16_t> sineWave(32000); // subclass of SoundGenerator, set max amplitude (=volume)
GeneratedSoundStream<int16_t> in_stream(sineWave); // Stream generated from sine wave
BluetoothA2DPSource a2dp_source; // A2DP Sender
// callback used by A2DP to provide the sound data - usually len is 128 * 2 channel int16 frames
int32_t get_sound_data(uint8_t * data, int32_t len) {
Serial.println("get_sound_data");
return in_stream.readBytes((uint8_t*)data, len);
}
// Arduino Setup
void setup(void) {
Serial.begin(115200);
AudioLogger::instance().begin(Serial, AudioLogger::Info);
// start input
auto cfg = in_stream.defaultConfig();
cfg.bits_per_sample = 16;
cfg.channels = 2;
cfg.sample_rate = 44100;
in_stream.begin(cfg);
sineWave.begin(cfg, N_B4);
// start the bluetooth
Serial.println("starting A2DP...");
a2dp_source.set_auto_reconnect(true);
a2dp_source.start_raw(name, get_sound_data);
}
// Arduino loop - repeated processing
void loop() {
delay(1000);
} Other Steps to ReproduceBuild and run What is your development environmentArduino IDE (2.3.2) I have checked existing issues, discussions and online documentation
|
Beta Was this translation helpful? Give feedback.
Replies: 13 comments 3 replies
-
I don't see any reason why v3.0.4 should not work. The A2DP library uses the Arduino ESP32 logger, so if you want to see any warnings or errors you need to activate the logger in the Arduino Tools menu |
Beta Was this translation helpful? Give feedback.
-
EDIT2: I see the logs, but there's just no logging appended after some point:
That is a typical log chunk i see after booting the ESP32. I still wonder what could be a reason why there's no audible output then 🤔? EDIT: As suggested in the wiki I've tried to add a visualiser (i guess over Serial plotter) in my sketch, but nothing is showing on the plotter (so far). serial is also totally silent after /**
* @file basic-generator-a2dp.ino
* @author Phil Schatzmann
* @brief We send a test sine signal to a bluetooth speaker
* @copyright GPLv3
*/
#include "AudioTools.h"
#include "AudioLibs/A2DPStream.h"
const char* name = "Bose Color II SoundLink"; // Replace with your bluetooth speaker name
+AudioInfo info(44100, 2, 16);
SineWaveGenerator<int16_t> sineWave(32000); // subclass of SoundGenerator, set max amplitude (=volume)
GeneratedSoundStream<int16_t> in_stream(sineWave); // Stream generated from sine wave
BluetoothA2DPSource a2dp_source; // A2DP Sender
+CsvOutput<int32_t> csvStream(Serial);
+StreamCopy copier(csvStream, in_stream); // copy i2sStream to csvStream
// callback used by A2DP to provide the sound data - usually len is 128 * 2 channel int16 frames
int32_t get_sound_data(uint8_t * data, int32_t len) {
- return in_stream.readBytes((uint8_t*)data, len);
+ int32_t result = in_stream.readBytes(data, len);
+ LOGI("get_sound_data %d->%d",len, result);
+ return result;
}
// Arduino Setup
void setup(void) {
Serial.begin(115200);
AudioLogger::instance().begin(Serial, AudioLogger::Info);
// start input
auto cfg = in_stream.defaultConfig();
cfg.bits_per_sample = 16;
cfg.channels = 2;
cfg.sample_rate = 44100;
in_stream.begin(cfg);
sineWave.begin(cfg, N_B4);
// start the bluetooth
Serial.println("starting A2DP...");
a2dp_source.set_auto_reconnect(true);
a2dp_source.start_raw(name, get_sound_data);
+ csvStream.begin(info);
}
// Arduino loop - repeated processing
void loop() {
delay(1000);
} With this i'll see the |
Beta Was this translation helpful? Give feedback.
-
![]() I have found that maybe the issue is that the data is not playable. I'm now looking at an example to build an mp3 encoded sine wave using your mp3 encoder https://github.com/pschatzmann/arduino-liblame. |
Beta Was this translation helpful? Give feedback.
-
It took me a couple of hours, but i got a compiling sketch (posting this in case somebody finds it useful). #include <AudioTools.h>
#include <AudioLibs/A2DPStream.h>
#include <AudioCodecs/CodecMP3LAME.h>
const char* name = "Bose Color II SoundLink";
SineWaveGenerator<int16_t> sineWave(32000);
GeneratedSoundStream<int16_t> in_stream(sineWave);
BufferedStream out_stream(1024);
AudioInfo info(44100, 2, 16);
MP3EncoderLAME mp3;
EncodedAudioOutput enc_stream(&out_stream, &mp3);
Throttle throttle(enc_stream);
static int frame_size = 498;
StreamCopy copier(throttle, in_stream, frame_size);
BluetoothA2DPSource a2dp_source;
// callback used by A2DP to provide the sound data - usually len is 128 * 2 channel int16 frames
int32_t get_sound_data(uint8_t * data, int32_t len) {
int32_t result = out_stream.readBytes((uint8_t*)data, len);
// LOGI("get_sound_data %d->%d",len, result);
return result;
}
// Arduino Setup
void setup(void) {
Serial.begin(115200);
AudioLogger::instance().begin(Serial, AudioLogger::Info);
throttle.begin(info);
in_stream.begin(info);
sineWave.begin(info, N_B4);
enc_stream.begin(info);
// start the bluetooth
Serial.println("starting A2DP...");
a2dp_source.set_auto_reconnect(true);
a2dp_source.start_raw(name, get_sound_data);
}
// Arduino loop - repeated processing
void loop() {
copier.copy();
} The flow i aimed to design was: Sine → SineStream → Copier → Throttle → EncodedAudioOutput → BufferedStream → BluetoothA2DPSource The problem i was not expecting was my board doesn't have SPIRAM which is required by the LAME encoder. This was easily spotted in the logs, hopefully.
I will switch to AAC/SBC and see if sound shows up, just to confirm that it was a codec issue. |
Beta Was this translation helpful? Give feedback.
-
Weirdly, a drop-in replacement with the SBC does not produce sound either: #include <AudioTools.h>
#include <AudioLibs/A2DPStream.h>
#include <AudioCodecs/CodecSBC.h>
const char* name = "Bose Color II SoundLink";
SineWaveGenerator<int16_t> sineWave(32000);
GeneratedSoundStream<int16_t> in_stream(sineWave);
BufferedStream out_stream(1024);
AudioInfo info(44100, 2, 16);
SBCEncoder encoder;
EncodedAudioOutput enc_stream(&out_stream, &encoder);
Throttle throttle(enc_stream);
static int frame_size = 498;
StreamCopy copier(throttle, in_stream, frame_size);
BluetoothA2DPSource a2dp_source;
int32_t get_sound_data(uint8_t * data, int32_t len) {
int32_t result = out_stream.readBytes((uint8_t*)data, len);
// LOGI("get_sound_data %d->%d",len, result);
return result;
}
// Arduino Setup
void setup(void) {
Serial.begin(115200);
AudioLogger::instance().begin(Serial, AudioLogger::Info);
Serial.println("Building pipeline...");
throttle.begin(info);
in_stream.begin(info);
sineWave.begin(info, N_B4);
enc_stream.begin(info);
// start the bluetooth
Serial.println("starting A2DP...");
a2dp_source.set_auto_reconnect(true);
a2dp_source.start_raw(name, get_sound_data);
}
// Arduino loop - repeated processing
void loop() {
copier.copy();
} we can see the copier gets some data in/out: It's quite hard to debug what's happening in a pipeline, so far there's no way for me to know/discover what's happening. I'll keep hacking around until i get results. |
Beta Was this translation helpful? Give feedback.
-
Dropping the throttler does not help further: #include <AudioTools.h>
#include <AudioLibs/A2DPStream.h>
#include <AudioCodecs/CodecSBC.h>
const char* name = "Bose Color II SoundLink";
SineWaveGenerator<int16_t> sineWave(32000);
GeneratedSoundStream<int16_t> in_stream(sineWave);
BufferedStream out_stream(1024);
AudioInfo info(44100, 2, 16);
SBCEncoder encoder;
EncodedAudioOutput enc_stream(&out_stream, &encoder);
static int frame_size = 498;
StreamCopy copier(enc_stream, in_stream, frame_size);
BluetoothA2DPSource a2dp_source;
int32_t get_sound_data(uint8_t * data, int32_t len) {
int32_t result = out_stream.readBytes((uint8_t*)data, len);
// LOGI("get_sound_data %d->%d",len, result);
return result;
}
// Arduino Setup
void setup(void) {
Serial.begin(115200);
AudioLogger::instance().begin(Serial, AudioLogger::Warning);
Serial.println("Building pipeline...");
in_stream.begin(info);
sineWave.begin(info, N_B4);
enc_stream.begin(info);
// start the bluetooth
Serial.println("starting A2DP...");
a2dp_source.set_auto_reconnect(true);
a2dp_source.start_raw(name, get_sound_data);
}
// Arduino loop - repeated processing
void loop() {
copier.copy();
} |
Beta Was this translation helpful? Give feedback.
-
I've gone to an easier script. Due to memory limitation i cannot upload the full Now doing: #include "StarWars30.h"
#include <AudioTools.h>
#include <AudioLibs/A2DPStream.h>
const char* name = "Bose Color II SoundLink";
MemoryStream music(StarWars30_raw, StarWars30_raw_len);
BluetoothA2DPSource a2dp_source;
int32_t get_sound_data(uint8_t * data, int32_t len) {
int32_t result = music.readBytes((uint8_t*)data, len);
LOGI("get_sound_data %d->%d",len, result);
return result;
}
// Arduino Setup
void setup(void) {
Serial.begin(115200);
AudioLogger::instance().begin(Serial, AudioLogger::Info);
// start the bluetooth
Serial.println("starting A2DP...");
a2dp_source.set_auto_reconnect(true);
a2dp_source.start_raw(name, get_sound_data);
music.begin();
}
void loop() {} Logs show there's something wrong (i guess) since the |
Beta Was this translation helpful? Give feedback.
-
if i may,few questions.
|
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
@pschatzmann may i ask for some pointers at a solution? is the hardware an issue (board, speaker) or rather the software? and more importantly, how would i debug that? I had never succeeded so far at having a sine showing in the plotter. |
Beta Was this translation helpful? Give feedback.
-
The Wiki contains a chapter on how to find this out: https://github.com/pschatzmann/arduino-audio-tools/wiki/It's-not-working The ESP32 A2DP API only supports PCM data as input which will be converted to SBC internally. (As you can find in the Readme of the A2DP library). Finally you never seemed to analyse the A2DP logs.... |
Beta Was this translation helpful? Give feedback.
-
@pschatzmann thank you and sorry for mentioning you. I'll follow your pointers and will update... until it works 😅 EDIT: if a2dp only supports PCM as input, then does that mean we can't send mp3s (stored on an sdcard)? or with additional decoder stream in between? EDIT2: i'd wish to convert this into a discussion but i dont think i'm allowed to. |
Beta Was this translation helpful? Give feedback.
-
I was just checking the existing examples which are using libhelix:
are still compiling properly: with 2.0.17: Sketch uses 1449937 bytes (46%) of program storage space. Maximum is 3145728 bytes. Both can be found in examples-communication/a2dp These sketches are assuming that the mp3 provides the data with the correct format (sample rate). Otherwise you would need to add a resampling step. ps. it is not the A2DP library which does the SBC encoding but the ESP32 IDF A2DP API |
Beta Was this translation helpful? Give feedback.
I don't see any reason why v3.0.4 should not work.
The A2DP library uses the Arduino ESP32 logger, so if you want to see any warnings or errors you need to activate the logger in the Arduino Tools menu