LCOV - code coverage report
Current view: top level - lib_lc3plus - lc3.c (source / functions) Hit Total Coverage
Test: Coverage on main -- dec/rend @ 633e3f2e309758d10805ef21e0436356fe719b7a Lines: 0 179 0.0 %
Date: 2025-08-23 01:22:27 Functions: 0 36 0.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             : *                        ETSI TS 103 634 V1.5.1                               *
       3             : *              Low Complexity Communication Codec Plus (LC3plus)              *
       4             : *                                                                             *
       5             : * Copyright licence is solely granted through ETSI Intellectual Property      *
       6             : * Rights Policy, 3rd April 2019. No patent licence is granted by implication, *
       7             : * estoppel or otherwise.                                                      *
       8             : ******************************************************************************/
       9             :                                                                               
      10             : #include "defines.h"
      11             : #include "functions.h"
      12             : #include "lc3.h"
      13             : #include "setup_dec_lc3.h"
      14             : #include "setup_enc_lc3.h"
      15             : 
      16             : #define RETURN_IF(cond, error)                                                                                         \
      17             :     if (cond)                                                                                                          \
      18             :     return (error)
      19             : 
      20             : #ifndef FIX_IVAS_LC3PLUS_WARNINGS
      21             : #ifdef SUBSET_NB
      22             : #pragma message("- SUBSET_NB")
      23             : #endif
      24             : #ifdef SUBSET_WB
      25             : #pragma message("- SUBSET_WB")
      26             : #endif
      27             : #ifdef SUBSET_SSWB
      28             : #pragma message("- SUBSET_SSWB")
      29             : #endif
      30             : #ifdef SUBSET_SWB
      31             : #pragma message("- SUBSET_SWB")
      32             : #endif
      33             : #ifdef SUBSET_FB
      34             : #pragma message("- SUBSET_FB")
      35             : #endif
      36             : #ifdef SUBSET_UB
      37             : #pragma message("- SUBSET_UB")
      38             : #endif
      39             : #endif
      40             : 
      41             : /* ensure api header constants are up to date */
      42             : STATIC_ASSERT(LC3PLUS_MAX_SAMPLES >= MAX_LEN);
      43             : STATIC_ASSERT(LC3PLUS_MAX_CHANNELS >= MAX_CHANNELS);
      44             : STATIC_ASSERT(LC3PLUS_MAX_BYTES >= BYTESBUFSIZE);
      45             : STATIC_ASSERT(LC3PLUS_ENC_MAX_SIZE >= ENC_MAX_SIZE);
      46             : STATIC_ASSERT(LC3PLUS_DEC_MAX_SIZE >= DEC_MAX_SIZE);
      47             : STATIC_ASSERT(LC3PLUS_ENC_MAX_SCRATCH_SIZE >= SCRATCH_BUF_LEN_ENC_TOT);
      48             : STATIC_ASSERT(LC3PLUS_DEC_MAX_SCRATCH_SIZE >= SCRATCH_BUF_LEN_DEC_TOT);
      49             : STATIC_ASSERT(PLC_FADEOUT_IN_MS >= 20);
      50             : 
      51             : 
      52             : /* misc functions ************************************************************/
      53             : 
      54           0 : int lc3plus_version(void)
      55             : {
      56           0 :     return LC3PLUS_VERSION;
      57             : }
      58             : 
      59           0 : int lc3plus_channels_supported(int channels)
      60             : {
      61           0 :     return channels >= 1 && channels <= MAX_CHANNELS;
      62             : }
      63             : 
      64           0 : int lc3plus_samplerate_supported(int samplerate)
      65             : {
      66           0 :     switch (samplerate)
      67             :     {
      68             : #ifdef SUBSET_NB
      69           0 :     case 8000: return 1;
      70             : #endif
      71             : #ifdef SUBSET_WB
      72           0 :     case 16000: return 1;
      73             : #endif
      74             : #ifdef SUBSET_SSWB
      75           0 :     case 24000: return 1;
      76             : #endif
      77             : #ifdef SUBSET_SWB
      78           0 :     case 32000: return 1;
      79             : #endif
      80             : #ifdef SUBSET_FB
      81           0 :     case 44100: return 1;
      82           0 :     case 48000: return 1;
      83             : #endif
      84             : #ifdef ENABLE_HR_MODE
      85           0 :     case 96000: return 1;
      86             : #endif
      87           0 :     default: return 0;
      88             :     }
      89             : }
      90             : 
      91           0 : static int lc3plus_plc_mode_supported(LC3PLUS_PlcMode plc_mode)
      92             : {
      93           0 :     switch ((int)plc_mode)
      94             :     {
      95           0 :     case LC3PLUS_PLC_ADVANCED: /* fallthru */
      96           0 :         return 1;
      97           0 :     default: return 0;
      98             :     }
      99             : }
     100             : 
     101           0 : static int lc3plus_frame_size_supported(int frame_dms)
     102             : {
     103           0 :     switch (frame_dms)
     104             :     {
     105           0 :     case 25: /* fallthru */
     106             :     case 50: /* fallthru */
     107             :     case 75: /* fallthru */
     108             :     case 100:
     109           0 :             return 1;
     110           0 :     default: return 0;
     111             :     }
     112             : }
     113             : 
     114           0 : static int null_in_list(void **list, int n)
     115             : {
     116           0 :     while (--n >= 0)
     117           0 :         RETURN_IF(list[n] == NULL, 1);
     118           0 :     return 0;
     119             : }
     120             : 
     121             : /* return pointer to aligned base + base_size, *base_size += size + 4 bytes align */
     122           0 : void *balloc(void *base, size_t *base_size, size_t size)
     123             : {
     124           0 :     uintptr_t ptr = ((uintptr_t)base + *base_size + 3) & ~3;
     125           0 :     assert((uintptr_t)base % 4 == 0); /* base must be 4-byte aligned */
     126           0 :     *base_size = (*base_size + size + 3) & ~3;
     127           0 :     return (void *)ptr;
     128             : }
     129             : 
     130           0 : int32_t lc3_enc_supported_lfe(void)
     131             : {
     132           0 :     return 1;
     133             : }
     134             : 
     135             : /* encoder functions *********************************************************/
     136             : 
     137           0 : LC3PLUS_Error lc3plus_enc_init(LC3PLUS_Enc *encoder, int samplerate, int channels
     138             : #ifdef ENABLE_HR_MODE
     139             :                                , int hrmode
     140             : #endif
     141             :                                , int32_t lfe_channel_array[]
     142             :                               )
     143             : {
     144           0 :     int ch = 0;
     145             : 
     146           0 :     RETURN_IF(encoder == NULL, LC3PLUS_NULL_ERROR);
     147           0 :     RETURN_IF((uintptr_t)encoder % 4 != 0, LC3PLUS_ALIGN_ERROR);
     148           0 :     RETURN_IF(!lc3plus_samplerate_supported(samplerate), LC3PLUS_SAMPLERATE_ERROR);
     149           0 :     RETURN_IF(!lc3plus_channels_supported(channels), LC3PLUS_CHANNELS_ERROR);
     150             : #ifdef ENABLE_HR_MODE
     151           0 :     RETURN_IF(samplerate==96000 && hrmode == 0, LC3PLUS_HRMODE_ERROR);
     152             : #endif
     153             : 
     154           0 :     if (lfe_channel_array != NULL)
     155             :     {
     156           0 :         for (ch = 0; ch < channels; ch++)
     157             :         {
     158           0 :             RETURN_IF(!lc3_enc_supported_lfe() && lfe_channel_array[ch], LC3PLUS_LFE_MODE_NOT_SUPPORTED);
     159             :         }
     160             :     }
     161             : 
     162             : #ifdef ENABLE_HR_MODE
     163           0 :     return FillEncSetup(encoder, samplerate, channels, hrmode
     164             :                         , lfe_channel_array
     165             :     ); /* real bitrate check happens here */
     166             : #else
     167             :     return FillEncSetup(encoder, samplerate, channels
     168             :                         , lfe_channel_array
     169             :     ); /* real bitrate check happens here */
     170             : #endif
     171             : }
     172             : 
     173           0 : int lc3plus_enc_get_size(int samplerate, int channels)
     174             : {
     175           0 :     RETURN_IF(!lc3plus_samplerate_supported(samplerate), 0);
     176           0 :     RETURN_IF(!lc3plus_channels_supported(channels), 0);
     177           0 :     return alloc_encoder(NULL, samplerate, channels);
     178             : }
     179             : 
     180           0 : int lc3plus_enc_get_scratch_size(const LC3PLUS_Enc *encoder)
     181             : {
     182           0 :     int size = 0;
     183           0 :      RETURN_IF(encoder == NULL, 0);
     184             : 
     185             : #ifdef ENABLE_HR_MODE
     186           0 :     size = 47 * MAX(encoder->frame_length, 160) + 64;
     187             : #else
     188             :     size = 14 * MAX(encoder->frame_length, 160) + 64;
     189             : #endif
     190           0 :     assert(size <= LC3PLUS_ENC_MAX_SCRATCH_SIZE);
     191           0 :     return size;
     192             : }
     193             : 
     194           0 : int lc3plus_enc_get_input_samples(const LC3PLUS_Enc *encoder)
     195             : {
     196           0 :     RETURN_IF(encoder == NULL, 0);
     197           0 :     return encoder->frame_length;
     198             : }
     199             : 
     200           0 : int lc3plus_enc_get_num_bytes(const LC3PLUS_Enc *encoder)
     201             : {
     202           0 :     RETURN_IF(encoder == NULL, 0);
     203           0 :     return (Word32)encoder->bitrate * encoder->frame_length / (8 * encoder->fs_in);
     204             : }
     205             : 
     206           0 : int lc3plus_enc_get_real_bitrate(const LC3PLUS_Enc *encoder)
     207             : {
     208           0 :     int ch = 0, totalBytes = 0;
     209           0 :     RETURN_IF(encoder == NULL, 0);
     210           0 :     RETURN_IF(!encoder->lc3_br_set, LC3PLUS_BITRATE_UNSET_ERROR);
     211             :     
     212           0 :     for (ch = 0; ch < encoder->channels; ch++)
     213             :     {
     214           0 :         totalBytes += encoder->channel_setup[ch]->targetBytes;
     215             :     }
     216             :     
     217           0 :     int bitrate = (totalBytes * 80000.0 + encoder->frame_dms - 1) / encoder->frame_dms;
     218             :     
     219           0 :     if (encoder->fs_in == 44100)
     220             :     {
     221           0 :         int rem = bitrate % 480;
     222           0 :         bitrate = ((bitrate - rem) / 480) * 441 + (rem * 441) / 480;
     223             :     }
     224             :     
     225           0 :     return bitrate;
     226             : }
     227             : 
     228           0 : LC3PLUS_Error lc3plus_enc_set_bitrate(LC3PLUS_Enc *encoder, int bitrate)
     229             : {
     230           0 :     RETURN_IF(encoder == NULL, LC3PLUS_NULL_ERROR);
     231           0 :     RETURN_IF(bitrate <= 0, LC3PLUS_BITRATE_ERROR);
     232           0 :     return update_enc_bitrate(encoder, bitrate);
     233             : }
     234             : 
     235           0 : int lc3plus_enc_get_delay(const LC3PLUS_Enc *encoder)
     236             : {
     237           0 :     RETURN_IF(encoder == NULL, 0);
     238           0 :     return encoder->frame_length - 2 * encoder->la_zeroes;
     239             : }
     240             : 
     241           0 : LC3PLUS_Error lc3plus_enc_set_ep_mode(LC3PLUS_Enc *encoder, LC3PLUS_EpMode epmode)
     242             : {
     243           0 :     RETURN_IF(encoder == NULL, LC3PLUS_NULL_ERROR);
     244           0 :     RETURN_IF((unsigned)epmode > LC3PLUS_EP_HIGH, LC3PLUS_EPMODE_ERROR);
     245           0 :     encoder->epmode = epmode;
     246           0 :     return encoder->lc3_br_set ? update_enc_bitrate(encoder, encoder->bitrate) : LC3PLUS_OK;
     247             : }
     248             : 
     249           0 : LC3PLUS_Error lc3plus_enc_set_ep_mode_request(LC3PLUS_Enc *encoder, LC3PLUS_EpModeRequest epmr)
     250             : {
     251           0 :     RETURN_IF(encoder == NULL, LC3PLUS_NULL_ERROR);
     252           0 :     RETURN_IF((unsigned)epmr > LC3PLUS_EPMR_HIGH, LC3PLUS_EPMR_ERROR);
     253           0 :     encoder->epmr = epmr;
     254           0 :     return LC3PLUS_OK;
     255             : }
     256             : 
     257           0 : LC3PLUS_Error lc3plus_enc_set_frame_dms(LC3PLUS_Enc *encoder, int frame_dms)
     258             : {
     259           0 :     RETURN_IF(encoder == NULL, LC3PLUS_NULL_ERROR);
     260           0 :     RETURN_IF(!lc3plus_frame_size_supported(frame_dms), LC3PLUS_FRAMEMS_ERROR);
     261           0 :     RETURN_IF(encoder->lc3_br_set, LC3PLUS_BITRATE_SET_ERROR);
     262           0 :     encoder->frame_dms = frame_dms;
     263           0 :     set_enc_frame_params(encoder);
     264           0 :     return LC3PLUS_OK;
     265             : }
     266             : 
     267             : 
     268           0 : LC3PLUS_Error lc3plus_enc_set_bandwidth(LC3PLUS_Enc *encoder, int bandwidth)
     269             : {
     270           0 :     RETURN_IF(encoder == NULL, LC3PLUS_NULL_ERROR);
     271           0 :     Word32 effective_fs = encoder->fs_in;
     272           0 :     if (encoder->bandwidth != bandwidth) {
     273           0 :         if (encoder->fs_in > 40000) {
     274           0 :             effective_fs = 40000;
     275             :         }
     276           0 :         if ((bandwidth * 2) > effective_fs) {
     277           0 :             return LC3PLUS_BW_WARNING;
     278             :         }
     279             :         else {
     280           0 :             encoder->bandwidth = bandwidth;
     281           0 :             encoder->bandwidth_preset = bandwidth;
     282           0 :             encoder->bw_ctrl_active   = 1;
     283           0 :             update_enc_bitrate(encoder, encoder->bitrate);
     284             :         }
     285             :     }
     286           0 :     return LC3PLUS_OK;
     287             : }
     288             : 
     289             : 
     290           0 : static LC3PLUS_Error lc3plus_enc(LC3PLUS_Enc *encoder, void **input_samples, int bitdepth, void *output_bytes, int *num_bytes,
     291             :                          void *scratch)
     292             : {
     293           0 :     RETURN_IF(!encoder || !input_samples || !output_bytes || !num_bytes || !scratch, LC3PLUS_NULL_ERROR);
     294           0 :     RETURN_IF(null_in_list(input_samples, encoder->channels), LC3PLUS_NULL_ERROR);
     295           0 :     RETURN_IF(bitdepth != 16 && bitdepth != 24, LC3PLUS_ERROR);
     296           0 :     RETURN_IF(!encoder->lc3_br_set, LC3PLUS_BITRATE_UNSET_ERROR);
     297           0 :     *num_bytes = Enc_LC3PLUS(encoder, input_samples, bitdepth, output_bytes, scratch, *num_bytes == -1);
     298             :     
     299           0 :     assert(*num_bytes == lc3plus_enc_get_num_bytes(encoder));
     300           0 :     return LC3PLUS_OK;
     301             : }
     302             : 
     303           0 : LC3PLUS_Error lc3plus_enc16(LC3PLUS_Enc *encoder, int16_t **input_samples, void *output_bytes, int *num_bytes, void *scratch)
     304             : {
     305           0 :     return lc3plus_enc(encoder, (void **)input_samples, 16, output_bytes, num_bytes, scratch);
     306             : }
     307             : 
     308           0 : LC3PLUS_Error lc3plus_enc24(LC3PLUS_Enc *encoder, int32_t **input_samples, void *output_bytes, int *num_bytes, void *scratch)
     309             : {
     310           0 :     return lc3plus_enc(encoder, (void **)input_samples, 24, output_bytes, num_bytes, scratch);
     311             : }
     312             : 
     313             : /* decoder functions *********************************************************/
     314             : 
     315           0 : LC3PLUS_Error lc3plus_dec_init(LC3PLUS_Dec *decoder, int samplerate, int channels, LC3PLUS_PlcMode plc_mode
     316             : #ifdef ENABLE_HR_MODE
     317             :                             , int hrmode
     318             : #endif
     319             : )
     320             : {
     321           0 :     RETURN_IF(decoder == NULL, LC3PLUS_NULL_ERROR);
     322           0 :     RETURN_IF(!lc3plus_samplerate_supported(samplerate), LC3PLUS_SAMPLERATE_ERROR);
     323           0 :     RETURN_IF(!lc3plus_channels_supported(channels), LC3PLUS_CHANNELS_ERROR);
     324           0 :     RETURN_IF(!lc3plus_plc_mode_supported(plc_mode), LC3PLUS_PLCMODE_ERROR);
     325             : #ifdef ENABLE_HR_MODE
     326           0 :     RETURN_IF(samplerate==96000 && hrmode == 0, LC3PLUS_HRMODE_ERROR);
     327             : #endif
     328             : 
     329           0 :     return FillDecSetup(decoder, samplerate, channels, plc_mode
     330             : #ifdef ENABLE_HR_MODE
     331             :                         , hrmode
     332             : #endif
     333             :                        );
     334             : } 
     335             : 
     336           0 : int lc3plus_dec_get_size(int samplerate, int channels, LC3PLUS_PlcMode plc_mode)
     337             : {
     338           0 :     RETURN_IF(!lc3plus_samplerate_supported(samplerate), 0);
     339           0 :     RETURN_IF(!lc3plus_channels_supported(channels), 0);
     340           0 :     RETURN_IF(!lc3plus_plc_mode_supported(plc_mode), 0);
     341           0 :     return alloc_decoder(NULL, samplerate, channels);
     342             : }
     343             : 
     344           0 : int lc3plus_dec_get_scratch_size(const LC3PLUS_Dec *decoder)
     345             : {
     346           0 :     int size = 0;
     347           0 :     RETURN_IF(decoder == NULL, 0);
     348             : 
     349             : #ifdef ENABLE_HR_MODE
     350           0 :     size = 30 * DYN_MAX_LEN(decoder->fs) + 2866;
     351           0 :     size += 4 * MAX_LGW + 8 * DYN_MAX_LPROT(decoder->fs) + 16 * DYN_MAX_LEN(decoder->fs);
     352             : #else
     353             :     size = 12 * DYN_MAX_LEN(decoder->fs) + 752;
     354             :     size += 2 * MAX_LGW + 8 * DYN_MAX_LPROT(decoder->fs) + 8 * DYN_MAX_LEN(decoder->fs);
     355             :     size += 3720;
     356             : #endif
     357             : 
     358           0 :     assert(size <= LC3PLUS_DEC_MAX_SCRATCH_SIZE);
     359           0 :     return size;
     360             : }
     361             : 
     362           0 : LC3PLUS_Error lc3plus_dec_set_ep_enabled(LC3PLUS_Dec *decoder, int ep_enabled)
     363             : {
     364           0 :     RETURN_IF(decoder == NULL, LC3PLUS_NULL_ERROR);
     365           0 :     decoder->ep_enabled = ep_enabled != 0;
     366           0 :     decoder->epmr       = LC3PLUS_EPMR_ZERO;
     367           0 :     return LC3PLUS_OK;
     368             : }
     369             : 
     370           0 : int lc3plus_dec_get_error_report(const LC3PLUS_Dec *decoder)
     371             : {
     372           0 :     RETURN_IF(decoder == NULL, 0);
     373           0 :     return decoder->error_report == 2047 ? -1 : decoder->error_report & 0x07FF;
     374             : }
     375             : 
     376           0 : int lc3plus_dec_get_epok_flags(const LC3PLUS_Dec *decoder)
     377             : {
     378           0 :     RETURN_IF(decoder == NULL, 0);
     379           0 :     return decoder->error_report >> 11;
     380             : }
     381             : 
     382           0 : LC3PLUS_EpModeRequest lc3plus_dec_get_ep_mode_request(const LC3PLUS_Dec *decoder)
     383             : {
     384           0 :     RETURN_IF(decoder == NULL, LC3PLUS_EPMR_ZERO);
     385           0 :     return (LC3PLUS_EpModeRequest)decoder->epmr;
     386             : }
     387             : 
     388           0 : LC3PLUS_Error lc3plus_dec_set_frame_dms(LC3PLUS_Dec *decoder, int frame_dms)
     389             : {
     390           0 :     RETURN_IF(decoder == NULL, LC3PLUS_NULL_ERROR);
     391           0 :     RETURN_IF(!lc3plus_frame_size_supported(frame_dms), LC3PLUS_FRAMEMS_ERROR);
     392           0 :     RETURN_IF(decoder->plcMeth == 2 && frame_dms != 100, LC3PLUS_FRAMEMS_ERROR);
     393             : 
     394           0 :     decoder->frame_dms = frame_dms;
     395           0 :     set_dec_frame_params(decoder);
     396           0 :     return LC3PLUS_OK;
     397             : }
     398             : 
     399             : 
     400           0 : int lc3plus_dec_get_output_samples(const LC3PLUS_Dec *decoder)
     401             : {
     402           0 :     RETURN_IF(decoder == NULL, 0);
     403           0 :     return decoder->frame_length;
     404             : }
     405             : 
     406           0 : int lc3plus_dec_get_delay(const LC3PLUS_Dec *decoder)
     407             : {
     408           0 :     RETURN_IF(decoder == NULL, 0);
     409           0 :     return decoder->frame_length - 2 * decoder->la_zeroes;
     410             : }
     411             : 
     412           0 : static LC3PLUS_Error lc3plus_dec(LC3PLUS_Dec *decoder, void *input_bytes, int num_bytes, void **output_samples, int bitdepth,
     413             :                          void *scratch, int bfi_ext)
     414             : {
     415           0 :     if (bfi_ext == 1)
     416             :     {
     417           0 :         RETURN_IF(!decoder || !output_samples || !scratch, LC3PLUS_NULL_ERROR);
     418             :     } else {
     419           0 :         RETURN_IF(!decoder || !input_bytes || !output_samples || !scratch, LC3PLUS_NULL_ERROR);
     420             :     }
     421             : 
     422           0 :     RETURN_IF(null_in_list(output_samples, decoder->channels), LC3PLUS_NULL_ERROR);
     423           0 :     RETURN_IF(bitdepth != 16 && bitdepth != 24, LC3PLUS_ERROR);
     424           0 :     return Dec_LC3PLUS(decoder, input_bytes, num_bytes, output_samples, bitdepth, scratch, bfi_ext);
     425             : }
     426             : 
     427           0 : LC3PLUS_Error lc3plus_dec16(LC3PLUS_Dec *decoder, void *input_bytes, int num_bytes, int16_t **output_samples, void *scratch, int bfi_ext)
     428             : {
     429           0 :     return lc3plus_dec(decoder, input_bytes, num_bytes, (void **)output_samples, 16, scratch, bfi_ext);
     430             : }
     431             : 
     432           0 : LC3PLUS_Error lc3plus_dec24(LC3PLUS_Dec *decoder, void *input_bytes, int num_bytes, int32_t **output_samples, void *scratch, int bfi_ext)
     433             : {
     434           0 :     return lc3plus_dec(decoder, input_bytes, num_bytes, (void **)output_samples, 24, scratch, bfi_ext);
     435             : }

Generated by: LCOV version 1.14