LCOV - code coverage report
Current view: top level - lib_isar - isar_lc3plus_enc.c (source / functions) Hit Total Coverage
Test: Coverage on main -- short test vectors @ 6c9ddc4024a9c0e1ecb8f643f114a84a0e26ec6b Lines: 0 223 0.0 %
Date: 2025-05-23 08:37:30 Functions: 0 7 0.0 %

          Line data    Source code
       1             : /******************************************************************************************************
       2             : 
       3             :    (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
       4             :    Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
       5             :    Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
       6             :    Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
       7             :    contributors to this repository. All Rights Reserved.
       8             : 
       9             :    This software is protected by copyright law and by international treaties.
      10             :    The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
      11             :    Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
      12             :    Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
      13             :    Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
      14             :    contributors to this repository retain full ownership rights in their respective contributions in
      15             :    the software. This notice grants no license of any kind, including but not limited to patent
      16             :    license, nor is any license granted by implication, estoppel or otherwise.
      17             : 
      18             :    Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
      19             :    contributions.
      20             : 
      21             :    This software is provided "AS IS", without any express or implied warranties. The software is in the
      22             :    development stage. It is intended exclusively for experts who have experience with such software and
      23             :    solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
      24             :    and fitness for a particular purpose are hereby disclaimed and excluded.
      25             : 
      26             :    Any dispute, controversy or claim arising under or in relation to providing this software shall be
      27             :    submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
      28             :    accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
      29             :    the United Nations Convention on Contracts on the International Sales of Goods.
      30             : 
      31             : *******************************************************************************************************/
      32             : 
      33             : #include "isar_lc3plus_enc.h"
      34             : #include "isar_lc3plus_common.h"
      35             : #include "lc3.h"
      36             : #include "ivas_error_utils.h"
      37             : #include "prot.h"
      38             : #include "wmc_auto.h"
      39             : #include "options.h"
      40             : 
      41             : static const LC3PLUS_RTP_FDL s_fdl_request = LC3PLUS_RTP_FDL_NO_REQ_OR_NO_DATA;
      42             : 
      43           0 : static int32_t limit_per_channel_bitrate(
      44             :     LC3PLUS_CONFIG config,
      45             :     const int32_t per_channel_bitrate )
      46             : {
      47           0 :     if ( config.high_res_mode_enabled )
      48             :     {
      49           0 :         switch ( config.lc3plus_frame_duration_us )
      50             :         {
      51           0 :             case 10000:
      52           0 :                 return min( per_channel_bitrate, 500000 );
      53           0 :             case 5000:
      54           0 :                 return min( per_channel_bitrate, 600000 );
      55           0 :             case 2500:
      56           0 :                 return min( per_channel_bitrate, 672000 );
      57           0 :             default:
      58           0 :                 assert( false && "unreachable" );
      59             :         }
      60             :     }
      61             : 
      62           0 :     switch ( config.samplerate )
      63             :     {
      64           0 :         case 48000:
      65             :         case 32000:
      66           0 :             return min( per_channel_bitrate, 320000 );
      67           0 :         case 24000:
      68           0 :             return min( per_channel_bitrate, 314400 );
      69           0 :         case 16000:
      70           0 :             return min( per_channel_bitrate, 221600 );
      71           0 :         case 8000:
      72           0 :             return min( per_channel_bitrate, 114400 );
      73           0 :         default:
      74           0 :             assert( false && "unreachable" );
      75             :     }
      76             : 
      77             :     assert( false && "unreachable" );
      78             :     return -1;
      79             : }
      80             : 
      81             : 
      82             : /*-------------------------------------------------------------------*
      83             :  * Function ISAR_LC3PLUS_ENC_Open()
      84             :  *
      85             :  *
      86             :  *-------------------------------------------------------------------*/
      87             : 
      88           0 : ivas_error ISAR_LC3PLUS_ENC_Open(
      89             :     const LC3PLUS_CONFIG config,    /* i  : LC3plus encoder configuration   */
      90             :     const uint32_t bitsPerSecond,   /* i  : bit rate                        */
      91             :     ISAR_LC3PLUS_ENC_HANDLE *handle /* o  : encoder handle                  */
      92             : )
      93             : {
      94             :     int32_t num_lc3plus_media_times_per_ivas_frame;
      95             :     bool is_last_media_time, is_last_channel;
      96             :     ivas_error ivas_err;
      97             :     int32_t encoder_size;
      98             :     LC3PLUS_Error err;
      99             :     int32_t lfeChans[1];
     100             :     int16_t i;
     101             : 
     102           0 :     lfeChans[0] = 0;
     103             : 
     104           0 :     if ( 0U == config.channels )
     105             :     {
     106           0 :         return IVAS_ERROR( IVAS_ERR_INTERNAL, "Invalid number of channels\n" );
     107             :     }
     108             : 
     109           0 :     if ( config.lc3plus_frame_duration_us != 2500 && config.lc3plus_frame_duration_us != 5000 && config.lc3plus_frame_duration_us != 10000 )
     110             :     {
     111           0 :         return IVAS_ERROR( IVAS_ERR_INTERNAL, "Invalid lc3plus_frame_duration_us\n" );
     112             :     }
     113           0 :     if ( config.isar_frame_duration_us != 20000 && config.isar_frame_duration_us != 10000 && config.isar_frame_duration_us != 5000 )
     114             :     {
     115           0 :         return IVAS_ERROR( IVAS_ERR_INTERNAL, "Invalid isar_frame_duration_us\n" );
     116             :     }
     117             : 
     118           0 :     encoder_size = lc3plus_enc_get_size( config.samplerate, 1 );
     119           0 :     if ( 0 == encoder_size )
     120             :     {
     121           0 :         return IVAS_ERROR( IVAS_ERR_INTERNAL, "lc3plus_enc_get_size failed\n" );
     122             :     }
     123             : 
     124           0 :     if ( ( *handle = malloc( sizeof( struct ISAR_LC3PLUS_ENC_HANDLE ) ) ) == NULL )
     125             :     {
     126           0 :         return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus wrapper handle\n" );
     127             :     }
     128             : 
     129           0 :     ( *handle )->config = config;
     130           0 :     ( *handle )->frame_type_descriptors = NULL;
     131             : 
     132           0 :     ( *handle )->pcm_conversion_buffer = NULL;
     133           0 :     ( *handle )->num_encs = 0;
     134           0 :     if ( ( ( *handle )->handles = malloc( config.channels * sizeof( ISAR_LC3PLUS_ENC_HANDLE ) ) ) == NULL )
     135             :     {
     136           0 :         ISAR_LC3PLUS_ENC_Close( handle );
     137           0 :         return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus wrapper handle\n" );
     138             :     }
     139             : 
     140           0 :     for ( i = 0; i < config.channels; ++i )
     141             :     {
     142           0 :         ( *handle )->handles[i] = NULL;
     143             :     }
     144           0 :     ( *handle )->num_encs = config.channels;
     145             : 
     146           0 :     num_lc3plus_media_times_per_ivas_frame = config.isar_frame_duration_us / config.lc3plus_frame_duration_us;
     147           0 :     ( *handle )->fdl_request = s_fdl_request;
     148           0 :     ( *handle )->num_ftds = config.channels * num_lc3plus_media_times_per_ivas_frame;
     149           0 :     ( *handle )->frame_type_descriptors = malloc( ( *handle )->num_ftds * sizeof( LC3PLUS_RTP_FTD ) );
     150           0 :     if ( NULL == ( *handle )->frame_type_descriptors )
     151             :     {
     152           0 :         ISAR_LC3PLUS_ENC_Close( handle );
     153           0 :         return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus frame_type_descriptors\n" );
     154             :     }
     155             : 
     156           0 :     for ( int32_t iCh = 0; iCh < config.channels; iCh++ )
     157             :     {
     158           0 :         if ( ( ( *handle )->handles[iCh] = malloc( encoder_size ) ) == NULL )
     159             :         {
     160           0 :             ISAR_LC3PLUS_ENC_Close( handle );
     161           0 :             return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus encoder\n" );
     162             :         }
     163             : 
     164           0 :         err = lc3plus_enc_init( ( *handle )->handles[iCh], config.samplerate, 1, config.high_res_mode_enabled, lfeChans );
     165           0 :         if ( err != LC3PLUS_OK )
     166             :         {
     167           0 :             ISAR_LC3PLUS_ENC_Close( handle );
     168           0 :             return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_enc_init failed\n" );
     169             :         }
     170             : 
     171           0 :         err = lc3plus_enc_set_frame_dms( ( *handle )->handles[iCh], config.lc3plus_frame_duration_us / 100 );
     172           0 :         if ( err != LC3PLUS_OK )
     173             :         {
     174           0 :             ISAR_LC3PLUS_ENC_Close( handle );
     175           0 :             return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_enc_set_frame_dms failed\n" );
     176             :         }
     177             :     }
     178             : 
     179           0 :     if ( config.isar_frame_duration_us < config.lc3plus_frame_duration_us || config.isar_frame_duration_us % config.lc3plus_frame_duration_us != 0 )
     180             :     {
     181           0 :         ISAR_LC3PLUS_ENC_Close( handle );
     182           0 :         return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "Current pcm_conversion_buffer sizing requires that lc3plus uses a shorter or equal frame duration than ivas\n" );
     183             :     }
     184             : 
     185           0 :     ( *handle )->pcm_conversion_buffer = malloc( sizeof( int16_t ) * config.samplerate * config.lc3plus_frame_duration_us / 1000000 );
     186           0 :     if ( NULL == ( *handle )->pcm_conversion_buffer )
     187             :     {
     188           0 :         ISAR_LC3PLUS_ENC_Close( handle );
     189           0 :         return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus encoder wrapper pcm_conversion_buffer\n" );
     190             :     }
     191             : 
     192             :     /* update FDI fields */
     193           0 :     for ( int32_t iMediaTime = 0; iMediaTime < num_lc3plus_media_times_per_ivas_frame; ++iMediaTime )
     194             :     {
     195           0 :         for ( uint32_t iEnc = 0; iEnc < ( *handle )->num_encs; ++iEnc )
     196             :         {
     197           0 :             int32_t ftd_index = iEnc + iMediaTime * ( *handle )->num_encs;
     198             : 
     199           0 :             ( *handle )->frame_type_descriptors[ftd_index].frame_data_length = 0; /* will be set to the correct value in IVAS_LC3PLUS_ENC_SetBitrate */
     200             : 
     201           0 :             if ( 0 != LC3PLUS_RTP_ftd_bwr_from_samplerate( &( *handle )->frame_type_descriptors[ftd_index].bwr, config.samplerate, config.high_res_mode_enabled ) )
     202             :             {
     203           0 :                 ISAR_LC3PLUS_ENC_Close( handle );
     204           0 :                 return IVAS_ERROR( IVAS_ERR_INTERNAL, "LC3PLUS_RTP_ftd_bwr_from_samplerate failed\n" );
     205             :             }
     206           0 :             if ( 0 != LC3PLUS_RTP_ftd_fdi_from_frame_duration_us( &( *handle )->frame_type_descriptors[ftd_index].fdi, config.lc3plus_frame_duration_us ) )
     207             :             {
     208           0 :                 ISAR_LC3PLUS_ENC_Close( handle );
     209           0 :                 return IVAS_ERROR( IVAS_ERR_INTERNAL, "LC3PLUS_RTP_ftd_fdi_from_frame_duration_us failed\n" );
     210             :             }
     211           0 :             ( *handle )->frame_type_descriptors[ftd_index].h = LC3PLUS_RTP_FTD_H_PRIMARY;
     212           0 :             ( *handle )->frame_type_descriptors[ftd_index].frame_data = NULL;
     213             : 
     214             :             /* The FTDs in the ToC are included in the following order:
     215             :              * 1) First the FTD for the first channel of the first FDB (oldest frame)
     216             :              * 2) Then the FTDs for the remaining channels for the first FDB in increasing CC order
     217             :              * 3) Then the FTD for the first channel of the second FDB
     218             :              * 4) Then the FTDs for the remaining channels for the second FDB
     219             :              * 5) Etc. to the last FDB */
     220           0 :             is_last_media_time = num_lc3plus_media_times_per_ivas_frame - 1 == iMediaTime;
     221           0 :             is_last_channel = ( *handle )->num_encs - 1 == iEnc;
     222           0 :             if ( is_last_media_time && is_last_channel )
     223             :             {
     224           0 :                 ( *handle )->frame_type_descriptors[ftd_index].fc = LC3PLUS_RTP_FTD_FC_LAST_OVERALL;
     225             :             }
     226           0 :             else if ( !is_last_media_time && is_last_channel )
     227             :             {
     228           0 :                 ( *handle )->frame_type_descriptors[ftd_index].fc = LC3PLUS_RTP_FTD_FC_LAST_IN_MEDIATIME;
     229             :             }
     230             :             else
     231             :             {
     232           0 :                 ( *handle )->frame_type_descriptors[ftd_index].fc = LC3PLUS_RTP_FTD_FC_SUBSEQUENT_CHANNEL;
     233             :             }
     234             :         }
     235             :     }
     236             : 
     237           0 :     ivas_err = IVAS_LC3PLUS_ENC_SetBitrate( *handle, bitsPerSecond );
     238           0 :     if ( ivas_err != IVAS_ERR_OK )
     239             :     {
     240           0 :         ISAR_LC3PLUS_ENC_Close( handle );
     241           0 :         return ivas_err;
     242             :     }
     243             : 
     244           0 :     return IVAS_ERR_OK;
     245             : }
     246             : 
     247             : /*-------------------------------------------------------------------*
     248             :  * Function IVAS_LC3PLUS_ENC_SetBitrate()
     249             :  *
     250             :  *
     251             :  *-------------------------------------------------------------------*/
     252             : 
     253           0 : ivas_error IVAS_LC3PLUS_ENC_SetBitrate(
     254             :     ISAR_LC3PLUS_ENC_HANDLE handle, /* o  : LC3plus encoder handle                           */
     255             :     const uint32_t bitsPerSecond    /* i  : new target bit rate                              */
     256             : )
     257             : {
     258             :     int32_t numLc3plusMediaTimesPerIvasFrame;
     259             :     int32_t lc3plus_num_bytes_per_frame;
     260             :     int32_t availableOctetsPerIsarFrame;
     261             :     int32_t actualOctetsPerFrame;
     262             :     LC3PLUS_Error err;
     263             :     ivas_error ivas_err;
     264             :     int32_t iFtd;
     265             :     int32_t fdrLength;
     266             :     int32_t lc3plusPacketRate;
     267             :     int32_t numSubframes;
     268             :     int32_t minPayloadOverhead;
     269             :     int32_t targetLc3PlusBitratePerChannel;
     270             :     int32_t targetLc3PlusOctetCount;
     271             :     int32_t lc3plusFdlLength;
     272             : 
     273           0 :     if ( NULL == handle )
     274             :     {
     275           0 :         return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3PLUS_Enc_Wrap_Handle is NULL\n" );
     276             :     }
     277             : 
     278           0 :     availableOctetsPerIsarFrame = bitsPerSecond / ( 1000000 / handle->config.isar_frame_duration_us ) / 8;
     279           0 :     lc3plusPacketRate = 1000 * 1000 / handle->config.lc3plus_frame_duration_us;
     280           0 :     numLc3plusMediaTimesPerIvasFrame = handle->config.isar_frame_duration_us / handle->config.lc3plus_frame_duration_us;
     281           0 :     numSubframes = numLc3plusMediaTimesPerIvasFrame * handle->config.channels;
     282             : 
     283             :     /* subtract minimum required payload bytes & calculate a first per-channel target bit rate */
     284           0 :     if ( LC3PLUS_RTP_frame_data_length_get_size( &fdrLength, s_fdl_request ) != LC3PLUS_RTP_ERR_NO_ERROR )
     285             :     {
     286           0 :         return IVAS_ERROR( IVAS_ERR_INTERNAL, "LC3PLUS_RTP_frame_data_length_get_size failed\n" );
     287             :     }
     288           0 :     minPayloadOverhead = fdrLength + ( numSubframes * LC3PLUS_RTP_FTD_MIN_SIZE );
     289           0 :     targetLc3PlusBitratePerChannel = ( availableOctetsPerIsarFrame - minPayloadOverhead ) / handle->config.channels * 8 * lc3plusPacketRate / numLc3plusMediaTimesPerIvasFrame;
     290             : 
     291           0 :     if ( targetLc3PlusBitratePerChannel <= 0 )
     292             :     {
     293           0 :         return IVAS_ERROR( IVAS_ERR_LC3PLUS_INVALID_BITRATE, "available LC3plus bitrate <= 0\n" );
     294             :     }
     295             : 
     296           0 :     targetLc3PlusBitratePerChannel = limit_per_channel_bitrate( handle->config, targetLc3PlusBitratePerChannel );
     297           0 :     targetLc3PlusOctetCount = targetLc3PlusBitratePerChannel / 8 / lc3plusPacketRate;
     298             :     /* check resulting octet count. If it requires larger than 1-byte length fields, decrease the bitrate by enough to make room for the additional length field */
     299           0 :     if ( LC3PLUS_RTP_frame_data_length_get_size( &lc3plusFdlLength, targetLc3PlusOctetCount ) != LC3PLUS_RTP_ERR_NO_ERROR )
     300             :     {
     301           0 :         return IVAS_ERROR( IVAS_ERR_INTERNAL, "LC3PLUS_RTP_frame_data_length_get_size failed\n" );
     302             :     }
     303           0 :     if ( lc3plusFdlLength != LC3PLUS_RTP_FDL_MIN_LENGTH )
     304             :     {
     305             :         /* reduce bitrate to allow for the required fdl field */
     306           0 :         targetLc3PlusBitratePerChannel = ( targetLc3PlusOctetCount - ( lc3plusFdlLength - LC3PLUS_RTP_FDL_MIN_LENGTH ) ) / handle->config.channels * 8 * lc3plusPacketRate;
     307             :     }
     308             : 
     309           0 :     for ( int32_t iCh = 0; iCh < handle->config.channels; iCh++ )
     310             :     {
     311           0 :         err = lc3plus_enc_set_bitrate( handle->handles[iCh], targetLc3PlusBitratePerChannel );
     312           0 :         if ( err != LC3PLUS_OK )
     313             :         {
     314           0 :             return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_enc_set_bitrate failed\n" );
     315             :         }
     316             :     }
     317             : 
     318             :     /* update FTD settings after bitrate change */
     319           0 :     for ( int32_t iMediaTime = 0; iMediaTime < numLc3plusMediaTimesPerIvasFrame; ++iMediaTime )
     320             :     {
     321           0 :         for ( uint32_t iEnc = 0; iEnc < handle->num_encs; ++iEnc )
     322             :         {
     323           0 :             iFtd = iEnc + iMediaTime * handle->num_encs;
     324           0 :             lc3plus_num_bytes_per_frame = lc3plus_enc_get_num_bytes( handle->handles[iEnc] );
     325           0 :             if ( lc3plus_num_bytes_per_frame <= 0 )
     326             :             {
     327           0 :                 return IVAS_ERROR( IVAS_ERR_INTERNAL, "lc3plus_enc_get_num_bytes reported invalid result failed\n" );
     328             :             }
     329           0 :             handle->frame_type_descriptors[iFtd].frame_data_length = lc3plus_num_bytes_per_frame;
     330             :         }
     331             :     }
     332             : 
     333           0 :     if ( ( ivas_err = ISAR_LC3PLUS_ENC_GetOutputBitstreamSize( handle, &actualOctetsPerFrame ) ) != IVAS_ERR_OK )
     334             :     {
     335           0 :         return ivas_err;
     336             :     }
     337             : 
     338           0 :     if ( actualOctetsPerFrame > availableOctetsPerIsarFrame )
     339             :     {
     340           0 :         return IVAS_ERROR( IVAS_ERR_INTERNAL, "Bitrate reduction logic failed\n" );
     341             :     }
     342             : 
     343           0 :     return IVAS_ERR_OK;
     344             : }
     345             : 
     346             : 
     347             : /*-------------------------------------------------------------------*
     348             :  * Function ISAR_LC3PLUS_ENC_GetDelay()
     349             :  *
     350             :  *
     351             :  *-------------------------------------------------------------------*/
     352             : 
     353           0 : ivas_error ISAR_LC3PLUS_ENC_GetDelay(
     354             :     ISAR_LC3PLUS_ENC_HANDLE handle, /* i  : LC3plus encoder handle                         */
     355             :     int32_t *delayInSamples         /* o  : encoder delay in number of samples per channel */
     356             : )
     357             : {
     358             :     int32_t tmpDelayInSamples;
     359             : 
     360           0 :     if ( NULL == handle )
     361             :     {
     362           0 :         return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3PLUS_Enc_Wrap_Handle is NULL\n" );
     363             :     }
     364           0 :     if ( NULL == delayInSamples )
     365             :     {
     366           0 :         return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "delayInSamples is NULL\n" );
     367             :     }
     368             : 
     369           0 :     *delayInSamples = 0;
     370             :     /* sanity check whether all encoders are actually configured identically */
     371           0 :     for ( uint32_t iEnc = 0; iEnc < handle->num_encs; iEnc++ )
     372             :     {
     373           0 :         if ( NULL == handle->handles[iEnc] )
     374             :         {
     375           0 :             return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3plus encoder handle is NULL\n" );
     376             :         }
     377             : 
     378           0 :         tmpDelayInSamples = lc3plus_enc_get_delay( handle->handles[iEnc] );
     379           0 :         if ( 0 != *delayInSamples && tmpDelayInSamples != *delayInSamples )
     380             :         {
     381           0 :             return IVAS_ERROR( IVAS_ERR_INTERNAL, "Not all mono LC3plus encoders are configured identically\n" );
     382             :         }
     383           0 :         *delayInSamples = tmpDelayInSamples;
     384             :     }
     385             : 
     386           0 :     return IVAS_ERR_OK;
     387             : }
     388             : 
     389             : 
     390             : /*-------------------------------------------------------------------*
     391             :  * Function ISAR_LC3PLUS_ENC_GetOutputBitstreamSize()
     392             :  *
     393             :  *
     394             :  *-------------------------------------------------------------------*/
     395             : 
     396           0 : ivas_error ISAR_LC3PLUS_ENC_GetOutputBitstreamSize(
     397             :     ISAR_LC3PLUS_ENC_HANDLE handle, /* i  : LC3plus encoder handle                   */
     398             :     int32_t *bsSize                 /* o  : size of each bitstream frame in bytes    */
     399             : )
     400             : {
     401             :     LC3PLUS_RTP_ERR rtp_err;
     402             :     int32_t num_lc3plus_media_times_per_ivas_frame;
     403             :     int32_t iMediaTime;
     404             :     int32_t ftd_frame_data_length_size, lc3plus_frame_data_length;
     405             :     int32_t ftd_index;
     406             : 
     407           0 :     if ( NULL == handle )
     408             :     {
     409           0 :         return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3PLUS_Enc_Wrap_Handle is NULL\n" );
     410             :     }
     411           0 :     if ( NULL == bsSize )
     412             :     {
     413           0 :         return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "bsSize is NULL\n" );
     414             :     }
     415             : 
     416           0 :     if ( 0 == handle->config.lc3plus_frame_duration_us )
     417             :     {
     418           0 :         return IVAS_ERROR( IVAS_ERR_INIT_ERROR, "lc3plus_frame_duration_us is 0\n" );
     419             :     }
     420           0 :     if ( handle->config.isar_frame_duration_us % handle->config.lc3plus_frame_duration_us != 0 )
     421             :     {
     422           0 :         return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "isar_frame_duration_us must be equal or multiple of lc3plus_frame_duration_us \n" );
     423             :     }
     424             : 
     425           0 :     num_lc3plus_media_times_per_ivas_frame = handle->config.isar_frame_duration_us / handle->config.lc3plus_frame_duration_us;
     426             : 
     427           0 :     *bsSize = 0;
     428             :     int32_t fdl_request_length;
     429           0 :     rtp_err = LC3PLUS_RTP_frame_data_length_get_size( &fdl_request_length, handle->fdl_request );
     430           0 :     if ( rtp_err != LC3PLUS_RTP_ERR_NO_ERROR )
     431             :     {
     432           0 :         return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Invalid LC3plus frame_data_length request\n" );
     433             :     }
     434           0 :     *bsSize += fdl_request_length;
     435             : 
     436           0 :     for ( uint32_t iEnc = 0; iEnc < handle->num_encs; iEnc++ )
     437             :     {
     438           0 :         if ( NULL == handle->handles[iEnc] )
     439             :         {
     440           0 :             return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3plus encoder handle is NULL\n" );
     441             :         }
     442             : 
     443           0 :         lc3plus_frame_data_length = lc3plus_enc_get_num_bytes( handle->handles[iEnc] );
     444             : 
     445           0 :         for ( iMediaTime = 0; iMediaTime < num_lc3plus_media_times_per_ivas_frame; ++iMediaTime )
     446             :         {
     447           0 :             ftd_index = iEnc + iMediaTime * handle->num_encs;
     448           0 :             if ( lc3plus_frame_data_length != (int32_t) handle->frame_type_descriptors[ftd_index].frame_data_length )
     449             :             {
     450           0 :                 return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "LC3plus FTD data not synchronised with encoder bitrate\n" );
     451             :             }
     452           0 :             rtp_err = LC3PLUS_RTP_frame_data_length_get_size( &ftd_frame_data_length_size, handle->frame_type_descriptors[ftd_index].frame_data_length );
     453           0 :             if ( rtp_err != LC3PLUS_RTP_ERR_NO_ERROR )
     454             :             {
     455           0 :                 return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Invalid LC3plus frame_data_length\n" );
     456             :             }
     457           0 :             *bsSize += LC3PLUS_RTP_FTD_LENGTH_EXCLUDING_FDL;
     458           0 :             *bsSize += handle->frame_type_descriptors[ftd_index].frame_data_length;
     459           0 :             *bsSize += ftd_frame_data_length_size;
     460             :         }
     461             :     }
     462             : 
     463           0 :     return IVAS_ERR_OK;
     464             : }
     465             : 
     466             : 
     467             : /*-------------------------------------------------------------------*
     468             :  * Function ISAR_LC3PLUS_ENC_Close()
     469             :  *
     470             :  *
     471             :  *-------------------------------------------------------------------*/
     472             : 
     473           0 : void ISAR_LC3PLUS_ENC_Close(
     474             :     ISAR_LC3PLUS_ENC_HANDLE *handle /* i/o: pointer to LC3plus encoder handle   */
     475             : )
     476             : {
     477           0 :     if ( NULL == handle || NULL == *handle )
     478             :     {
     479           0 :         return;
     480             :     }
     481             : 
     482           0 :     if ( NULL != ( *handle )->frame_type_descriptors )
     483             :     {
     484           0 :         free( ( *handle )->frame_type_descriptors );
     485             :     }
     486             : 
     487           0 :     for ( uint32_t iEnc = 0; iEnc < ( *handle )->num_encs; iEnc++ )
     488             :     {
     489           0 :         if ( NULL != ( *handle )->handles[iEnc] )
     490             :         {
     491           0 :             lc3plus_free_encoder_structs( ( *handle )->handles[iEnc] );
     492           0 :             free( ( *handle )->handles[iEnc] );
     493             :         }
     494             :     }
     495             : 
     496           0 :     if ( NULL != ( *handle )->pcm_conversion_buffer )
     497             :     {
     498           0 :         free( ( *handle )->pcm_conversion_buffer );
     499             :     }
     500             : 
     501           0 :     free( ( *handle )->handles );
     502           0 :     free( *handle );
     503             : 
     504           0 :     *handle = NULL;
     505             : 
     506           0 :     return;
     507             : }
     508             : 
     509             : 
     510             : /*-------------------------------------------------------------------*
     511             :  * Function ISAR_LC3PLUS_ENC_Encode()
     512             :  *
     513             :  *
     514             :  *-------------------------------------------------------------------*/
     515             : 
     516           0 : ivas_error ISAR_LC3PLUS_ENC_Encode(
     517             :     ISAR_LC3PLUS_ENC_HANDLE handle,  /* i  : LC3plus encoder handle      */
     518             :     float **pcm_in,                  /* i  : pointer input samples       */
     519             :     void *bitstream_out,             /* o  : pointer to bitstream frame                       */
     520             :     const int32_t bitstream_out_size /* i  : size of the bitstream_out buffer in bytes. Must be equal to ISAR_LC3PLUS_ENC_GetOutputBitstreamSize. */
     521             : )
     522             : {
     523             :     int32_t ftdIndex;
     524             :     LC3PLUS_RTP_ERR rtpErr;
     525             :     uint32_t num_media_times;
     526             :     uint32_t numSamplesPerLC3plusChannel;
     527             :     int32_t ivasSampleIndex;
     528           0 :     int32_t num_bytes = 0;
     529             :     LC3PLUS_Error err;
     530             : 
     531           0 :     push_wmops( "ISAR_LC3PLUS_ENC_Encode" );
     532             : 
     533           0 :     if ( NULL == handle )
     534             :     {
     535           0 :         return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3PLUS_Enc_Wrap_Handle is NULL\n" );
     536             :     }
     537           0 :     if ( NULL == pcm_in )
     538             :     {
     539           0 :         return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "pcm_in is NULL\n" );
     540             :     }
     541           0 :     if ( NULL == bitstream_out )
     542             :     {
     543           0 :         return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "bitstream_out is NULL\n" );
     544             :     }
     545             : 
     546           0 :     if ( handle->config.isar_frame_duration_us % handle->config.lc3plus_frame_duration_us != 0 )
     547             :     {
     548           0 :         return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "isar_frame_duration_us must be equal or multiple of lc3plus_frame_duration_us \n" );
     549             :     }
     550             : 
     551           0 :     num_media_times = handle->config.isar_frame_duration_us / handle->config.lc3plus_frame_duration_us;
     552           0 :     numSamplesPerLC3plusChannel = handle->config.samplerate / ( 1000000 / handle->config.isar_frame_duration_us ) / num_media_times;
     553             : 
     554             :     size_t actual_size;
     555           0 :     rtpErr = LC3PLUS_RTP_payload_serialize( bitstream_out, bitstream_out_size, &actual_size, s_fdl_request, handle->frame_type_descriptors, handle->num_ftds );
     556           0 :     if ( rtpErr != LC3PLUS_RTP_ERR_NO_ERROR )
     557             :     {
     558           0 :         return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( rtpErr ), "LC3PLUS_RTP_payload_serialize failed\n" );
     559             :     }
     560           0 :     for ( uint32_t iEnc = 0; iEnc < handle->num_encs; iEnc++ )
     561             :     {
     562           0 :         for ( uint32_t iMediaTime = 0; iMediaTime < num_media_times; iMediaTime++ )
     563             :         {
     564           0 :             for ( uint32_t iSampleInt16 = 0; iSampleInt16 < numSamplesPerLC3plusChannel; iSampleInt16++ )
     565             :             {
     566           0 :                 ivasSampleIndex = iSampleInt16 + iMediaTime * numSamplesPerLC3plusChannel;
     567           0 :                 handle->pcm_conversion_buffer[iSampleInt16] = (int16_t) max( INT16_MIN, min( pcm_in[iEnc][ivasSampleIndex], INT16_MAX ) );
     568             :             }
     569             : 
     570           0 :             ftdIndex = iMediaTime * handle->num_encs + iEnc;
     571           0 :             num_bytes = 0;
     572           0 :             push_wmops( "lc3plus_enc16" );
     573           0 :             err = lc3plus_enc16( handle->handles[iEnc], &handle->pcm_conversion_buffer, handle->frame_type_descriptors[ftdIndex].frame_data, &num_bytes, NULL );
     574           0 :             pop_wmops();
     575             : 
     576           0 :             if ( err != LC3PLUS_OK )
     577             :             {
     578           0 :                 return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_enc16 failed\n" );
     579             :             }
     580             : 
     581           0 :             if ( 0 == num_bytes )
     582             :             {
     583           0 :                 return IVAS_ERROR( IVAS_ERR_INTERNAL, "lc3plus_enc16 did not produce output\n" );
     584             :             }
     585             : 
     586           0 :             if ( num_bytes != (int32_t) handle->frame_type_descriptors[ftdIndex].frame_data_length )
     587             :             {
     588           0 :                 return IVAS_ERROR( IVAS_ERR_INTERNAL, "payload format and lc3plus enc bitrate are not aligned\n" );
     589             :             }
     590             :         }
     591             :     }
     592             : 
     593           0 :     pop_wmops();
     594             : 
     595           0 :     return IVAS_ERR_OK;
     596             : }

Generated by: LCOV version 1.14