|  | /* | 
|  | * Copyright 2024 NXP | 
|  | * | 
|  | * SPDX-License-Identifier: Apache-2.0 | 
|  | */ | 
|  |  | 
|  | #include <errno.h> | 
|  | #include <zephyr/libsbc/sbc.h> | 
|  |  | 
|  | #if defined(CONFIG_LIBSBC_ENCODER) | 
|  |  | 
|  | int sbc_setup_encoder(struct sbc_encoder *encoder, struct sbc_encoder_init_param *param) | 
|  | { | 
|  | SBC_ENC_PARAMS *encoder_params; | 
|  |  | 
|  | if (encoder == NULL) { | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | memset(encoder, 0, sizeof(struct sbc_encoder)); | 
|  |  | 
|  | encoder_params = &encoder->sbc_encoder_params; | 
|  |  | 
|  | encoder_params->s16ChannelMode = (int16_t)param->ch_mode; | 
|  | encoder_params->s16NumOfSubBands = (int16_t)param->subband; | 
|  | if (!encoder_params->s16NumOfSubBands) { | 
|  | return -EINVAL; | 
|  | } | 
|  | encoder_params->s16NumOfBlocks = (int16_t)param->blk_len; | 
|  | if (!encoder_params->s16NumOfBlocks) { | 
|  | return -EINVAL; | 
|  | } | 
|  | encoder_params->s16AllocationMethod = (int16_t)param->alloc_mthd; | 
|  | encoder_params->s16NumOfChannels = param->ch_num; | 
|  | if (!encoder_params->s16NumOfChannels) { | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | switch (param->samp_freq) { | 
|  | case 16000u: | 
|  | encoder_params->s16SamplingFreq = 0; | 
|  | break; | 
|  | case 32000u: | 
|  | encoder_params->s16SamplingFreq = 1; | 
|  | break; | 
|  | case 44100u: | 
|  | encoder_params->s16SamplingFreq = 2; | 
|  | break; | 
|  | case 48000u: | 
|  | encoder_params->s16SamplingFreq = 3; | 
|  | break; | 
|  | default: | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | encoder_params->u16BitRate = param->bit_rate; | 
|  |  | 
|  | SBC_Encoder_Init(encoder_params); | 
|  |  | 
|  | if (encoder_params->s16BitPool < param->min_bitpool) { | 
|  | /* need to increase the `param->bit_rate` */ | 
|  | return -EINVAL; | 
|  | } else if (encoder_params->s16BitPool > param->max_bitpool) { | 
|  | /* need to decrease the `param->bit_rate` */ | 
|  | return -EOVERFLOW; | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Encode a SBC frame | 
|  | */ | 
|  | uint32_t sbc_encode(struct sbc_encoder *encoder, const void *in_data, void *out_data) | 
|  | { | 
|  | uint32_t ret; | 
|  |  | 
|  | if ((encoder == NULL) || (in_data == NULL) || (out_data == NULL)) { | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | ret = SBC_Encode(&encoder->sbc_encoder_params, (int16_t *)in_data, out_data); | 
|  |  | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | int sbc_frame_samples(struct sbc_encoder *encoder) | 
|  | { | 
|  | if (encoder == NULL) { | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | return encoder->sbc_encoder_params.s16NumOfSubBands * | 
|  | encoder->sbc_encoder_params.s16NumOfBlocks; | 
|  | } | 
|  |  | 
|  | int sbc_frame_bytes(struct sbc_encoder *encoder) | 
|  | { | 
|  | if (encoder == NULL) { | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | return sbc_frame_samples(encoder) * 2 * | 
|  | (encoder->sbc_encoder_params.s16ChannelMode == SBC_CH_MODE_MONO ? 1 : 2); | 
|  | } | 
|  |  | 
|  | int sbc_frame_encoded_bytes(struct sbc_encoder *encoder) | 
|  | { | 
|  | int size = 4; | 
|  | int channel_num = 2; | 
|  | SBC_ENC_PARAMS *encoder_params; | 
|  |  | 
|  | if (encoder == NULL) { | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | encoder_params = &encoder->sbc_encoder_params; | 
|  |  | 
|  | if (encoder_params->s16ChannelMode == SBC_CH_MODE_MONO) { | 
|  | channel_num = 1; | 
|  | } | 
|  |  | 
|  | size += (4 * encoder_params->s16NumOfSubBands * channel_num) / 8; | 
|  | if ((encoder_params->s16ChannelMode == SBC_CH_MODE_MONO) || | 
|  | (encoder_params->s16ChannelMode == SBC_CH_MODE_DUAL_CHANNEL)) { | 
|  | size += ((encoder_params->s16NumOfBlocks * channel_num * | 
|  | encoder_params->s16BitPool + 7) / 8); | 
|  | } else if (encoder_params->s16ChannelMode == SBC_CH_MODE_STEREO) { | 
|  | size += ((encoder_params->s16NumOfBlocks * | 
|  | encoder_params->s16BitPool + 7) / 8); | 
|  | } else { | 
|  | size += ((encoder_params->s16NumOfSubBands + | 
|  | encoder_params->s16NumOfBlocks * | 
|  | encoder_params->s16BitPool + 7) / 8); | 
|  | } | 
|  |  | 
|  | return size; | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #if defined(CONFIG_LIBSBC_DECODER) | 
|  | /** | 
|  | * Setup decoder | 
|  | */ | 
|  | int sbc_setup_decoder(struct sbc_decoder *decoder) | 
|  | { | 
|  | OI_STATUS status; | 
|  |  | 
|  | if (decoder == NULL) { | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | memset(decoder, 0, sizeof(struct sbc_decoder)); | 
|  |  | 
|  | status = OI_CODEC_SBC_DecoderReset( | 
|  | &decoder->context, | 
|  | &decoder->context_data[0], | 
|  | sizeof(decoder->context_data), | 
|  | 2, 2, FALSE); | 
|  | if (!OI_SUCCESS(status)) { | 
|  | return -EIO; | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Decode a frame | 
|  | */ | 
|  | int sbc_decode(struct sbc_decoder *decoder, const void **in_data, uint32_t *in_size, | 
|  | void *out_data, uint32_t *out_size) | 
|  | { | 
|  | OI_STATUS status; | 
|  |  | 
|  | if (decoder == NULL || in_data == NULL || in_size == NULL || | 
|  | out_data == NULL || out_size == NULL) { | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | status = OI_CODEC_SBC_DecodeFrame(&decoder->context, | 
|  | (const OI_BYTE**)in_data, | 
|  | in_size, | 
|  | out_data, | 
|  | out_size); | 
|  | if (!OI_SUCCESS(status)) { | 
|  | return -EIO; | 
|  | } else { | 
|  | return 0; | 
|  | } | 
|  | } | 
|  | #endif |