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

Generated by: LCOV version 1.14