Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

samples: broadcast_config_tool: Verify lc3 header file #17497

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions applications/nrf5340_audio/src/modules/lc3_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,34 @@ LOG_MODULE_REGISTER(sd_card_lc3_file, CONFIG_MODULE_SD_CARD_LC3_FILE_LOG_LEVEL);

#define LC3_FILE_ID 0xCC1C

static void lc3_header_print(struct lc3_file_header *header)
{
if (header == NULL) {
LOG_ERR("Nullptr received");
rick1082 marked this conversation as resolved.
Show resolved Hide resolved
return;
}

LOG_DBG("File ID: 0x%04x", header->file_id);
LOG_DBG("Header size: %d", header->hdr_size);
LOG_DBG("Sample rate: %d Hz", header->sample_rate * 100);
LOG_DBG("Bit rate: %d bps", header->bit_rate * 100);
LOG_DBG("Channels: %d", header->channels);
LOG_DBG("Frame duration: %d us", header->frame_duration * 10);
rick1082 marked this conversation as resolved.
Show resolved Hide resolved
LOG_DBG("Num samples: %d", header->signal_len_lsb | (header->signal_len_msb << 16));
}

int lc3_header_get(struct lc3_file_ctx const *const file, struct lc3_file_header *header)
{
if ((file == NULL) || (header == NULL)) {
LOG_ERR("Nullptr received");
rick1082 marked this conversation as resolved.
Show resolved Hide resolved
return -EINVAL;
}

*header = file->lc3_header;

return 0;
}

int lc3_file_frame_get(struct lc3_file_ctx *file, uint8_t *buffer, size_t buffer_size)
{
int ret;
Expand Down Expand Up @@ -83,6 +111,9 @@ int lc3_file_open(struct lc3_file_ctx *file, const char *file_name)
return ret;
}

/* Debug: Print header */
lc3_header_print(&file->lc3_header);

if (file->lc3_header.file_id != LC3_FILE_ID) {
LOG_ERR("Invalid file ID: 0x%04x", file->lc3_header.file_id);
return -EINVAL;
Expand Down
11 changes: 11 additions & 0 deletions applications/nrf5340_audio/src/modules/lc3_file.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@ struct lc3_file_ctx {
uint32_t number_of_samples;
};

/**
* @brief Get the LC3 header from the file.
*
* @param[in] file Pointer to the file context.
* @param[out] header Pointer to the header structure to store the header.
*
* @retval -EINVAL Invalid file context.
* @retval 0 Success.
*/
int lc3_header_get(struct lc3_file_ctx const *const file, struct lc3_file_header *header);

/**
* @brief Get the next LC3 frame from the file.
*
Expand Down
58 changes: 58 additions & 0 deletions applications/nrf5340_audio/src/modules/lc3_streamer.c
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,64 @@ int lc3_streamer_next_frame_get(const uint8_t streamer_idx, const uint8_t **cons
return 0;
}

bool lc3_streamer_file_compatible_check(const char *const filename,
const struct lc3_stream_cfg *const cfg)
{
int ret;
bool result = true;

if (filename == NULL || cfg == NULL) {
LOG_ERR("NULL pointer received");
return false;
}

if (strlen(filename) > CONFIG_FS_FATFS_MAX_LFN - 1) {
LOG_ERR("Filename too long");
return false;
}

struct lc3_file_ctx file;

ret = lc3_file_open(&file, filename);
if (ret) {
LOG_ERR("Failed to open file %d", ret);
return false;
}

struct lc3_file_header header;

ret = lc3_header_get(&file, &header);
if (ret) {
LOG_WRN("Failed to get header %d", ret);
return false;
}

if ((header.sample_rate * 100) != cfg->sample_rate_hz) {
koffes marked this conversation as resolved.
Show resolved Hide resolved
LOG_WRN("Sample rate mismatch %d Hz != %d Hz", (header.sample_rate * 100),
cfg->sample_rate_hz);
result = false;
}

if ((header.bit_rate * 100) != cfg->bit_rate_bps) {
LOG_WRN("Bit rate mismatch %d bps != %d bps", (header.bit_rate * 100),
cfg->bit_rate_bps);
result = false;
}

if ((header.frame_duration * 10) != cfg->frame_duration_us) {
LOG_WRN("Frame duration mismatch %d us != %d us", (header.frame_duration * 10),
cfg->frame_duration_us);
result = false;
}

ret = lc3_file_close(&file);
if (ret) {
LOG_ERR("Failed to close file %d", ret);
}

return result;
}

int lc3_streamer_stream_register(const char *const filename, uint8_t *const streamer_idx,
const bool loop)
{
Expand Down
34 changes: 28 additions & 6 deletions applications/nrf5340_audio/src/modules/lc3_streamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,20 @@
#include <stdbool.h>
#include <sys/types.h>

struct lc3_stream_cfg {
koffes marked this conversation as resolved.
Show resolved Hide resolved
uint32_t sample_rate_hz;
uint32_t bit_rate_bps;
uint32_t frame_duration_us;
};

/**
* @brief Get the next frame for the stream.
*
* @details Populates a pointer to the buffer holding the next frame. This buffer is valid until
* the next call to this function. or stream is closed.
* @details Populates a pointer to the buffer holding the next frame. This buffer is valid until
* the next call to this function. or stream is closed.
*
* @param[in] streamer_idx Index of the streamer to get the next frame from.
* @param[out] frame_buffer Pointer to the buffer holding the next frame.
* @param[in] streamer_idx Index of the streamer to get the next frame from.
* @param[out] frame_buffer Pointer to the buffer holding the next frame.
*
* @retval 0 Success.
* @retval -EINVAL Invalid streamer index.
Expand All @@ -30,6 +36,22 @@
*/
int lc3_streamer_next_frame_get(const uint8_t streamer_idx, const uint8_t **const frame_buffer);

/**
* @brief Verify that the LC3 header matches the stream configuration.
*
* @details Verifies that the file is valid and can be used by the LC3 streamer.
* Since there is no standard header for LC3 files, the header might be different than
* what is defined in the struct lc3_file_header.
*
* @param[in] filename Name of the file to verify.
* @param[in] cfg Stream configuration to compare against.
*
* @retval true Success.
* @retval false Header is not matching the configuration.
*/
bool lc3_streamer_file_compatible_check(const char *const filename,
const struct lc3_stream_cfg *const cfg);

/**
* @brief Register a new stream that will be played by the LC3 streamer.
*
Expand Down Expand Up @@ -63,10 +85,10 @@ uint8_t lc3_streamer_num_active_streams(void);
* truncated.
*
* @param[in] streamer_idx Index of the streamer.
* @param[out] path Pointer for string to store filepath in.
* @param[out] path Pointer for string to store file path in.
* @param[in] path_len Length of string buffer.
*
* @retval -EINVAL Nullpointers or invalid index given.
* @retval -EINVAL Null pointers or invalid index given.
* @retval 0 Success.
*/
int lc3_streamer_file_path_get(const uint8_t streamer_idx, char *const path, const size_t path_len);
Expand Down
6 changes: 6 additions & 0 deletions samples/bluetooth/broadcast_config_tool/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ rsource "${ZEPHYR_NRF_MODULE_DIR}/applications/nrf5340_audio/src/utils/Kconfig"
config TRANSPORT_BIS
bool "Use BIS (Broadcast Isochronous Stream)"

config BROADCAST_CONFIG_TOOL
bool "Broadcast Configuration Tool"
depends on TRANSPORT_BIS
select EXPERIMENTAL
default y

menu "Logging"

module = MAIN
Expand Down
30 changes: 30 additions & 0 deletions samples/bluetooth/broadcast_config_tool/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1584,6 +1584,36 @@ static int cmd_file_select(const struct shell *shell, size_t argc, char **argv)
LOG_DBG("Selecting file %s for stream big: %d sub: %d bis: %d", file_name, big_index,
sub_index, bis_index);

struct bt_audio_codec_cfg *codec_cfg =
&broadcast_param[big_index].subgroups[sub_index].group_lc3_preset.codec_cfg;

struct lc3_stream_cfg cfg;

ret = le_audio_freq_hz_get(codec_cfg, &cfg.sample_rate_hz);
if (ret) {
shell_error(shell, "Failed to get frequency: %d", ret);
return ret;
}

ret = le_audio_duration_us_get(codec_cfg, &cfg.frame_duration_us);
if (ret) {
shell_error(shell, "Failed to get frame duration: %d", ret);
}

ret = le_audio_bitrate_get(codec_cfg, &cfg.bit_rate_bps);
if (ret) {
shell_error(shell, "Failed to get bitrate: %d", ret);
}

/* Verify that the file header matches the stream configurationn */
/* NOTE: This will not abort the streamer if the file is not valid, only give a warning */
bool header_valid = lc3_streamer_file_compatible_check(file_name, &cfg);

if (!header_valid) {
shell_warn(shell, "File header verification failed. File may not be compatible "
"with stream config.");
}

ret = lc3_streamer_stream_register(
file_name, &lc3_stream_infos[big_index][sub_index].lc3_streamer_idx[bis_index],
true);
Expand Down
Loading