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;
83 assert(A2DPStream_self==
nullptr);
84 A2DPStream_self =
this;
93 if (a2dp_source!=
nullptr)
delete a2dp_source;
94 if (a2dp_sink!=
nullptr)
delete a2dp_sink;
95 A2DPStream_self =
nullptr;
102 cfg.
name=
"[Unknown]";
109 if (a2dp_source==
nullptr){
110 a2dp = a2dp_source =
new BluetoothA2DPSource();
117 if (a2dp_sink==
nullptr){
118 a2dp = a2dp_sink =
new BluetoothA2DPSink();
135 LOGI(
"Connecting to %s",cfg.
name);
137 if (!a2dp_buffer.
resize(cfg.buffer_size)){
138 LOGE(
"a2dp_buffer resize failed");
144 LOGI(
"Using StartOnConnect")
150 LOGI(
"Starting a2dp_source...");
152 a2dp_source->set_auto_reconnect(cfg.auto_reconnect);
153 a2dp_source->set_volume(
volume() * A2DP_MAX_VOL);
156 a2dp_source->set_ssid_callback(detected_device);
158 a2dp_source->set_on_connection_state_changed(a2dp_state_callback,
this);
159 a2dp_source->start_raw((
char*)cfg.
name, a2dp_stream_source_sound_data);
160 while(!a2dp_source->is_connected()){
161 LOGD(
"waiting for connection");
164 LOGI(
"a2dp_source is connected...");
171 LOGI(
"Starting a2dp_sink...");
173 a2dp_sink->set_auto_reconnect(cfg.auto_reconnect);
175 a2dp_sink->set_volume(
volume() * A2DP_MAX_VOL);
176 a2dp_sink->set_on_connection_state_changed(a2dp_state_callback,
this);
178 a2dp_sink->start((
char*)cfg.
name);
179 while(!a2dp_sink->is_connected()){
180 LOGD(
"waiting for connection");
183 LOGI(
"a2dp_sink is connected...");
184 is_a2dp_active =
true;
188 LOGE(
"Undefined mode: %d", cfg.mode);
195 void end()
override {
196 if (a2dp !=
nullptr) {
204 if (a2dp_source==
nullptr && a2dp_sink==
nullptr)
return false;
205 if (a2dp_source!=
nullptr)
return a2dp_source->is_connected();
206 return a2dp_sink->is_connected();
211 return is_a2dp_active;
220 size_t write(
const uint8_t* data,
size_t len)
override {
221 LOGD(
"%s: %zu", LOG_METHOD, len);
222 if (config.mode == TX_MODE){
226 && a2dp_buffer.
available() >= 0.8f * a2dp_buffer.size()){
228 is_a2dp_active =
true;
234 LOGD(
"Waiting for buffer: writing %d > available %d", (
int) len, (
int) free);
241 size_t result = a2dp_buffer.
writeArray(data, len);
242 LOGD(
"write %d -> %d", len, result);
243 if (config.mode == TX_MODE){
252 if (!is_a2dp_active){
253 LOGW(
"readBytes failed because !is_a2dp_active");
256 LOGD(
"readBytes %d", len);
257 size_t result = a2dp_buffer.
readArray(data, len);
258 LOGI(
"readBytes %d->%d", len,result);
265 if (config.mode!=RX_MODE)
return 0;
272 if (config.mode!=TX_MODE )
return 0;
281 if (a2dp!=
nullptr) a2dp->set_volume(
volume * A2DP_MAX_VOL);
297 BluetoothA2DPSource *a2dp_source =
nullptr;
298 BluetoothA2DPSink *a2dp_sink =
nullptr;
299 BluetoothA2DPCommon *a2dp=
nullptr;
300 const int A2DP_MAX_VOL = 128;
303 static bool detected_device(
const char* ssid, esp_bd_addr_t address,
int rssi){
304 LOGW(
"found Device: %s rssi: %d", ssid, rssi);
309 static void a2dp_state_callback(esp_a2d_connection_state_t state,
void *caller){
311 A2DPStream *
self = (A2DPStream*)caller;
312 if (state==ESP_A2D_CONNECTION_STATE_CONNECTED && self->config.startup_logic==StartOnConnect){
313 is_a2dp_active =
true;
315 LOGW(
"==> state: %s", self->a2dp->to_str(state));
320 static int32_t a2dp_stream_source_sound_data(uint8_t* data, int32_t len) {
321 int32_t result_len = 0;
322 A2DPConfig config = A2DPStream_self->config;
328 result_len = a2dp_buffer.
readArray((uint8_t*)data, len);
331 if (config.silence_on_nodata && result_len == 0){
338 switch (config.startup_nodata) {
340 memset(data, 0, len);
343 int16_t *data16 = (int16_t*)data;
344 for (
int j=0;j<len/4;j+=2){
345 data16[j+1] = data16[j] = (rand() % 50) - 25;
355 LOGD(
"a2dp_stream_source_sound_data: %d -> %d", len, result_len);
362 uint32_t result_len = a2dp_buffer.
writeArray(data, len);
363 LOGD(
"a2dp_stream_sink_sound_data %d -> %d", len, result_len);
373 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