10#include "AudioConfig.h"
13#include "BluetoothA2DPSink.h"
14#include "BluetoothA2DPSource.h"
15#include "AudioTools/CoreAudio/AudioStreams.h"
16#include "AudioTools/Concurrency/RTOS/BufferRTOS.h"
17#include "AudioTools/CoreAudio/AudioBasic/StrView.h"
23static A2DPStream *A2DPStream_self=
nullptr;
25static BufferRTOS<uint8_t>a2dp_buffer{0, A2DP_BUFFER_SIZE, portMAX_DELAY, portMAX_DELAY};
27static bool is_a2dp_active =
false;
29int32_t a2dp_stream_source_sound_data(Frame* data, int32_t len);
30void a2dp_stream_sink_sound_data(
const uint8_t* data, uint32_t len);
54 int buffer_size = A2DP_BUFFER_SIZE * A2DP_BUFFER_COUNT;
89 assert(A2DPStream_self==
nullptr);
90 A2DPStream_self =
this;
99 if (a2dp_source!=
nullptr)
delete a2dp_source;
100 if (a2dp_sink!=
nullptr)
delete a2dp_sink;
101 A2DPStream_self =
nullptr;
108 cfg.
name=
"[Unknown]";
115 if (a2dp_source==
nullptr){
123 if (a2dp_sink==
nullptr){
142 LOGI(
"Connecting to %s",cfg.
name);
144 if (!a2dp_buffer.resize(cfg.buffer_size)){
145 LOGE(
"a2dp_buffer resize failed");
151 LOGI(
"Using StartOnConnect")
157 LOGI(
"Starting a2dp_source...");
160 a2dp_source->set_volume(
volume() * A2DP_MAX_VOL);
163 a2dp_source->set_ssid_callback(detected_device);
165 a2dp_source->set_on_connection_state_changed(a2dp_state_callback,
this);
166 a2dp_source->start_raw((
char*)cfg.
name, a2dp_stream_source_sound_data);
168 while(!a2dp_source->is_connected()){
169 LOGD(
"waiting for connection");
172 LOGI(
"a2dp_source is connected...");
177 LOGI(
"a2dp_source started without connecting");
183 LOGI(
"Starting a2dp_sink...");
187 a2dp_sink->set_volume(
volume() * A2DP_MAX_VOL);
188 a2dp_sink->set_on_connection_state_changed(a2dp_state_callback,
this);
190 a2dp_sink->start((
char*)cfg.
name);
192 while(!a2dp_sink->is_connected()){
193 LOGD(
"waiting for connection");
196 LOGI(
"a2dp_sink is connected...");
199 LOGI(
"a2dp_sink started without connection");
201 is_a2dp_active =
true;
205 LOGE(
"Undefined mode: %d", cfg.
mode);
212 void end()
override {
213 if (a2dp !=
nullptr) {
221 if (a2dp_source==
nullptr && a2dp_sink==
nullptr)
return false;
222 if (a2dp_source!=
nullptr)
return a2dp_source->is_connected();
223 return a2dp_sink->is_connected();
228 return is_a2dp_active;
238 LOGD(
"%s: %zu", LOG_METHOD, len);
239 if (config.
mode == TX_MODE){
243 && a2dp_buffer.available() >= 0.8f * a2dp_buffer.size()){
245 is_a2dp_active =
true;
251 size_t free = a2dp_buffer.availableForWrite();
253 LOGD(
"Waiting for buffer: writing %d > available %d", (
int) len, (
int) free);
256 if (timeout <= 0)
return 0;
259 free = a2dp_buffer.availableForWrite();
264 size_t result = a2dp_buffer.writeArray(data, len);
265 LOGD(
"write %d -> %d", len, result);
266 if (config.
mode == TX_MODE){
275 if (!is_a2dp_active){
276 LOGW(
"readBytes failed because !is_a2dp_active");
279 LOGD(
"readBytes %d", len);
280 size_t result = a2dp_buffer.readArray(data, len);
281 LOGI(
"readBytes %d->%d", len,result);
288 if (config.
mode!=RX_MODE)
return 0;
289 return a2dp_buffer.available();
295 if (config.
mode!=TX_MODE )
return 0;
297 return a2dp_buffer.availableForWrite();
304 if (a2dp!=
nullptr) a2dp->set_volume(
volume * A2DP_MAX_VOL);
323 const int A2DP_MAX_VOL = 128;
327 LOGW(
"found Device: %s rssi: %d", ssid,
rssi);
332 static void a2dp_state_callback(esp_a2d_connection_state_t state,
void *caller){
334 A2DPStream *self = (A2DPStream*)caller;
335 if (state==ESP_A2D_CONNECTION_STATE_CONNECTED && self->config.startup_logic==StartOnConnect){
336 is_a2dp_active =
true;
338 LOGW(
"==> state: %s", self->a2dp->to_str(state));
343 static int32_t a2dp_stream_source_sound_data(uint8_t* data, int32_t len) {
344 int32_t result_len = 0;
345 A2DPConfig config = A2DPStream_self->config;
351 result_len = a2dp_buffer.readArray((uint8_t*)data, len);
354 if (config.silence_on_nodata && result_len == 0){
361 switch (config.startup_nodata) {
363 memset(data, 0, len);
366 int16_t *data16 = (int16_t*)data;
367 for (
int j=0;j<len/4;j+=2){
368 data16[j+1] = data16[j] = (rand() % 50) - 25;
378 LOGD(
"a2dp_stream_source_sound_data: %d -> %d", len, result_len);
386 LOGD(
"a2dp_stream_sink_sound_data %d -> %d", len,
result_len);
396 notifyAudioChange(info);
401 A2DPStream_self->info.sample_rate = rate;
402 A2DPStream_self->notify_base_Info(rate);
RxTxMode
The Microcontroller is the Audio Source (TX_MODE) or Audio Sink (RX_MODE). RXTX_MODE is Source and Si...
Definition AudioTypes.h:28