samples: Add USB Audio to broadcast audio source
Adds support for using a connected host to broadcast audio via USB Audio. Offload LC3 encoding to separate thread. Signed-off-by: Lars Knudsen <LAKD@demant.com>
This commit is contained in:
parent
1fbcccd2fc
commit
78714b193a
5 changed files with 298 additions and 81 deletions
|
@ -28,4 +28,13 @@ config ENABLE_LC3
|
|||
select LIBLC3
|
||||
select FPU
|
||||
|
||||
config USE_USB_AUDIO_INPUT
|
||||
bool "Use USB Audio as input"
|
||||
# By default, use the USB Audio path is disabled.
|
||||
default n
|
||||
depends on ENABLE_LC3
|
||||
select USB_DEVICE_STACK
|
||||
select USB_DEVICE_AUDIO
|
||||
select RING_BUFFER
|
||||
|
||||
source "Kconfig.zephyr"
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
# The LC3 codec uses a large amount of stack. This app runs the codec in the work-queue, hence
|
||||
# inctease stack size for that thread.
|
||||
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096
|
||||
CONFIG_MAIN_STACK_SIZE=4096
|
||||
|
||||
# Use USB Audio as input
|
||||
CONFIG_USE_USB_AUDIO_INPUT=y
|
||||
CONFIG_USB_DEVICE_PRODUCT="Zephyr Broadcast Source"
|
||||
|
||||
# Two streams in one subgroup (stereo)
|
||||
CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT=1
|
||||
|
|
|
@ -1,4 +1 @@
|
|||
# The LC3 codec uses a large amount of stack. This app runs the codec in the work-queue, hence
|
||||
# inctease stack size for that thread.
|
||||
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096
|
||||
CONFIG_MAIN_STACK_SIZE=4096
|
||||
|
|
|
@ -13,5 +13,3 @@ CONFIG_BT_ISO_TX_BUF_COUNT=4
|
|||
CONFIG_BT_ISO_TX_MTU=60
|
||||
|
||||
CONFIG_BT_DEVICE_NAME="Broadcast Audio Source"
|
||||
|
||||
CONFIG_BT_TINYCRYPT_ECC=y
|
||||
|
|
|
@ -35,19 +35,93 @@ BUILD_ASSERT(CONFIG_BT_ISO_TX_BUF_COUNT >= TOTAL_BUF_NEEDED,
|
|||
#if defined(CONFIG_BAP_BROADCAST_16_2_1)
|
||||
|
||||
static struct bt_bap_lc3_preset preset_active = BT_BAP_LC3_BROADCAST_PRESET_16_2_1(
|
||||
BT_AUDIO_LOCATION_FRONT_LEFT, BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED);
|
||||
BT_AUDIO_LOCATION_FRONT_LEFT | BT_AUDIO_LOCATION_FRONT_RIGHT,
|
||||
BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED);
|
||||
|
||||
#define BROADCAST_SAMPLE_RATE 16000
|
||||
|
||||
#elif defined(CONFIG_BAP_BROADCAST_24_2_1)
|
||||
|
||||
static struct bt_bap_lc3_preset preset_active = BT_BAP_LC3_BROADCAST_PRESET_24_2_1(
|
||||
BT_AUDIO_LOCATION_FRONT_LEFT, BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED);
|
||||
BT_AUDIO_LOCATION_FRONT_LEFT | BT_AUDIO_LOCATION_FRONT_RIGHT,
|
||||
BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED);
|
||||
|
||||
#define BROADCAST_SAMPLE_RATE 24000
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BAP_BROADCAST_16_2_1)
|
||||
#define MAX_SAMPLE_RATE 16000
|
||||
#elif defined(CONFIG_BAP_BROADCAST_24_2_1)
|
||||
#define MAX_SAMPLE_RATE 24000
|
||||
#endif
|
||||
#define MAX_FRAME_DURATION_US 10000
|
||||
#define MAX_NUM_SAMPLES ((MAX_FRAME_DURATION_US * MAX_SAMPLE_RATE) / USEC_PER_SEC)
|
||||
|
||||
#if defined(CONFIG_LIBLC3)
|
||||
#include "lc3.h"
|
||||
|
||||
#if defined(CONFIG_USB_DEVICE_AUDIO)
|
||||
#include <zephyr/usb/usb_device.h>
|
||||
#include <zephyr/usb/class/usb_audio.h>
|
||||
#include <zephyr/sys/ring_buffer.h>
|
||||
|
||||
/* USB Audio Data is downsampled from 48kHz to match broadcast preset when receiving data */
|
||||
#define USB_SAMPLE_RATE 48000
|
||||
#define USB_DOWNSAMPLE_RATE BROADCAST_SAMPLE_RATE
|
||||
#define USB_FRAME_DURATION_US 1000
|
||||
#define USB_NUM_SAMPLES ((USB_FRAME_DURATION_US * USB_DOWNSAMPLE_RATE) / USEC_PER_SEC)
|
||||
#define USB_BYTES_PER_SAMPLE 2
|
||||
#define USB_CHANNELS 2
|
||||
|
||||
#define RING_BUF_USB_FRAMES 20
|
||||
#define AUDIO_RING_BUF_BYTES USB_NUM_SAMPLES * USB_BYTES_PER_SAMPLE * RING_BUF_USB_FRAMES
|
||||
#else /* !defined(CONFIG_USB_DEVICE_AUDIO) */
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#define AUDIO_VOLUME (INT16_MAX - 3000) /* codec does clipping above INT16_MAX - 3000 */
|
||||
#define AUDIO_TONE_FREQUENCY_HZ 400
|
||||
|
||||
/**
|
||||
* Use the math lib to generate a sine-wave using 16 bit samples into a buffer.
|
||||
*
|
||||
* @param buf Destination buffer
|
||||
* @param length_us Length of the buffer in microseconds
|
||||
* @param frequency_hz frequency in Hz
|
||||
* @param sample_rate_hz sample-rate in Hz.
|
||||
*/
|
||||
static void fill_audio_buf_sin(int16_t *buf, int length_us, int frequency_hz, int sample_rate_hz)
|
||||
{
|
||||
const int sine_period_samples = sample_rate_hz / frequency_hz;
|
||||
const unsigned int num_samples = (length_us * sample_rate_hz) / USEC_PER_SEC;
|
||||
const float step = 2 * 3.1415f / sine_period_samples;
|
||||
|
||||
for (unsigned int i = 0; i < num_samples; i++) {
|
||||
const float sample = sin(i * step);
|
||||
|
||||
buf[i] = (int16_t)(AUDIO_VOLUME * sample);
|
||||
}
|
||||
}
|
||||
#endif /* defined(CONFIG_USB_DEVICE_AUDIO) */
|
||||
#endif /* defined(CONFIG_LIBLC3) */
|
||||
|
||||
static struct broadcast_source_stream {
|
||||
struct bt_bap_stream stream;
|
||||
uint16_t seq_num;
|
||||
size_t sent_cnt;
|
||||
#if defined(CONFIG_LIBLC3)
|
||||
lc3_encoder_t lc3_encoder;
|
||||
#if defined(CONFIG_BAP_BROADCAST_16_2_1)
|
||||
lc3_encoder_mem_16k_t lc3_encoder_mem;
|
||||
#elif defined(CONFIG_BAP_BROADCAST_24_2_1)
|
||||
lc3_encoder_mem_48k_t lc3_encoder_mem;
|
||||
#endif
|
||||
#if defined(CONFIG_USB_DEVICE_AUDIO)
|
||||
struct ring_buf audio_ring_buf;
|
||||
uint8_t _ring_buffer_memory[AUDIO_RING_BUF_BYTES];
|
||||
#endif /* defined(CONFIG_USB_DEVICE_AUDIO) */
|
||||
#endif /* defined(CONFIG_LIBLC3) */
|
||||
} streams[CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT];
|
||||
static struct bt_bap_broadcast_source *broadcast_source;
|
||||
|
||||
|
@ -55,10 +129,8 @@ NET_BUF_POOL_FIXED_DEFINE(tx_pool,
|
|||
TOTAL_BUF_NEEDED,
|
||||
BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU),
|
||||
CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL);
|
||||
#define MAX_SAMPLE_RATE 16000
|
||||
#define MAX_FRAME_DURATION_US 10000
|
||||
#define MAX_NUM_SAMPLES ((MAX_FRAME_DURATION_US * MAX_SAMPLE_RATE) / USEC_PER_SEC)
|
||||
static int16_t mock_data[MAX_NUM_SAMPLES];
|
||||
|
||||
static int16_t send_pcm_data[MAX_NUM_SAMPLES];
|
||||
static uint16_t seq_num;
|
||||
static bool stopping;
|
||||
|
||||
|
@ -68,17 +140,80 @@ static K_SEM_DEFINE(sem_stopped, 0U, ARRAY_SIZE(streams));
|
|||
#define BROADCAST_SOURCE_LIFETIME 120U /* seconds */
|
||||
|
||||
#if defined(CONFIG_LIBLC3)
|
||||
|
||||
#include "lc3.h"
|
||||
|
||||
static lc3_encoder_t lc3_encoder;
|
||||
static lc3_encoder_mem_16k_t lc3_encoder_mem;
|
||||
static int freq_hz;
|
||||
static int frame_duration_us;
|
||||
static int frames_per_sdu;
|
||||
static int octets_per_frame;
|
||||
|
||||
static void init_lc3(void)
|
||||
static K_SEM_DEFINE(lc3_encoder_sem, 0U, ARRAY_SIZE(streams));
|
||||
#endif
|
||||
|
||||
static void send_data(struct broadcast_source_stream *source_stream)
|
||||
{
|
||||
struct bt_bap_stream *stream = &source_stream->stream;
|
||||
struct net_buf *buf;
|
||||
int ret;
|
||||
|
||||
if (stopping) {
|
||||
return;
|
||||
}
|
||||
|
||||
buf = net_buf_alloc(&tx_pool, K_FOREVER);
|
||||
if (buf == NULL) {
|
||||
printk("Could not allocate buffer when sending on %p\n",
|
||||
stream);
|
||||
return;
|
||||
}
|
||||
|
||||
net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE);
|
||||
#if defined(CONFIG_LIBLC3)
|
||||
uint8_t lc3_encoded_buffer[preset_active.qos.sdu];
|
||||
|
||||
if (source_stream->lc3_encoder == NULL) {
|
||||
printk("LC3 encoder not setup, cannot encode data.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_USB_DEVICE_AUDIO)
|
||||
uint32_t size = ring_buf_get(&source_stream->audio_ring_buf,
|
||||
(uint8_t *)send_pcm_data, sizeof(send_pcm_data));
|
||||
|
||||
if (size < sizeof(send_pcm_data)) {
|
||||
const size_t padding_size = sizeof(send_pcm_data) - size;
|
||||
|
||||
printk("Not enough bytes ready, padding %d!\n", padding_size);
|
||||
memset(&((uint8_t *)send_pcm_data)[size], 0, padding_size);
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = lc3_encode(source_stream->lc3_encoder, LC3_PCM_FORMAT_S16,
|
||||
send_pcm_data, 1, octets_per_frame, lc3_encoded_buffer);
|
||||
if (ret == -1) {
|
||||
printk("LC3 encoder failed - wrong parameters?: %d", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
net_buf_add_mem(buf, lc3_encoded_buffer, preset_active.qos.sdu);
|
||||
#else
|
||||
net_buf_add_mem(buf, send_pcm_data, preset_active.qos.sdu);
|
||||
#endif /* defined(CONFIG_LIBLC3) */
|
||||
|
||||
ret = bt_bap_stream_send(stream, buf, source_stream->seq_num++, BT_ISO_TIMESTAMP_NONE);
|
||||
if (ret < 0) {
|
||||
/* This will end broadcasting on this stream. */
|
||||
printk("Unable to broadcast data on %p: %d\n", stream, ret);
|
||||
net_buf_unref(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
source_stream->sent_cnt++;
|
||||
if ((source_stream->sent_cnt % 1000U) == 0U) {
|
||||
printk("Stream %p: Sent %u total ISO packets\n", stream, source_stream->sent_cnt);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_LIBLC3)
|
||||
static void init_lc3_thread(void *arg1, void *arg2, void *arg3)
|
||||
{
|
||||
const struct bt_audio_codec_cfg *codec_cfg = &preset_active.codec_cfg;
|
||||
int ret;
|
||||
|
@ -116,14 +251,95 @@ static void init_lc3(void)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Create the encoder instance. This shall complete before stream_started() is called. */
|
||||
lc3_encoder = lc3_setup_encoder(frame_duration_us, freq_hz, 0, /* No resampling */
|
||||
&lc3_encoder_mem);
|
||||
#if !defined(CONFIG_USB_DEVICE_AUDIO)
|
||||
/* If USB is not used as a sound source, generate a sine wave */
|
||||
fill_audio_buf_sin(send_pcm_data, frame_duration_us, AUDIO_TONE_FREQUENCY_HZ, freq_hz);
|
||||
#endif
|
||||
|
||||
if (lc3_encoder == NULL) {
|
||||
printk("ERROR: Failed to setup LC3 encoder - wrong parameters?\n");
|
||||
/* Create the encoder instance. This shall complete before stream_started() is called. */
|
||||
for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) {
|
||||
printk("Initializing lc3 encoder for stream %zu\n", i);
|
||||
streams[i].lc3_encoder = lc3_setup_encoder(frame_duration_us, freq_hz,
|
||||
0, &streams[i].lc3_encoder_mem);
|
||||
|
||||
if (streams[i].lc3_encoder == NULL) {
|
||||
printk("ERROR: Failed to setup LC3 encoder - wrong parameters?\n");
|
||||
}
|
||||
}
|
||||
|
||||
while (true) {
|
||||
for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) {
|
||||
k_sem_take(&lc3_encoder_sem, K_FOREVER);
|
||||
}
|
||||
for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) {
|
||||
send_data(&streams[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define LC3_ENCODER_STACK_SIZE 4 * 4096
|
||||
#define LC3_ENCODER_PRIORITY 5
|
||||
|
||||
K_THREAD_DEFINE(encoder, LC3_ENCODER_STACK_SIZE, init_lc3_thread,
|
||||
NULL, NULL, NULL, LC3_ENCODER_PRIORITY, 0, -1);
|
||||
|
||||
#if defined(CONFIG_USB_DEVICE_AUDIO)
|
||||
static void data_received(const struct device *dev,
|
||||
struct net_buf *buffer,
|
||||
size_t size)
|
||||
{
|
||||
static int count;
|
||||
int16_t *pcm;
|
||||
int nsamples, ratio;
|
||||
int16_t usb_pcm_data[USB_CHANNELS][USB_NUM_SAMPLES];
|
||||
|
||||
if (!buffer) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!size) {
|
||||
net_buf_unref(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
pcm = (int16_t *)net_buf_pull_mem(buffer, size);
|
||||
|
||||
/* 'size' is in bytes, containing 1ms, 48kHz, stereo, 2 bytes per sample.
|
||||
* Take left channel and do a simple downsample to 16kHz/24Khz
|
||||
* matching the broadcast preset.
|
||||
*/
|
||||
|
||||
ratio = USB_SAMPLE_RATE / USB_DOWNSAMPLE_RATE;
|
||||
nsamples = size / (sizeof(int16_t) * USB_CHANNELS * ratio);
|
||||
for (size_t i = 0, j = 0; i < nsamples; i++, j += USB_CHANNELS * ratio) {
|
||||
usb_pcm_data[0][i] = pcm[j];
|
||||
usb_pcm_data[1][i] = pcm[j + 1];
|
||||
}
|
||||
|
||||
for (size_t i = 0U; i < MIN(ARRAY_SIZE(streams), 2); i++) {
|
||||
const uint32_t size_put = ring_buf_put(&(streams[i].audio_ring_buf),
|
||||
(uint8_t *)(usb_pcm_data[i]), nsamples * USB_BYTES_PER_SAMPLE);
|
||||
if (size_put < nsamples * USB_BYTES_PER_SAMPLE) {
|
||||
printk("Not enough room for samples in %s buffer: %u < %u, total capacity: %u\n",
|
||||
i == 0 ? "left" : "right",
|
||||
size_put,
|
||||
nsamples * USB_BYTES_PER_SAMPLE,
|
||||
ring_buf_capacity_get(&(streams[i].audio_ring_buf)));
|
||||
}
|
||||
}
|
||||
|
||||
count++;
|
||||
if ((count % 1000) == 0) {
|
||||
printk("USB Data received (count = %d)\n", count);
|
||||
}
|
||||
|
||||
net_buf_unref(buffer);
|
||||
}
|
||||
|
||||
static const struct usb_audio_ops ops = {
|
||||
.data_received_cb = data_received
|
||||
};
|
||||
#endif /* defined(CONFIG_USB_DEVICE_AUDIO) */
|
||||
#endif /* defined(CONFIG_LIBLC3) */
|
||||
|
||||
static void stream_started_cb(struct bt_bap_stream *stream)
|
||||
|
@ -143,57 +359,15 @@ static void stream_stopped_cb(struct bt_bap_stream *stream, uint8_t reason)
|
|||
|
||||
static void stream_sent_cb(struct bt_bap_stream *stream)
|
||||
{
|
||||
#if defined(CONFIG_LIBLC3)
|
||||
k_sem_give(&lc3_encoder_sem);
|
||||
#else
|
||||
/* If no LC3 encoder is used, just send mock data directly */
|
||||
struct broadcast_source_stream *source_stream =
|
||||
CONTAINER_OF(stream, struct broadcast_source_stream, stream);
|
||||
struct net_buf *buf;
|
||||
int ret;
|
||||
|
||||
if (stopping) {
|
||||
return;
|
||||
}
|
||||
|
||||
buf = net_buf_alloc(&tx_pool, K_FOREVER);
|
||||
if (buf == NULL) {
|
||||
printk("Could not allocate buffer when sending on %p\n",
|
||||
stream);
|
||||
return;
|
||||
}
|
||||
|
||||
net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE);
|
||||
#if defined(CONFIG_LIBLC3)
|
||||
int lc3_ret;
|
||||
uint8_t lc3_encoder_buffer[preset_active.qos.sdu];
|
||||
|
||||
if (lc3_encoder == NULL) {
|
||||
printk("LC3 encoder not setup, cannot encode data.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
lc3_ret = lc3_encode(lc3_encoder, LC3_PCM_FORMAT_S16, mock_data, 1, octets_per_frame,
|
||||
lc3_encoder_buffer);
|
||||
|
||||
if (lc3_ret == -1) {
|
||||
printk("LC3 encoder failed - wrong parameters?: %d", lc3_ret);
|
||||
return;
|
||||
}
|
||||
|
||||
net_buf_add_mem(buf, lc3_encoder_buffer, preset_active.qos.sdu);
|
||||
#else
|
||||
net_buf_add_mem(buf, mock_data, preset_active.qos.sdu);
|
||||
#endif /* defined(CONFIG_LIBLC3) */
|
||||
|
||||
ret = bt_bap_stream_send(stream, buf, source_stream->seq_num++, BT_ISO_TIMESTAMP_NONE);
|
||||
if (ret < 0) {
|
||||
/* This will end broadcasting on this stream. */
|
||||
printk("Unable to broadcast data on %p: %d\n", stream, ret);
|
||||
net_buf_unref(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
source_stream->sent_cnt++;
|
||||
if ((source_stream->sent_cnt % 1000U) == 0U) {
|
||||
printk("Stream %p: Sent %u total ISO packets\n", stream, source_stream->sent_cnt);
|
||||
}
|
||||
send_data(source_stream);
|
||||
#endif
|
||||
}
|
||||
|
||||
static struct bt_bap_stream_ops stream_ops = {
|
||||
|
@ -210,10 +384,12 @@ static int setup_broadcast_source(struct bt_bap_broadcast_source **source)
|
|||
subgroup_param[CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT];
|
||||
struct bt_bap_broadcast_source_param create_param;
|
||||
const size_t streams_per_subgroup = ARRAY_SIZE(stream_params) / ARRAY_SIZE(subgroup_param);
|
||||
uint8_t left[] = {BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_CONFIG_LC3_CHAN_ALLOC,
|
||||
BT_BYTES_LIST_LE32(BT_AUDIO_LOCATION_FRONT_LEFT))};
|
||||
uint8_t right[] = {BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_CONFIG_LC3_CHAN_ALLOC,
|
||||
BT_BYTES_LIST_LE32(BT_AUDIO_LOCATION_FRONT_RIGHT))};
|
||||
int err;
|
||||
|
||||
(void)memset(streams, 0, sizeof(streams));
|
||||
|
||||
for (size_t i = 0U; i < ARRAY_SIZE(subgroup_param); i++) {
|
||||
subgroup_param[i].params_count = streams_per_subgroup;
|
||||
subgroup_param[i].params = stream_params + i * streams_per_subgroup;
|
||||
|
@ -222,8 +398,8 @@ static int setup_broadcast_source(struct bt_bap_broadcast_source **source)
|
|||
|
||||
for (size_t j = 0U; j < ARRAY_SIZE(stream_params); j++) {
|
||||
stream_params[j].stream = &streams[j].stream;
|
||||
stream_params[j].data = NULL;
|
||||
stream_params[j].data_len = 0U;
|
||||
stream_params[j].data = j == 0 ? left : right;
|
||||
stream_params[j].data_len = j == 0 ? sizeof(left) : sizeof(right);
|
||||
bt_bap_stream_cb_register(stream_params[j].stream, &stream_ops);
|
||||
}
|
||||
|
||||
|
@ -258,13 +434,43 @@ int main(void)
|
|||
}
|
||||
printk("Bluetooth initialized\n");
|
||||
|
||||
for (size_t i = 0U; i < ARRAY_SIZE(mock_data); i++) {
|
||||
for (size_t i = 0U; i < ARRAY_SIZE(send_pcm_data); i++) {
|
||||
/* Initialize mock data */
|
||||
mock_data[i] = i;
|
||||
send_pcm_data[i] = i;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_LIBLC3)
|
||||
init_lc3();
|
||||
#if defined(CONFIG_USB_DEVICE_AUDIO)
|
||||
const struct device *hs_dev;
|
||||
|
||||
hs_dev = DEVICE_DT_GET(DT_NODELABEL(hs_0));
|
||||
|
||||
if (!device_is_ready(hs_dev)) {
|
||||
printk("Device USB Headset is not ready\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
printk("Found USB Headset Device\n");
|
||||
|
||||
(void)memset(streams, 0, sizeof(streams));
|
||||
|
||||
for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) {
|
||||
ring_buf_init(&(streams[i].audio_ring_buf),
|
||||
sizeof(streams[i]._ring_buffer_memory),
|
||||
streams[i]._ring_buffer_memory);
|
||||
printk("Initialized ring buf %zu: capacity: %u\n", i,
|
||||
ring_buf_capacity_get(&(streams[i].audio_ring_buf)));
|
||||
}
|
||||
|
||||
usb_audio_register(hs_dev, &ops);
|
||||
|
||||
err = usb_enable(NULL);
|
||||
if (err) {
|
||||
printk("Failed to enable USB");
|
||||
return 0;
|
||||
}
|
||||
#endif /* defined(CONFIG_USB_DEVICE_AUDIO) */
|
||||
k_thread_start(encoder);
|
||||
#endif /* defined(CONFIG_LIBLC3) */
|
||||
|
||||
while (true) {
|
||||
|
@ -372,10 +578,13 @@ int main(void)
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_LIBLC3) && defined(CONFIG_USB_DEVICE_AUDIO)
|
||||
/* Never stop streaming when using USB Audio as input */
|
||||
k_sleep(K_FOREVER);
|
||||
#endif /* defined(CONFIG_LIBLC3) && defined(CONFIG_USB_DEVICE_AUDIO) */
|
||||
printk("Waiting %u seconds before stopped\n",
|
||||
BROADCAST_SOURCE_LIFETIME);
|
||||
k_sleep(K_SECONDS(BROADCAST_SOURCE_LIFETIME));
|
||||
|
||||
printk("Stopping broadcast source\n");
|
||||
stopping = true;
|
||||
err = bt_bap_broadcast_source_stop(broadcast_source);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue