blob: 9be90dd3cffacc87b58dad5c3c540e2b1edac5d6 [file] [log] [blame] [edit]
/*
* 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