Skip to content

Commit

Permalink
Bluetooth: BAP: Shell: Add USB out support for the BAP shell
Browse files Browse the repository at this point in the history
Add USB out support for the BAP shell, so that decoded LC3
data can be sent to the host (e.g. a PC).

Signed-off-by: Emil Gydesen <[email protected]>
  • Loading branch information
Thalley committed Feb 29, 2024
1 parent 1848cf1 commit 6d5a72c
Show file tree
Hide file tree
Showing 6 changed files with 360 additions and 41 deletions.
3 changes: 3 additions & 0 deletions subsys/bluetooth/audio/shell/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ zephyr_library_sources_ifdef(
CONFIG_BT_BAP_STREAM
bap.c
)
if (CONFIG_BT_AUDIO_RX AND CONFIG_LIBLC3 AND CONFIG_USB_DEVICE_AUDIO)
zephyr_library_sources(bap_usb.c)
endif()
zephyr_library_sources_ifdef(
CONFIG_BT_BAP_SCAN_DELEGATOR
bap_scan_delegator.c
Expand Down
30 changes: 30 additions & 0 deletions subsys/bluetooth/audio/shell/audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@

#include "shell/bt.h"

#define MAX_CODEC_FRAMES_PER_SDU 2

extern struct bt_csip_set_member_svc_inst *svc_inst;

ssize_t audio_ad_data_add(struct bt_data *data, const size_t data_size, const bool discoverable,
Expand All @@ -43,6 +45,12 @@ size_t pbp_ad_data_add(struct bt_data data[], size_t data_size);

#if defined(CONFIG_LIBLC3)
#include "lc3.h"

#define USB_SAMPLE_RATE 48000U
#define LC3_MAX_SAMPLE_RATE 48000
#define LC3_MAX_FRAME_DURATION_US 10000
#define LC3_MAX_NUM_SAMPLES_MONO ((LC3_MAX_FRAME_DURATION_US * LC3_MAX_SAMPLE_RATE) / USEC_PER_SEC)

Check warning on line 52 in subsys/bluetooth/audio/shell/audio.h

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LONG_LINE

subsys/bluetooth/audio/shell/audio.h:52 line length of 101 exceeds 100 columns
#define LC3_MAX_NUM_SAMPLES_STEREO (LC3_MAX_NUM_SAMPLES_MONO * 2)
#endif /* CONFIG_LIBLC3 */

#define LOCATION BT_AUDIO_LOCATION_FRONT_LEFT | BT_AUDIO_LOCATION_FRONT_RIGHT
Expand All @@ -62,6 +70,12 @@ struct named_lc3_preset {
const struct named_lc3_preset *bap_get_named_preset(bool is_unicast, enum bt_audio_dir dir,
const char *preset_arg);

int bap_usb_init(void);
void bap_usb_add_frame(enum bt_audio_location lc3_chan_allocation, const int16_t *frame,
size_t frame_size);
void bap_usb_clear_frames(void);
void bap_usb_send_frames(void);

#if defined(CONFIG_BT_BAP_UNICAST)

#define UNICAST_SERVER_STREAM_COUNT \
Expand Down Expand Up @@ -168,6 +182,22 @@ int cap_ac_unicast(const struct shell *sh, size_t argc, char **argv,
#endif /* CONFIG_BT_BAP_UNICAST_CLIENT */
#endif /* CONFIG_BT_BAP_UNICAST */

static inline uint8_t get_chan_cnt(enum bt_audio_location chan_allocation)
{
uint8_t cnt = 0U;

if (chan_allocation == BT_AUDIO_LOCATION_MONO_AUDIO) {
return 1;
}

while (chan_allocation != 0) {
cnt += chan_allocation & 1U;
chan_allocation >>= 1;
}

return cnt;
}

static inline void print_qos(const struct shell *sh, const struct bt_audio_codec_qos *qos)
{
#if defined(CONFIG_BT_BAP_BROADCAST_SOURCE) || defined(CONFIG_BT_BAP_UNICAST)
Expand Down
69 changes: 42 additions & 27 deletions subsys/bluetooth/audio/shell/bap.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,6 @@

#if defined(CONFIG_LIBLC3)

#define LC3_MAX_SAMPLE_RATE 48000
#define LC3_MAX_FRAME_DURATION_US 10000
#define LC3_MAX_NUM_SAMPLES ((LC3_MAX_FRAME_DURATION_US * LC3_MAX_SAMPLE_RATE) / USEC_PER_SEC)

static void clear_lc3_sine_data(struct bt_bap_stream *bap_stream);
static void lc3_decoder_stream_clear(struct shell_stream *sh_stream);

Expand Down Expand Up @@ -213,7 +209,7 @@ NET_BUF_POOL_FIXED_DEFINE(sine_tx_pool, CONFIG_BT_ISO_TX_BUF_COUNT, SINE_TX_POOL
#define AUDIO_VOLUME (INT16_MAX - 3000) /* codec does clipping above INT16_MAX - 3000 */
#define AUDIO_TONE_FREQUENCY_HZ 400

static int16_t lc3_tx_buf[LC3_MAX_NUM_SAMPLES];
static int16_t lc3_tx_buf[LC3_MAX_NUM_SAMPLES_MONO];
static lc3_encoder_t lc3_encoder;
static lc3_encoder_mem_48k_t lc3_encoder_mem;
static int lc3_encoder_freq_hz;
Expand Down Expand Up @@ -602,7 +598,7 @@ static int lc3_release(struct bt_bap_stream *stream, struct bt_bap_ascs_rsp *rsp

static const struct bt_audio_codec_cap lc3_codec_cap = BT_AUDIO_CODEC_CAP_LC3(
BT_AUDIO_CODEC_CAP_FREQ_ANY, BT_AUDIO_CODEC_CAP_DURATION_ANY,
BT_AUDIO_CODEC_CAP_CHAN_COUNT_SUPPORT(1, 2), 30, 240, 2, CONTEXT);
BT_AUDIO_CODEC_CAP_CHAN_COUNT_SUPPORT(1, 2), 30, 240, MAX_CODEC_FRAMES_PER_SDU, CONTEXT);

static const struct bt_bap_unicast_server_cb unicast_server_cb = {
.config = lc3_config,
Expand Down Expand Up @@ -2333,7 +2329,7 @@ static struct bt_le_scan_cb bap_scan_cb = {
static unsigned long recv_stats_interval = 100U;

#if defined(CONFIG_LIBLC3)
static int16_t lc3_rx_buf[LC3_MAX_NUM_SAMPLES];
static int16_t lc3_rx_buf[LC3_MAX_NUM_SAMPLES_MONO];
static lc3_decoder_mem_48k_t lc3_decoder_mem;
static K_SEM_DEFINE(lc3_decoder_sem, 0, 1); /* used as a signal */
static int lc3_decoder_frame_duration_us;
Expand Down Expand Up @@ -2366,7 +2362,7 @@ static int init_lc3_decoder(const struct shell_stream *sh_stream)
sh_stream->lc3_frame_duration_us, sh_stream->lc3_freq_hz);
/* Create the encoder instance. This shall complete before stream_started() is called. */
lc3_decoder = lc3_setup_decoder(sh_stream->lc3_frame_duration_us, sh_stream->lc3_freq_hz,
0, /* No resampling */
IS_ENABLED(CONFIG_USB_DEVICE_AUDIO) ? USB_SAMPLE_RATE : 0,
&lc3_decoder_mem);
if (lc3_decoder == NULL) {
shell_error(ctx_shell, "Failed to setup LC3 encoder - wrong parameters?\n");
Expand Down Expand Up @@ -2463,12 +2459,44 @@ static void do_lc3_decode(struct shell_stream *sh_stream)
octets_per_frame * frame_cnt, buf->len);

net_buf_unref(buf);
if (IS_ENABLED(CONFIG_USB_DEVICE_AUDIO)) {
bap_usb_clear_frames();
}

return;
}

if (IS_ENABLED(CONFIG_USB_DEVICE_AUDIO)) {
const bool has_left = (sh_stream->lc3_chan_allocation &
BT_AUDIO_LOCATION_FRONT_LEFT) != 0;
const bool has_right = (sh_stream->lc3_chan_allocation &
BT_AUDIO_LOCATION_FRONT_RIGHT) != 0;
const bool is_mono = sh_stream->lc3_chan_allocation ==
BT_AUDIO_LOCATION_MONO_AUDIO;
const bool is_left = j == 0 && has_left;
const bool is_right = has_right && (j == 0 || (j == 1 && has_left));
enum bt_audio_location chan_alloc;

if (is_left) {
chan_alloc = BT_AUDIO_LOCATION_FRONT_LEFT;
} else if (is_right) {
chan_alloc = BT_AUDIO_LOCATION_FRONT_RIGHT;
} else if (is_mono) {
chan_alloc = BT_AUDIO_LOCATION_MONO_AUDIO;
} else {
/* Not suitable for USB */
continue;
}

bap_usb_add_frame(chan_alloc, lc3_rx_buf, sizeof(lc3_rx_buf));
}
}
}

if (IS_ENABLED(CONFIG_USB_DEVICE_AUDIO)) {
bap_usb_send_frames();
}

sh_stream->decoded_cnt++;

net_buf_unref(buf);
Expand Down Expand Up @@ -2610,24 +2638,6 @@ static void stream_enabled_cb(struct bt_bap_stream *stream)
}
}

#if defined(CONFIG_LIBLC3)
static uint8_t get_chan_cnt(enum bt_audio_location chan_allocation)
{
uint8_t cnt = 0U;

if (chan_allocation == BT_AUDIO_LOCATION_MONO_AUDIO) {
return 1;
}

while (chan_allocation != 0) {
cnt += chan_allocation & 1U;
chan_allocation >>= 1;
}

return cnt;
}
#endif /* CONFIG_LIBLC3 */

static void stream_started_cb(struct bt_bap_stream *bap_stream)
{
struct shell_stream *sh_stream = shell_stream_from_bap_stream(bap_stream);
Expand Down Expand Up @@ -3368,13 +3378,18 @@ static int cmd_init(const struct shell *sh, size_t argc, char *argv[])
#if defined(CONFIG_LIBLC3) && defined(CONFIG_BT_AUDIO_RX)
static K_KERNEL_STACK_DEFINE(lc3_decoder_thread_stack, 4096);
/* make it slightly lower priority than the RX thread */
int lc3_decoder_thread_prio = K_PRIO_COOP(CONFIG_BT_RX_PRIO + 1);
int lc3_decoder_thread_prio = K_PRIO_PREEMPT(CONFIG_BT_RX_PRIO + 1);
static struct k_thread lc3_decoder_thread;

k_thread_create(&lc3_decoder_thread, lc3_decoder_thread_stack,
K_KERNEL_STACK_SIZEOF(lc3_decoder_thread_stack), lc3_decoder_thread_func,
NULL, NULL, NULL, lc3_decoder_thread_prio, 0, K_NO_WAIT);
k_thread_name_set(&lc3_decoder_thread, "LC3 Decode");

if (IS_ENABLED(CONFIG_USB_DEVICE_AUDIO)) {
err = bap_usb_init();
__ASSERT(err == 0, "Failed to enable USB: %d", err);
}
#endif /* CONFIG_LIBLC3 && CONFIG_BT_AUDIO_RX */

initialized = true;
Expand Down
Loading

0 comments on commit 6d5a72c

Please sign in to comment.