10 #include "AudioConfig.h"
13 #include "BluetoothA2DPSink.h"
14 #include "BluetoothA2DPSource.h"
15 #include "AudioTools/CoreAudio/AudioStreams.h"
16 #include "AudioTools/Concurrency/BufferRTOS.h"
17 #include "AudioTools/CoreAudio/AudioBasic/StrView.h"
23 static A2DPStream *A2DPStream_self=
nullptr;
25 static BufferRTOS<uint8_t>a2dp_buffer{0, A2DP_BUFFER_SIZE, portMAX_DELAY, portMAX_DELAY};
27 static bool is_a2dp_active =
false;
29 int32_t a2dp_stream_source_sound_data(Frame* data, int32_t len);
30 void a2dp_stream_sink_sound_data(
const uint8_t* data, uint32_t len);
51 bool auto_reconnect =
false;
52 int buffer_size = A2DP_BUFFER_SIZE * A2DP_BUFFER_COUNT;
85 assert(A2DPStream_self==
nullptr);
86 A2DPStream_self =
this;
95 if (a2dp_source!=
nullptr)
delete a2dp_source;
96 if (a2dp_sink!=
nullptr)
delete a2dp_sink;
97 A2DPStream_self =
nullptr;
104 cfg.
name=
"[Unknown]";
111 if (a2dp_source==
nullptr){
112 a2dp = a2dp_source =
new BluetoothA2DPSource();
119 if (a2dp_sink==
nullptr){
120 a2dp = a2dp_sink =
new BluetoothA2DPSink();
137 LOGI(
"Connecting to %s",cfg.
name);
139 if (!a2dp_buffer.
resize(cfg.buffer_size)){
140 LOGE(
"a2dp_buffer resize failed");
146 LOGI(
"Using StartOnConnect")
152 LOGI(
"Starting a2dp_source...");
154 a2dp_source->set_auto_reconnect(cfg.auto_reconnect);
155 a2dp_source->set_volume(
volume() * A2DP_MAX_VOL);
158 a2dp_source->set_ssid_callback(detected_device);
160 a2dp_source->set_on_connection_state_changed(a2dp_state_callback,
this);
161 a2dp_source->start_raw((
char*)cfg.
name, a2dp_stream_source_sound_data);
162 while(!a2dp_source->is_connected()){
163 LOGD(
"waiting for connection");
166 LOGI(
"a2dp_source is connected...");
173 LOGI(
"Starting a2dp_sink...");
175 a2dp_sink->set_auto_reconnect(cfg.auto_reconnect);
177 a2dp_sink->set_volume(
volume() * A2DP_MAX_VOL);
178 a2dp_sink->set_on_connection_state_changed(a2dp_state_callback,
this);
180 a2dp_sink->start((
char*)cfg.
name);
181 while(!a2dp_sink->is_connected()){
182 LOGD(
"waiting for connection");
185 LOGI(
"a2dp_sink is connected...");
186 is_a2dp_active =
true;
190 LOGE(
"Undefined mode: %d", cfg.mode);
197 void end()
override {
198 if (a2dp !=
nullptr) {
206 if (a2dp_source==
nullptr && a2dp_sink==
nullptr)
return false;
207 if (a2dp_source!=
nullptr)
return a2dp_source->is_connected();
208 return a2dp_sink->is_connected();
213 return is_a2dp_active;
222 size_t write(
const uint8_t* data,
size_t len)
override {
223 LOGD(
"%s: %zu", LOG_METHOD, len);
224 if (config.mode == TX_MODE){
228 && a2dp_buffer.
available() >= 0.8f * a2dp_buffer.size()){
230 is_a2dp_active =
true;
238 LOGD(
"Waiting for buffer: writing %d > available %d", (
int) len, (
int) free);
240 timeout -= wait_time;
241 if (timeout <= 0)
return 0;
249 size_t result = a2dp_buffer.
writeArray(data, len);
250 LOGD(
"write %d -> %d", len, result);
251 if (config.mode == TX_MODE){
260 if (!is_a2dp_active){
261 LOGW(
"readBytes failed because !is_a2dp_active");
264 LOGD(
"readBytes %d", len);
265 size_t result = a2dp_buffer.
readArray(data, len);
266 LOGI(
"readBytes %d->%d", len,result);
273 if (config.mode!=RX_MODE)
return 0;
280 if (config.mode!=TX_MODE )
return 0;
289 if (a2dp!=
nullptr) a2dp->set_volume(
volume * A2DP_MAX_VOL);
305 BluetoothA2DPSource *a2dp_source =
nullptr;
306 BluetoothA2DPSink *a2dp_sink =
nullptr;
307 BluetoothA2DPCommon *a2dp=
nullptr;
308 const int A2DP_MAX_VOL = 128;
311 static bool detected_device(
const char* ssid, esp_bd_addr_t address,
int rssi){
312 LOGW(
"found Device: %s rssi: %d", ssid, rssi);
317 static void a2dp_state_callback(esp_a2d_connection_state_t state,
void *caller){
319 A2DPStream *
self = (A2DPStream*)caller;
320 if (state==ESP_A2D_CONNECTION_STATE_CONNECTED && self->config.startup_logic==StartOnConnect){
321 is_a2dp_active =
true;
323 LOGW(
"==> state: %s", self->a2dp->to_str(state));
328 static int32_t a2dp_stream_source_sound_data(uint8_t* data, int32_t len) {
329 int32_t result_len = 0;
330 A2DPConfig config = A2DPStream_self->config;
336 result_len = a2dp_buffer.
readArray((uint8_t*)data, len);
339 if (config.silence_on_nodata && result_len == 0){
346 switch (config.startup_nodata) {
348 memset(data, 0, len);
351 int16_t *data16 = (int16_t*)data;
352 for (
int j=0;j<len/4;j+=2){
353 data16[j+1] = data16[j] = (rand() % 50) - 25;
363 LOGD(
"a2dp_stream_source_sound_data: %d -> %d", len, result_len);
370 uint32_t result_len = a2dp_buffer.
writeArray(data, len);
371 LOGD(
"a2dp_stream_sink_sound_data %d -> %d", len, result_len);
381 notifyAudioChange(info);
RxTxMode
The Microcontroller is the Audio Source (TX_MODE) or Audio Sink (RX_MODE). RXTX_MODE is Source and Si...
Definition: AudioTypes.h:28