diff --git a/lc3/include/sw_codec_lc3.h b/lc3/include/sw_codec_lc3.h index 08c32cfcf2..296c9d3ebb 100644 --- a/lc3/include/sw_codec_lc3.h +++ b/lc3/include/sw_codec_lc3.h @@ -98,6 +98,40 @@ int sw_codec_lc3_dec_run(uint8_t const *const lc3_data, uint16_t lc3_data_size, uint16_t pcm_data_buf_size, uint8_t audio_ch, void *const pcm_data, uint16_t *const pcm_data_wr_size, bool bad_frame); +/**@brief Calculates the number of encoded bytes of data required to decode a + * single frame for one channel. + * + * @param[in] pcm_sample_rate Sample rate in Hz (typ. 16000 or 48000). + * @param[in] bitrate_bps Bitrate of the coded stream. + * @param[in] framesize_us Frame size in microseconds. + * @param[out] enc_size Maximum bytes per coded frame. + * + * @note The return codes from Zephyr and LC3 may overlap. + * + * @return 0 on success, otherwise an error. + * Other errors. Refer to LC3 documentation. + */ +int sw_codec_lc3_enc_size_get(uint16_t pcm_sample_rate, + uint32_t bitrate_bps, uint16_t framesize_us, + size_t *enc_size); + +/**@brief Calculates the number of samples in bytes of data required to encode a + * single frame for one channel. + * + * @param[in] pcm_sample_rate Sample rate in Hz (typ. 16000 or 48000). + * @param[in] bit_depth Bit depth of generated PCM data. + * @param[in] framesize_us Frame size in microseconds. + * @param[out] dec_size Maximum bytes per decoded frame. + * + * @note The return codes from Zephyr and LC3 may overlap. + * + * @return 0 on success, otherwise an error. + * Other errors. Refer to LC3 documentation. + */ +int sw_codec_lc3_dec_size_get(uint16_t pcm_sample_rate, + uint8_t bit_depth, uint16_t framesize_us, + size_t *dec_size); + /**@brief Closes the LC3 encoder and frees allocated RAM * * @return 0 on success. -EALREADY if already un-initialized. @@ -110,12 +144,20 @@ int sw_codec_lc3_enc_uninit_all(void); */ int sw_codec_lc3_dec_uninit_all(void); -/**@brief Initializes the LC3 Codec +/**@brief Initializes the LC3 decoder and allocates required RAM * - * @note: For documentation, see LC3API.h (/codec/inc/LC3API.h) + * @param[in] pcm_sample_rate Sample rate in Hz (typ. 16000 or 48000) + * @param[in] pcm_bit_depth Output PCM bits per sample. + * @param[in] framesize_us Frame size in microseconds + * @param[in] num_channels Number of channels to initialize + * + * @note The return codes from Zephyr and LC3 may overlap. + * + * @return 0 on success. -EALREADY if already initialized. + * Other errors. Refer to LC3 documentation. */ -int sw_codec_lc3_init(uint8_t *sw_codec_lc3_buffer, uint32_t *sw_codec_lc3_buffer_size, - uint16_t framesize_us); +int sw_codec_lc3_dec_init(uint16_t pcm_sample_rate, uint8_t pcm_bit_depth, uint16_t framesize_us, + uint8_t num_channels); /**@brief Initializes the LC3 encoder and allocates required RAM * @@ -139,20 +181,12 @@ int sw_codec_lc3_enc_init(uint16_t pcm_sample_rate, uint8_t pcm_bit_depth, uint1 uint32_t enc_bitrate, uint8_t num_channels, uint16_t *const pcm_bytes_req); -/**@brief Initializes the LC3 decoder and allocates required RAM - * - * @param[in] pcm_sample_rate Sample rate in Hz (typ. 16000 or 48000) - * @param[in] pcm_bit_depth Output PCM bits per sample. - * @param[in] framesize_us Frame size in microseconds - * @param[in] num_channels Number of channels to initialize - * - * @note The return codes from Zephyr and LC3 may overlap. +/**@brief Initializes the LC3 Codec * - * @return 0 on success. -EALREADY if already initialized. - * Other errors. Refer to LC3 documentation. + * @note: For documentation, see LC3API.h (/codec/inc/LC3API.h) */ -int sw_codec_lc3_dec_init(uint16_t pcm_sample_rate, uint8_t pcm_bit_depth, uint16_t framesize_us, - uint8_t num_channels); +int sw_codec_lc3_init(uint8_t *sw_codec_lc3_buffer, uint32_t *sw_codec_lc3_buffer_size, + uint16_t framesize_us); /*! \} */ /* LC3_translation */ diff --git a/lc3/src/sw_codec_lc3.c b/lc3/src/sw_codec_lc3.c index 185df9c887..686edd11fd 100644 --- a/lc3/src/sw_codec_lc3.c +++ b/lc3/src/sw_codec_lc3.c @@ -138,6 +138,7 @@ int sw_codec_lc3_dec_run(uint8_t const *const lc3_data, uint16_t lc3_data_size, LOG_ERR("LC3 dec ch:%d is not initialized", audio_ch); return -EPERM; } + ret = LC3DecodeSessionData(dec_handle_ch[audio_ch], &LC3DecodeInput, &LC3DecodeOutput); if (ret) { return ret; @@ -157,6 +158,76 @@ int sw_codec_lc3_dec_run(uint8_t const *const lc3_data, uint16_t lc3_data_size, return 0; } +int sw_codec_lc3_enc_size_get(uint16_t pcm_sample_rate, uint32_t bitrate_bps, + uint16_t framesize_us, size_t *enc_size) +{ + int ret; + LC3FrameSize_t framesize; + + if (enc_size == NULL) { + LOG_ERR("encoded_size pointer is NULL"); + return -EINVAL; + } + + *enc_size = 0; + + switch (framesize_us) { + case 7500: + framesize = LC3FrameSize7_5Ms; + break; + case 10000: + framesize = LC3FrameSize10Ms; + break; + default: + LOG_ERR("Unsupported framesize: %d", framesize_us); + return -EINVAL; + } + + *enc_size = + LC3BitstreamBuffersize(pcm_sample_rate, bitrate_bps, framesize, &ret); + if (*enc_size == 0) { + LOG_ERR("Required coded bytes to LC3 instance is zero"); + return -EPERM; + } + + return 0; +} + +int sw_codec_lc3_dec_size_get(uint16_t pcm_sample_rate, uint8_t bit_depth, + uint16_t framesize_us, size_t *dec_size) +{ + int ret; + LC3FrameSize_t framesize; + + if (dec_size == NULL) { + LOG_ERR("decoded_size pointer is NULL"); + return -EINVAL; + } + + *dec_size = 0; + + switch (framesize_us) { + case 7500: + framesize = LC3FrameSize7_5Ms; + break; + case 10000: + framesize = LC3FrameSize10Ms; + break; + default: + LOG_ERR("Unsupported framesize: %d", framesize_us); + return -EINVAL; + } + + *dec_size = + LC3PCMBuffersize(pcm_sample_rate, bit_depth, framesize, &ret); + if (*dec_size == 0) { + LOG_ERR("Required un-coded bytes to LC3 instance is zero"); + return -EPERM; + } + + return 0; +} + int sw_codec_lc3_enc_uninit_all(void) { for (uint8_t i = 0; i < enc_num_instances; i++) { @@ -187,59 +258,10 @@ int sw_codec_lc3_dec_uninit_all(void) return 0; } -int sw_codec_lc3_init(uint8_t *sw_codec_lc3_buffer, uint32_t *sw_codec_lc3_buffer_size, - uint16_t framesize_us) +int sw_codec_lc3_dec_init(uint16_t pcm_sample_rate, uint8_t pcm_bit_depth, uint16_t framesize_us, + uint8_t num_channels) { int ret; - uint8_t enc_sample_rates = 0; - uint8_t dec_sample_rates = 0; - - /* Set unique session to 0 for using the default sharing memory setting. - * - * This could lead to higher heap consumption, but is able to manipulate - * different sample rate setting between encoder/decoder. - */ - uint8_t unique_session = 0; - - /* Check supported sample rates for encoder */ - if (IS_ENABLED(CONFIG_LC3_ENC_SAMPLE_RATE_8KHZ_SUPPORT)) { - enc_sample_rates |= LC3_SAMPLE_RATE_8_KHZ; - } - if (IS_ENABLED(CONFIG_LC3_ENC_SAMPLE_RATE_16KHZ_SUPPORT)) { - enc_sample_rates |= LC3_SAMPLE_RATE_16_KHZ; - } - if (IS_ENABLED(CONFIG_LC3_ENC_SAMPLE_RATE_24KHZ_SUPPORT)) { - enc_sample_rates |= LC3_SAMPLE_RATE_24_KHZ; - } - if (IS_ENABLED(CONFIG_LC3_ENC_SAMPLE_RATE_32KHZ_SUPPORT)) { - enc_sample_rates |= LC3_SAMPLE_RATE_32_KHZ; - } - if (IS_ENABLED(CONFIG_LC3_ENC_SAMPLE_RATE_441KHZ_SUPPORT)) { - enc_sample_rates |= LC3_SAMPLE_RATE_441_KHZ; - } - if (IS_ENABLED(CONFIG_LC3_ENC_SAMPLE_RATE_48KHZ_SUPPORT)) { - enc_sample_rates |= LC3_SAMPLE_RATE_48_KHZ; - } - - /* Check supported sample rates for decoder */ - if (IS_ENABLED(CONFIG_LC3_DEC_SAMPLE_RATE_8KHZ_SUPPORT)) { - dec_sample_rates |= LC3_SAMPLE_RATE_8_KHZ; - } - if (IS_ENABLED(CONFIG_LC3_DEC_SAMPLE_RATE_16KHZ_SUPPORT)) { - dec_sample_rates |= LC3_SAMPLE_RATE_16_KHZ; - } - if (IS_ENABLED(CONFIG_LC3_DEC_SAMPLE_RATE_24KHZ_SUPPORT)) { - dec_sample_rates |= LC3_SAMPLE_RATE_24_KHZ; - } - if (IS_ENABLED(CONFIG_LC3_DEC_SAMPLE_RATE_32KHZ_SUPPORT)) { - dec_sample_rates |= LC3_SAMPLE_RATE_32_KHZ; - } - if (IS_ENABLED(CONFIG_LC3_DEC_SAMPLE_RATE_441KHZ_SUPPORT)) { - dec_sample_rates |= LC3_SAMPLE_RATE_441_KHZ; - } - if (IS_ENABLED(CONFIG_LC3_DEC_SAMPLE_RATE_48KHZ_SUPPORT)) { - dec_sample_rates |= LC3_SAMPLE_RATE_48_KHZ; - } LC3FrameSize_t framesize; @@ -255,9 +277,21 @@ int sw_codec_lc3_init(uint8_t *sw_codec_lc3_buffer, uint32_t *sw_codec_lc3_buffe return -EINVAL; } - ret = LC3Initialize(enc_sample_rates, dec_sample_rates, framesize, unique_session, - sw_codec_lc3_buffer, sw_codec_lc3_buffer_size); - return ret; + for (uint8_t i = 0; i < num_channels; i++) { + if (dec_handle_ch[i]) { + LOG_ERR("LC3 dec ch: %d already initialized", i); + return -EALREADY; + } + dec_handle_ch[i] = LC3DecodeSessionOpen(pcm_sample_rate, pcm_bit_depth, framesize, + NULL, NULL, &ret); + if (ret) { + return ret; + } + } + + dec_num_instances = num_channels; + + return 0; } int sw_codec_lc3_enc_init(uint16_t pcm_sample_rate, uint8_t pcm_bit_depth, uint16_t framesize_us, @@ -314,10 +348,59 @@ int sw_codec_lc3_enc_init(uint16_t pcm_sample_rate, uint8_t pcm_bit_depth, uint1 return ret; } -int sw_codec_lc3_dec_init(uint16_t pcm_sample_rate, uint8_t pcm_bit_depth, uint16_t framesize_us, - uint8_t num_channels) +int sw_codec_lc3_init(uint8_t *sw_codec_lc3_buffer, uint32_t *sw_codec_lc3_buffer_size, + uint16_t framesize_us) { int ret; + uint8_t enc_sample_rates = 0; + uint8_t dec_sample_rates = 0; + + /* Set unique session to 0 for using the default sharing memory setting. + * + * This could lead to higher heap consumption, but is able to manipulate + * different sample rate setting between encoder/decoder. + */ + uint8_t unique_session = 0; + + /* Check supported sample rates for encoder */ + if (IS_ENABLED(CONFIG_LC3_ENC_SAMPLE_RATE_8KHZ_SUPPORT)) { + enc_sample_rates |= LC3_SAMPLE_RATE_8_KHZ; + } + if (IS_ENABLED(CONFIG_LC3_ENC_SAMPLE_RATE_16KHZ_SUPPORT)) { + enc_sample_rates |= LC3_SAMPLE_RATE_16_KHZ; + } + if (IS_ENABLED(CONFIG_LC3_ENC_SAMPLE_RATE_24KHZ_SUPPORT)) { + enc_sample_rates |= LC3_SAMPLE_RATE_24_KHZ; + } + if (IS_ENABLED(CONFIG_LC3_ENC_SAMPLE_RATE_32KHZ_SUPPORT)) { + enc_sample_rates |= LC3_SAMPLE_RATE_32_KHZ; + } + if (IS_ENABLED(CONFIG_LC3_ENC_SAMPLE_RATE_441KHZ_SUPPORT)) { + enc_sample_rates |= LC3_SAMPLE_RATE_441_KHZ; + } + if (IS_ENABLED(CONFIG_LC3_ENC_SAMPLE_RATE_48KHZ_SUPPORT)) { + enc_sample_rates |= LC3_SAMPLE_RATE_48_KHZ; + } + + /* Check supported sample rates for decoder */ + if (IS_ENABLED(CONFIG_LC3_DEC_SAMPLE_RATE_8KHZ_SUPPORT)) { + dec_sample_rates |= LC3_SAMPLE_RATE_8_KHZ; + } + if (IS_ENABLED(CONFIG_LC3_DEC_SAMPLE_RATE_16KHZ_SUPPORT)) { + dec_sample_rates |= LC3_SAMPLE_RATE_16_KHZ; + } + if (IS_ENABLED(CONFIG_LC3_DEC_SAMPLE_RATE_24KHZ_SUPPORT)) { + dec_sample_rates |= LC3_SAMPLE_RATE_24_KHZ; + } + if (IS_ENABLED(CONFIG_LC3_DEC_SAMPLE_RATE_32KHZ_SUPPORT)) { + dec_sample_rates |= LC3_SAMPLE_RATE_32_KHZ; + } + if (IS_ENABLED(CONFIG_LC3_DEC_SAMPLE_RATE_441KHZ_SUPPORT)) { + dec_sample_rates |= LC3_SAMPLE_RATE_441_KHZ; + } + if (IS_ENABLED(CONFIG_LC3_DEC_SAMPLE_RATE_48KHZ_SUPPORT)) { + dec_sample_rates |= LC3_SAMPLE_RATE_48_KHZ; + } LC3FrameSize_t framesize; @@ -333,19 +416,7 @@ int sw_codec_lc3_dec_init(uint16_t pcm_sample_rate, uint8_t pcm_bit_depth, uint1 return -EINVAL; } - for (uint8_t i = 0; i < num_channels; i++) { - if (dec_handle_ch[i]) { - LOG_ERR("LC3 dec ch: %d already initialized", i); - return -EALREADY; - } - dec_handle_ch[i] = LC3DecodeSessionOpen(pcm_sample_rate, pcm_bit_depth, framesize, - NULL, NULL, &ret); - if (ret) { - return ret; - } - } - - dec_num_instances = num_channels; - - return 0; + ret = LC3Initialize(enc_sample_rates, dec_sample_rates, framesize, unique_session, + sw_codec_lc3_buffer, sw_codec_lc3_buffer_size); + return ret; }