|
esp32-a2dp-xq 0.1.0
ESP32 A2DP source with SBC-XQ
|
esp32-a2dp-xq: ESP32 as a Bluetooth A2DP source (sends audio to headphones and speakers) with SBC-XQ. More...
#include <stdbool.h>#include <stddef.h>#include <stdint.h>#include "esp_err.h"
Go to the source code of this file.
Data Structures | |
| struct | a2dp_xq_device_t |
| struct | a2dp_xq_status_t |
| struct | a2dp_xq_event_t |
| struct | a2dp_xq_config_t |
| struct | a2dp_xq_stats_t |
Macros | |
| #define | A2DP_XQ_VERSION_MAJOR 0 |
| #define | A2DP_XQ_VERSION_MINOR 1 |
| #define | A2DP_XQ_VERSION_PATCH 0 |
| #define | A2DP_XQ_VERSION_STRING "0.1.0" |
| #define | A2DP_XQ_SAMPLE_RATE 44100u |
| The Bluedroid SBC encoder takes 16-bit stereo PCM at this rate. | |
| #define | A2DP_XQ_CONFIG_DEFAULT() |
Typedefs | |
| typedef void(* | a2dp_xq_event_cb_t) (const a2dp_xq_event_t *event, void *user) |
| Both callbacks run in the library's worker task, outside its locks: they may call back into the library. | |
| typedef void(* | a2dp_xq_remote_cb_t) (a2dp_xq_remote_t cmd, int value, void *user) |
Functions | |
| bool | a2dp_xq_supported (void) |
| True when this build can negotiate SBC-XQ (ESP-IDF >= 6.0 with the internal SBC encoder). | |
| esp_err_t | a2dp_xq_init (const a2dp_xq_config_t *cfg) |
| Start the controller (BR/EDR only, the BLE memory is released), Bluedroid, A2DP source and AVRCP. | |
| void | a2dp_xq_deinit (void) |
| Disconnect and release everything (controller disabled, memory returned). | |
| bool | a2dp_xq_is_initialized (void) |
| esp_err_t | a2dp_xq_start (void) |
| Open the audio path: the stream to the headphones starts as soon as they are connected. | |
| void | a2dp_xq_stop (void) |
| Close the audio path (queued audio is dropped) and suspend the stream. | |
| void | a2dp_xq_pause (bool paused) |
| Pause keeps the queued audio; after 5 s of pause the stream is suspended so the headphones can sleep their decoder. | |
| int32_t | a2dp_xq_write_s16 (const int16_t *pcm, uint32_t frames, uint32_t timeout_ms) |
| Queue interleaved stereo frames at A2DP_XQ_SAMPLE_RATE. | |
| int32_t | a2dp_xq_write_q31 (const int32_t *pcm, uint32_t frames, uint32_t timeout_ms) |
| Same from left-justified 32-bit samples (24-bit audio in the top bits): reduced to 16 bits with TPDF dither, so quiet passages keep their resolution. | |
| void | a2dp_xq_flush (void) |
| Drop what is queued (seek, skip). | |
| uint32_t | a2dp_xq_buffered_frames (void) |
| Frames queued and not yet sent. | |
| void | a2dp_xq_set_volume_db (float db) |
| Output volume in dB (<= 0). | |
| float | a2dp_xq_volume_to_db (int v127) |
| AVRCP absolute volume (0..127) <-> dB: 127 = 0 dB, 1..127 span 60 dB in equal steps, 0 = mute. | |
| uint8_t | a2dp_xq_volume_from_db (float db) |
| void | a2dp_xq_get_status (a2dp_xq_status_t *out) |
| void | a2dp_xq_describe (char *out, size_t out_size) |
| "SBC-XQ 452 kbps", "SBC 328 kbps", "" when not connected. | |
| void | a2dp_xq_scan (bool start) |
| Inquiry for about 10 s; A2DP_XQ_EVENT_DEVICE_FOUND per device (audio devices only). | |
| uint32_t | a2dp_xq_devices (a2dp_xq_device_t *out, uint32_t max) |
| Bonded devices and the ones found by the last scan: connected first, then paired, then by signal strength. | |
| esp_err_t | a2dp_xq_connect (const char *addr) |
| void | a2dp_xq_disconnect (void) |
| void | a2dp_xq_forget (const char *addr) |
| Remove the bond and the stored results of a device. | |
| esp_err_t | a2dp_xq_set_xq_allowed (const char *addr, bool allowed) |
| Allow or forbid SBC-XQ for one device (kept in state_dir); takes effect on the next connection. | |
| void | a2dp_xq_get_stats (a2dp_xq_stats_t *out) |
esp32-a2dp-xq: ESP32 as a Bluetooth A2DP source (sends audio to headphones and speakers) with SBC-XQ.
Classic ESP32 only (ESP32-S3/C3/C6 have no Bluetooth Classic). The application writes stereo PCM at 44.1 kHz:
a2dp_xq_config_t cfg = A2DP_XQ_CONFIG_DEFAULT(); cfg.device_name = "My speaker source"; a2dp_xq_init(&cfg); a2dp_xq_connect("aa:bb:cc:dd:ee:ff"); // or a2dp_xq_scan(true) and pick a device a2dp_xq_start(); for (;;) a2dp_xq_write_s16(pcm, frames, portMAX_DELAY);
| #define A2DP_XQ_CONFIG_DEFAULT | ( | ) |
| #define A2DP_XQ_SAMPLE_RATE 44100u |
The Bluedroid SBC encoder takes 16-bit stereo PCM at this rate.
| #define A2DP_XQ_VERSION_MAJOR 0 |
| #define A2DP_XQ_VERSION_MINOR 1 |
| #define A2DP_XQ_VERSION_PATCH 0 |
| #define A2DP_XQ_VERSION_STRING "0.1.0" |
| typedef void(* a2dp_xq_event_cb_t) (const a2dp_xq_event_t *event, void *user) |
Both callbacks run in the library's worker task, outside its locks: they may call back into the library.
Keep them short.
| typedef void(* a2dp_xq_remote_cb_t) (a2dp_xq_remote_t cmd, int value, void *user) |
| enum a2dp_xq_event_type_t |
| Enumerator | |
|---|---|
| A2DP_XQ_EVENT_STATE | state changed: event.state |
| A2DP_XQ_EVENT_DEVICE_FOUND | discovery found or named a device: event.device |
| A2DP_XQ_EVENT_PAIRING_FAILED | event.device.addr |
| A2DP_XQ_EVENT_CODEC | the stream configuration is known: a2dp_xq_get_status() |
| enum a2dp_xq_remote_t |
| enum a2dp_xq_state_t |
| uint32_t a2dp_xq_buffered_frames | ( | void | ) |
Frames queued and not yet sent.
| esp_err_t a2dp_xq_connect | ( | const char * | addr | ) |
| void a2dp_xq_deinit | ( | void | ) |
Disconnect and release everything (controller disabled, memory returned).
| void a2dp_xq_describe | ( | char * | out, |
| size_t | out_size | ||
| ) |
"SBC-XQ 452 kbps", "SBC 328 kbps", "" when not connected.
| uint32_t a2dp_xq_devices | ( | a2dp_xq_device_t * | out, |
| uint32_t | max | ||
| ) |
Bonded devices and the ones found by the last scan: connected first, then paired, then by signal strength.
Returns the number written.
| void a2dp_xq_disconnect | ( | void | ) |
| void a2dp_xq_flush | ( | void | ) |
Drop what is queued (seek, skip).
| void a2dp_xq_forget | ( | const char * | addr | ) |
Remove the bond and the stored results of a device.
| void a2dp_xq_get_stats | ( | a2dp_xq_stats_t * | out | ) |
| void a2dp_xq_get_status | ( | a2dp_xq_status_t * | out | ) |
| esp_err_t a2dp_xq_init | ( | const a2dp_xq_config_t * | cfg | ) |
Start the controller (BR/EDR only, the BLE memory is released), Bluedroid, A2DP source and AVRCP.
Takes about 100 KB of internal RAM. ESP_ERR_NOT_SUPPORTED when Bluetooth Classic or A2DP is disabled in sdkconfig.
| bool a2dp_xq_is_initialized | ( | void | ) |
| void a2dp_xq_pause | ( | bool | paused | ) |
Pause keeps the queued audio; after 5 s of pause the stream is suspended so the headphones can sleep their decoder.
| void a2dp_xq_scan | ( | bool | start | ) |
Inquiry for about 10 s; A2DP_XQ_EVENT_DEVICE_FOUND per device (audio devices only).
| void a2dp_xq_set_volume_db | ( | float | db | ) |
Output volume in dB (<= 0).
Headphones with AVRCP absolute volume get it as SetAbsoluteVolume and play at their own gain; for other headphones the library attenuates in its 16-bit conversion. Their own volume changes arrive as A2DP_XQ_REMOTE_VOLUME_ABS.
| esp_err_t a2dp_xq_set_xq_allowed | ( | const char * | addr, |
| bool | allowed | ||
| ) |
Allow or forbid SBC-XQ for one device (kept in state_dir); takes effect on the next connection.
Allowing again also clears an earlier failure verdict.
| esp_err_t a2dp_xq_start | ( | void | ) |
Open the audio path: the stream to the headphones starts as soon as they are connected.
| void a2dp_xq_stop | ( | void | ) |
Close the audio path (queued audio is dropped) and suspend the stream.
| bool a2dp_xq_supported | ( | void | ) |
True when this build can negotiate SBC-XQ (ESP-IDF >= 6.0 with the internal SBC encoder).
| uint8_t a2dp_xq_volume_from_db | ( | float | db | ) |
| float a2dp_xq_volume_to_db | ( | int | v127 | ) |
AVRCP absolute volume (0..127) <-> dB: 127 = 0 dB, 1..127 span 60 dB in equal steps, 0 = mute.
| int32_t a2dp_xq_write_q31 | ( | const int32_t * | pcm, |
| uint32_t | frames, | ||
| uint32_t | timeout_ms | ||
| ) |
Same from left-justified 32-bit samples (24-bit audio in the top bits): reduced to 16 bits with TPDF dither, so quiet passages keep their resolution.
| int32_t a2dp_xq_write_s16 | ( | const int16_t * | pcm, |
| uint32_t | frames, | ||
| uint32_t | timeout_ms | ||
| ) |
Queue interleaved stereo frames at A2DP_XQ_SAMPLE_RATE.
Blocks up to timeout_ms while the FIFO is full (it drains at the real-time rate while the stream runs). Returns the frames accepted (may be fewer than requested) or -1 when the audio path is not started.