LCOV - code coverage report
Current view: top level - lib_isar - isar_lc3plus_enc.c (source / functions) Hit Total Coverage
Test: Coverage on main -- dec/rend @ 633e3f2e309758d10805ef21e0436356fe719b7a Lines: 0 230 0.0 %
Date: 2025-08-23 01:22:27 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_fx.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( LC3PLUS_CONFIG config,
      44             :                                           int32_t per_channel_bitrate )
      45             : {
      46           0 :     if ( config.high_res_mode_enabled )
      47             :     {
      48           0 :         switch ( config.lc3plus_frame_duration_us )
      49             :         {
      50           0 :             case 10000:
      51           0 :                 return min( per_channel_bitrate, 500000 );
      52           0 :             case 5000:
      53           0 :                 return min( per_channel_bitrate, 600000 );
      54           0 :             case 2500:
      55           0 :                 return min( per_channel_bitrate, 672000 );
      56           0 :             default:
      57           0 :                 assert( false && "unreachable" );
      58             :         }
      59             :     }
      60             : 
      61           0 :     switch ( config.samplerate )
      62             :     {
      63           0 :         case 48000:
      64             :         case 32000:
      65           0 :             return min( per_channel_bitrate, 320000 );
      66           0 :         case 24000:
      67           0 :             return min( per_channel_bitrate, 314400 );
      68           0 :         case 16000:
      69           0 :             return min( per_channel_bitrate, 221600 );
      70           0 :         case 8000:
      71           0 :             return min( per_channel_bitrate, 114400 );
      72           0 :         default:
      73           0 :             assert( false && "unreachable" );
      74             :     }
      75             : 
      76             :     assert( false && "unreachable" );
      77             :     return -1;
      78             : }
      79             : 
      80             : /*-------------------------------------------------------------------*
      81             :  * Function ISAR_LC3PLUS_ENC_Open()
      82             :  *
      83             :  *
      84             :  *-------------------------------------------------------------------*/
      85           0 : ivas_error ISAR_LC3PLUS_ENC_Open(
      86             :     const LC3PLUS_CONFIG config,    /* i  : LC3plus encoder configuration   */
      87             :     const UWord32 bitsPerSecond,    /* i  : bit rate                        */
      88             :     ISAR_LC3PLUS_ENC_HANDLE *handle /* o  : encoder handle                  */
      89             : )
      90             : {
      91             :     int32_t num_lc3plus_media_times_per_ivas_frame;
      92             :     bool is_last_media_time, is_last_channel;
      93             :     ivas_error ivas_err;
      94             :     Word32 scratch_size;
      95             :     int32_t encoder_size;
      96             :     LC3PLUS_Error err;
      97             :     int32_t lfeChans[1];
      98             :     int16_t i;
      99             : 
     100           0 :     lfeChans[0] = 0;
     101             : 
     102           0 :     if ( 0U == config.channels )
     103             :     {
     104           0 :         return IVAS_ERROR( IVAS_ERR_INTERNAL, "Invalid number of channels\n" );
     105             :     }
     106           0 :     if ( config.lc3plus_frame_duration_us != 2500 && config.lc3plus_frame_duration_us != 5000 && config.lc3plus_frame_duration_us != 10000 )
     107             :     {
     108           0 :         return IVAS_ERROR( IVAS_ERR_INTERNAL, "Invalid lc3plus_frame_duration_us\n" );
     109             :     }
     110           0 :     if ( config.isar_frame_duration_us != 20000 && config.isar_frame_duration_us != 10000 && config.isar_frame_duration_us != 5000 )
     111             :     {
     112           0 :         return IVAS_ERROR( IVAS_ERR_INTERNAL, "Invalid isar_frame_duration_us\n" );
     113             :     }
     114           0 :     encoder_size = lc3plus_enc_get_size( config.samplerate, 1 );
     115           0 :     if ( 0 == encoder_size )
     116             :     {
     117           0 :         return IVAS_ERROR( IVAS_ERR_INTERNAL, "lc3plus_enc_get_size failed\n" );
     118             :     }
     119             : 
     120           0 :     if ( ( *handle = malloc( sizeof( struct ISAR_LC3PLUS_ENC_HANDLE ) ) ) == NULL )
     121             :     {
     122           0 :         return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus wrapper handle\n" );
     123             :     }
     124           0 :     ( *handle )->config = config;
     125           0 :     ( *handle )->frame_type_descriptors = NULL;
     126             : 
     127           0 :     ( *handle )->pcm_conversion_buffer = NULL;
     128           0 :     ( *handle )->scratch = NULL;
     129           0 :     ( *handle )->num_encs = 0;
     130           0 :     if ( ( ( *handle )->handles = malloc( config.channels * sizeof( ISAR_LC3PLUS_ENC_HANDLE ) ) ) == NULL )
     131             :     {
     132           0 :         ISAR_LC3PLUS_ENC_Close( handle );
     133           0 :         return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus wrapper handle\n" );
     134             :     }
     135             : 
     136           0 :     for ( i = 0; i < config.channels; ++i )
     137             :     {
     138           0 :         ( *handle )->handles[i] = NULL;
     139             :     }
     140           0 :     ( *handle )->num_encs = config.channels;
     141           0 :     num_lc3plus_media_times_per_ivas_frame = config.isar_frame_duration_us / config.lc3plus_frame_duration_us;
     142           0 :     ( *handle )->fdl_request = s_fdl_request;
     143           0 :     ( *handle )->num_ftds = config.channels * num_lc3plus_media_times_per_ivas_frame;
     144           0 :     ( *handle )->frame_type_descriptors = malloc( ( *handle )->num_ftds * sizeof( LC3PLUS_RTP_FTD ) );
     145           0 :     if ( NULL == ( *handle )->frame_type_descriptors )
     146             :     {
     147           0 :         ISAR_LC3PLUS_ENC_Close( handle );
     148           0 :         return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus frame_type_descriptors\n" );
     149             :     }
     150             : 
     151           0 :     for ( int32_t iCh = 0; iCh < config.channels; iCh++ )
     152             :     {
     153           0 :         if ( ( ( *handle )->handles[iCh] = malloc( encoder_size ) ) == NULL )
     154             :         {
     155           0 :             ISAR_LC3PLUS_ENC_Close( handle );
     156           0 :             return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus encoder\n" );
     157             :         }
     158             : 
     159           0 :         err = lc3plus_enc_init( ( *handle )->handles[iCh], config.samplerate, 1, config.high_res_mode_enabled, lfeChans );
     160           0 :         if ( err != LC3PLUS_OK )
     161             :         {
     162           0 :             ISAR_LC3PLUS_ENC_Close( handle );
     163           0 :             return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_enc_init failed\n" );
     164             :         }
     165             : 
     166           0 :         err = lc3plus_enc_set_frame_dms( ( *handle )->handles[iCh], config.lc3plus_frame_duration_us / 100 );
     167           0 :         if ( err != LC3PLUS_OK )
     168             :         {
     169           0 :             ISAR_LC3PLUS_ENC_Close( handle );
     170           0 :             return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_enc_set_frame_dms failed\n" );
     171             :         }
     172             :     }
     173             : 
     174           0 :     if ( config.isar_frame_duration_us < config.lc3plus_frame_duration_us || config.isar_frame_duration_us % config.lc3plus_frame_duration_us != 0 )
     175             :     {
     176           0 :         ISAR_LC3PLUS_ENC_Close( handle );
     177           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" );
     178             :     }
     179             : 
     180           0 :     ( *handle )->pcm_conversion_buffer = malloc( sizeof( int16_t ) * config.samplerate * config.lc3plus_frame_duration_us / 1000000 );
     181           0 :     if ( NULL == ( *handle )->pcm_conversion_buffer )
     182             :     {
     183           0 :         ISAR_LC3PLUS_ENC_Close( handle );
     184           0 :         return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus encoder wrapper pcm_conversion_buffer\n" );
     185             :     }
     186             : 
     187             :     /* update FDI fields */
     188           0 :     for ( int32_t iMediaTime = 0; iMediaTime < num_lc3plus_media_times_per_ivas_frame; ++iMediaTime )
     189             :     {
     190           0 :         for ( uint32_t iEnc = 0; iEnc < ( *handle )->num_encs; ++iEnc )
     191             :         {
     192           0 :             int32_t ftd_index = iEnc + iMediaTime * ( *handle )->num_encs;
     193           0 :             ( *handle )->frame_type_descriptors[ftd_index].frame_data_length = 0; /* will be set to the correct value in IVAS_LC3PLUS_ENC_SetBitrate */
     194           0 :             if ( 0 != LC3PLUS_RTP_ftd_bwr_from_samplerate( &( *handle )->frame_type_descriptors[ftd_index].bwr, config.samplerate, config.high_res_mode_enabled ) )
     195             :             {
     196           0 :                 ISAR_LC3PLUS_ENC_Close( handle );
     197           0 :                 return IVAS_ERROR( IVAS_ERR_INTERNAL, "LC3PLUS_RTP_ftd_bwr_from_samplerate failed\n" );
     198             :             }
     199           0 :             if ( 0 != LC3PLUS_RTP_ftd_fdi_from_frame_duration_us( &( *handle )->frame_type_descriptors[ftd_index].fdi, config.lc3plus_frame_duration_us ) )
     200             :             {
     201           0 :                 ISAR_LC3PLUS_ENC_Close( handle );
     202           0 :                 return IVAS_ERROR( IVAS_ERR_INTERNAL, "LC3PLUS_RTP_ftd_fdi_from_frame_duration_us failed\n" );
     203             :             }
     204           0 :             ( *handle )->frame_type_descriptors[ftd_index].h = LC3PLUS_RTP_FTD_H_PRIMARY;
     205           0 :             ( *handle )->frame_type_descriptors[ftd_index].frame_data = NULL;
     206             : 
     207             :             /* The FTDs in the ToC are included in the following order:
     208             :              * 1) First the FTD for the first channel of the first FDB (oldest frame)
     209             :              * 2) Then the FTDs for the remaining channels for the first FDB in increasing CC order
     210             :              * 3) Then the FTD for the first channel of the second FDB
     211             :              * 4) Then the FTDs for the remaining channels for the second FDB
     212             :              * 5) Etc. to the last FDB */
     213           0 :             is_last_media_time = num_lc3plus_media_times_per_ivas_frame - 1 == iMediaTime;
     214           0 :             is_last_channel = ( *handle )->num_encs - 1 == iEnc;
     215           0 :             if ( is_last_media_time && is_last_channel )
     216             :             {
     217           0 :                 ( *handle )->frame_type_descriptors[ftd_index].fc = LC3PLUS_RTP_FTD_FC_LAST_OVERALL;
     218             :             }
     219           0 :             else if ( !is_last_media_time && is_last_channel )
     220             :             {
     221           0 :                 ( *handle )->frame_type_descriptors[ftd_index].fc = LC3PLUS_RTP_FTD_FC_LAST_IN_MEDIATIME;
     222             :             }
     223             :             else
     224             :             {
     225           0 :                 ( *handle )->frame_type_descriptors[ftd_index].fc = LC3PLUS_RTP_FTD_FC_SUBSEQUENT_CHANNEL;
     226             :             }
     227             :         }
     228             :     }
     229             : 
     230           0 :     ivas_err = IVAS_LC3PLUS_ENC_SetBitrate( *handle, bitsPerSecond );
     231           0 :     if ( ivas_err != IVAS_ERR_OK )
     232             :     {
     233           0 :         ISAR_LC3PLUS_ENC_Close( handle );
     234           0 :         return ivas_err;
     235             :     }
     236           0 :     scratch_size = lc3plus_enc_get_scratch_size( ( *handle )->handles[0] );
     237           0 :     ( *handle )->scratch = malloc( sizeof( uint8_t ) * scratch_size );
     238           0 :     IF( NULL == ( *handle )->scratch )
     239             :     {
     240           0 :         ISAR_LC3PLUS_ENC_Close( handle );
     241           0 :         return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LC3plus encoder wrapper scratch\n" );
     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 UWord32 bitsPerSecond     /* i  : new target bit rate                              */
     256             : )
     257             : {
     258             :     Word32 numLc3plusMediaTimesPerIvasFrame;
     259             :     Word32 lc3plus_num_bytes_per_frame;
     260             :     Word32 availableOctetsPerIsarFrame;
     261             :     Word32 actualOctetsPerFrame;
     262             :     LC3PLUS_Error err;
     263             :     ivas_error ivas_err;
     264             :     Word32 iFtd;
     265             :     Word32 fdrLength;
     266             :     Word32 lc3plusPacketRate;
     267             :     Word32 numSubframes;
     268             :     Word32 minPayloadOverhead;
     269             :     Word32 targetLc3PlusBitratePerChannel;
     270             :     Word32 targetLc3PlusOctetCount;
     271             :     Word32 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           0 :     if ( targetLc3PlusBitratePerChannel <= 0 )
     291             :     {
     292           0 :         return IVAS_ERROR( IVAS_ERR_LC3PLUS_INVALID_BITRATE, "available LC3plus bitrate <= 0\n" );
     293             :     }
     294           0 :     targetLc3PlusBitratePerChannel = limit_per_channel_bitrate( handle->config, targetLc3PlusBitratePerChannel );
     295           0 :     targetLc3PlusOctetCount = targetLc3PlusBitratePerChannel / 8 / lc3plusPacketRate;
     296             :     /* 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 */
     297           0 :     if ( LC3PLUS_RTP_frame_data_length_get_size( &lc3plusFdlLength, targetLc3PlusOctetCount ) != LC3PLUS_RTP_ERR_NO_ERROR )
     298             :     {
     299           0 :         return IVAS_ERROR( IVAS_ERR_INTERNAL, "LC3PLUS_RTP_frame_data_length_get_size failed\n" );
     300             :     }
     301           0 :     if ( lc3plusFdlLength != LC3PLUS_RTP_FDL_MIN_LENGTH )
     302             :     {
     303             :         /* reduce bitrate to allow for the required fdl field */
     304           0 :         targetLc3PlusBitratePerChannel = ( targetLc3PlusOctetCount - ( lc3plusFdlLength - LC3PLUS_RTP_FDL_MIN_LENGTH ) ) / handle->config.channels * 8 * lc3plusPacketRate;
     305             :     }
     306             : 
     307           0 :     for ( Word32 iCh = 0; iCh < handle->config.channels; iCh++ )
     308             :     {
     309           0 :         err = lc3plus_enc_set_bitrate( handle->handles[iCh], targetLc3PlusBitratePerChannel );
     310           0 :         if ( err != LC3PLUS_OK )
     311             :         {
     312           0 :             return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_enc_set_bitrate failed\n" );
     313             :         }
     314             :     }
     315             : 
     316             :     /* update FTD settings after bitrate change */
     317           0 :     for ( int32_t iMediaTime = 0; iMediaTime < numLc3plusMediaTimesPerIvasFrame; ++iMediaTime )
     318             :     {
     319           0 :         for ( UWord32 iEnc = 0; iEnc < handle->num_encs; ++iEnc )
     320             :         {
     321           0 :             iFtd = iEnc + iMediaTime * handle->num_encs;
     322           0 :             lc3plus_num_bytes_per_frame = lc3plus_enc_get_num_bytes( handle->handles[iEnc] );
     323           0 :             if ( lc3plus_num_bytes_per_frame <= 0 )
     324             :             {
     325           0 :                 return IVAS_ERROR( IVAS_ERR_INTERNAL, "lc3plus_enc_get_num_bytes reported invalid result failed\n" );
     326             :             }
     327           0 :             handle->frame_type_descriptors[iFtd].frame_data_length = lc3plus_num_bytes_per_frame;
     328             :         }
     329             :     }
     330             : 
     331           0 :     if ( ( ivas_err = ISAR_LC3PLUS_ENC_GetOutputBitstreamSize( handle, &actualOctetsPerFrame ) ) != IVAS_ERR_OK )
     332             :     {
     333           0 :         return ivas_err;
     334             :     }
     335             : 
     336           0 :     if ( actualOctetsPerFrame > availableOctetsPerIsarFrame )
     337             :     {
     338           0 :         return IVAS_ERROR( IVAS_ERR_INTERNAL, "Bitrate reduction logic failed\n" );
     339             :     }
     340             : 
     341           0 :     return IVAS_ERR_OK;
     342             : }
     343             : 
     344             : 
     345             : /*-------------------------------------------------------------------*
     346             :  * Function ISAR_LC3PLUS_ENC_GetDelay()
     347             :  *
     348             :  *
     349             :  *-------------------------------------------------------------------*/
     350             : 
     351           0 : ivas_error ISAR_LC3PLUS_ENC_GetDelay(
     352             :     ISAR_LC3PLUS_ENC_HANDLE handle, /* i  : LC3plus encoder handle                         */
     353             :     Word32 *delayInSamples          /* o  : encoder delay in number of samples per channel */
     354             : )
     355             : {
     356             :     Word32 tmpDelayInSamples;
     357             : 
     358           0 :     if ( NULL == handle )
     359             :     {
     360           0 :         return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3PLUS_Enc_Wrap_Handle is NULL\n" );
     361             :     }
     362           0 :     if ( NULL == delayInSamples )
     363             :     {
     364           0 :         return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "delayInSamples is NULL\n" );
     365             :     }
     366             : 
     367           0 :     *delayInSamples = 0;
     368             :     /* sanity check whether all encoders are actually configured identically */
     369           0 :     for ( UWord32 iEnc = 0; iEnc < handle->num_encs; iEnc++ )
     370             :     {
     371           0 :         if ( NULL == handle->handles[iEnc] )
     372             :         {
     373           0 :             return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3plus encoder handle is NULL\n" );
     374             :         }
     375             : 
     376           0 :         tmpDelayInSamples = lc3plus_enc_get_delay( handle->handles[iEnc] );
     377           0 :         if ( 0 != *delayInSamples && tmpDelayInSamples != *delayInSamples )
     378             :         {
     379           0 :             return IVAS_ERROR( IVAS_ERR_INTERNAL, "Not all mono LC3plus encoders are configured identically\n" );
     380             :         }
     381           0 :         *delayInSamples = tmpDelayInSamples;
     382             :     }
     383             : 
     384           0 :     return IVAS_ERR_OK;
     385             : }
     386             : 
     387             : 
     388             : /*-------------------------------------------------------------------*
     389             :  * Function ISAR_LC3PLUS_ENC_GetOutputBitstreamSize()
     390             :  *
     391             :  *
     392             :  *-------------------------------------------------------------------*/
     393             : 
     394           0 : ivas_error ISAR_LC3PLUS_ENC_GetOutputBitstreamSize(
     395             :     ISAR_LC3PLUS_ENC_HANDLE handle, /* i  : LC3plus encoder handle                   */
     396             :     Word32 *bsSize                  /* o  : size of each bitstream frame in bytes    */
     397             : )
     398             : {
     399             :     LC3PLUS_RTP_ERR rtp_err;
     400             :     int32_t num_lc3plus_media_times_per_ivas_frame;
     401             :     int32_t iMediaTime;
     402             :     int32_t ftd_frame_data_length_size, lc3plus_frame_data_length;
     403             :     int32_t ftd_index;
     404           0 :     if ( NULL == handle )
     405             :     {
     406           0 :         return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3PLUS_Enc_Wrap_Handle is NULL\n" );
     407             :     }
     408           0 :     if ( NULL == bsSize )
     409             :     {
     410           0 :         return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "bsSize is NULL\n" );
     411             :     }
     412             : 
     413           0 :     if ( 0 == handle->config.lc3plus_frame_duration_us )
     414             :     {
     415           0 :         return IVAS_ERROR( IVAS_ERR_INIT_ERROR, "lc3plus_frame_duration_us is 0\n" );
     416             :     }
     417           0 :     if ( handle->config.isar_frame_duration_us % handle->config.lc3plus_frame_duration_us != 0 )
     418             :     {
     419           0 :         return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "isar_frame_duration_us must be equal or multiple of lc3plus_frame_duration_us \n" );
     420             :     }
     421             : 
     422           0 :     num_lc3plus_media_times_per_ivas_frame = handle->config.isar_frame_duration_us / handle->config.lc3plus_frame_duration_us;
     423           0 :     *bsSize = 0;
     424             :     int32_t fdl_request_length;
     425           0 :     rtp_err = LC3PLUS_RTP_frame_data_length_get_size( &fdl_request_length, handle->fdl_request );
     426           0 :     if ( rtp_err != LC3PLUS_RTP_ERR_NO_ERROR )
     427             :     {
     428           0 :         return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Invalid LC3plus frame_data_length request\n" );
     429             :     }
     430           0 :     *bsSize += fdl_request_length;
     431           0 :     for ( uint32_t iEnc = 0; iEnc < handle->num_encs; iEnc++ )
     432             :     {
     433           0 :         if ( NULL == handle->handles[iEnc] )
     434             :         {
     435           0 :             return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3plus encoder handle is NULL\n" );
     436             :         }
     437           0 :         lc3plus_frame_data_length = lc3plus_enc_get_num_bytes( handle->handles[iEnc] );
     438           0 :         for ( iMediaTime = 0; iMediaTime < num_lc3plus_media_times_per_ivas_frame; ++iMediaTime )
     439             :         {
     440           0 :             ftd_index = iEnc + iMediaTime * handle->num_encs;
     441           0 :             if ( lc3plus_frame_data_length != (int32_t) handle->frame_type_descriptors[ftd_index].frame_data_length )
     442             :             {
     443           0 :                 return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "LC3plus FTD data not synchronised with encoder bitrate\n" );
     444             :             }
     445           0 :             rtp_err = LC3PLUS_RTP_frame_data_length_get_size( &ftd_frame_data_length_size, handle->frame_type_descriptors[ftd_index].frame_data_length );
     446           0 :             if ( rtp_err != LC3PLUS_RTP_ERR_NO_ERROR )
     447             :             {
     448           0 :                 return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Invalid LC3plus frame_data_length\n" );
     449             :             }
     450           0 :             *bsSize += LC3PLUS_RTP_FTD_LENGTH_EXCLUDING_FDL;
     451           0 :             *bsSize += handle->frame_type_descriptors[ftd_index].frame_data_length;
     452           0 :             *bsSize += ftd_frame_data_length_size;
     453             :         }
     454             :     }
     455             : 
     456           0 :     return IVAS_ERR_OK;
     457             : }
     458             : 
     459             : 
     460             : /*-------------------------------------------------------------------*
     461             :  * Function ISAR_LC3PLUS_ENC_Close()
     462             :  *
     463             :  *
     464             :  *-------------------------------------------------------------------*/
     465             : 
     466           0 : void ISAR_LC3PLUS_ENC_Close(
     467             :     ISAR_LC3PLUS_ENC_HANDLE *handle /* i/o: pointer to LC3plus encoder handle   */
     468             : )
     469             : {
     470           0 :     if ( NULL == handle || NULL == *handle )
     471             :     {
     472           0 :         return;
     473             :     }
     474           0 :     if ( NULL != ( *handle )->frame_type_descriptors )
     475             :     {
     476           0 :         free( ( *handle )->frame_type_descriptors );
     477             :     }
     478           0 :     for ( UWord32 iEnc = 0; iEnc < ( *handle )->num_encs; iEnc++ )
     479             :     {
     480           0 :         if ( NULL != ( *handle )->handles[iEnc] )
     481             :         {
     482           0 :             free( ( *handle )->handles[iEnc] );
     483             :         }
     484             :     }
     485           0 :     if ( NULL != ( *handle )->pcm_conversion_buffer )
     486             :     {
     487           0 :         free( ( *handle )->pcm_conversion_buffer );
     488             :     }
     489             : 
     490           0 :     if ( NULL != ( *handle )->scratch )
     491             :     {
     492           0 :         free( ( *handle )->scratch );
     493             :     }
     494             : 
     495           0 :     free( ( *handle )->handles );
     496           0 :     free( *handle );
     497             : 
     498           0 :     *handle = NULL;
     499             : 
     500           0 :     return;
     501             : }
     502             : 
     503             : 
     504             : /*-------------------------------------------------------------------*
     505             :  * Function ISAR_LC3PLUS_ENC_Encode()
     506             :  *
     507             :  *
     508             :  *-------------------------------------------------------------------*/
     509             : 
     510           0 : ivas_error ISAR_LC3PLUS_ENC_Encode(
     511             :     ISAR_LC3PLUS_ENC_HANDLE handle,  /* i  : LC3plus encoder handle                           */
     512             :     Word32 **pcm_in,                 /* i  : pointer input samples                            */
     513             :     void *bitstream_out,             /* o  : pointer to bitstream frame                       */
     514             :     const Word32 bitstream_out_size, /* i  : size of the bitstream_out buffer in bytes. Must be equal to ISAR_LC3PLUS_ENC_GetOutputBitstreamSize. */
     515             :     Word16 q_in[16] )
     516             : {
     517             :     Word32 ftdIndex;
     518             :     LC3PLUS_RTP_ERR rtpErr;
     519             :     UWord32 num_media_times;
     520             :     UWord32 numSamplesPerLC3plusChannel;
     521             :     Word32 ivasSampleIndex;
     522           0 :     Word32 num_bytes = 0;
     523             :     LC3PLUS_Error err;
     524             : 
     525           0 :     push_wmops( "ISAR_LC3PLUS_ENC_Encode" );
     526             : 
     527           0 :     if ( NULL == handle )
     528             :     {
     529           0 :         return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "LC3PLUS_Enc_Wrap_Handle is NULL\n" );
     530             :     }
     531           0 :     if ( NULL == pcm_in )
     532             :     {
     533           0 :         return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "pcm_in is NULL\n" );
     534             :     }
     535           0 :     if ( NULL == bitstream_out )
     536             :     {
     537           0 :         return IVAS_ERROR( IVAS_ERR_UNEXPECTED_NULL_POINTER, "bitstream_out is NULL\n" );
     538             :     }
     539             : 
     540           0 :     if ( handle->config.isar_frame_duration_us % handle->config.lc3plus_frame_duration_us != 0 )
     541             :     {
     542           0 :         return IVAS_ERROR( IVAS_ERR_NOT_IMPLEMENTED, "isar_frame_duration_us must be equal or multiple of lc3plus_frame_duration_us \n" );
     543             :     }
     544           0 :     num_media_times = handle->config.isar_frame_duration_us / handle->config.lc3plus_frame_duration_us;
     545           0 :     numSamplesPerLC3plusChannel = handle->config.samplerate / ( 1000000 / handle->config.isar_frame_duration_us ) / num_media_times;
     546             : 
     547             :     size_t actual_size;
     548           0 :     rtpErr = LC3PLUS_RTP_payload_serialize( bitstream_out, bitstream_out_size, &actual_size, s_fdl_request, handle->frame_type_descriptors, handle->num_ftds );
     549           0 :     if ( rtpErr != LC3PLUS_RTP_ERR_NO_ERROR )
     550             :     {
     551           0 :         return IVAS_ERROR( IVAS_LC3PLUS_LC3plusRtpErrToIvasErr( rtpErr ), "LC3PLUS_RTP_payload_serialize failed\n" );
     552             :     }
     553             : 
     554           0 :     FOR( UWord32 iEnc = 0; iEnc < handle->num_encs; iEnc++ )
     555             :     {
     556           0 :         FOR( UWord32 iMediaTime = 0; iMediaTime < num_media_times; iMediaTime++ )
     557             :         {
     558           0 :             FOR( UWord32 iSampleInt16 = 0; iSampleInt16 < numSamplesPerLC3plusChannel; iSampleInt16++ )
     559             :             {
     560           0 :                 ivasSampleIndex = iSampleInt16 + iMediaTime * numSamplesPerLC3plusChannel;
     561           0 :                 handle->pcm_conversion_buffer[iSampleInt16] = (Word16) max( INT16_MIN, min( L_shr( pcm_in[iEnc][ivasSampleIndex], q_in[iEnc] ), INT16_MAX ) );
     562             :             }
     563             : 
     564           0 :             ftdIndex = iMediaTime * handle->num_encs + iEnc;
     565           0 :             num_bytes = 0;
     566           0 :             push_wmops( "lc3plus_enc16" );
     567           0 :             err = lc3plus_enc16( handle->handles[iEnc], &handle->pcm_conversion_buffer, handle->frame_type_descriptors[ftdIndex].frame_data, &num_bytes, handle->scratch );
     568           0 :             pop_wmops();
     569           0 :             if ( err != LC3PLUS_OK )
     570             :             {
     571           0 :                 return IVAS_ERROR( ISAR_LC3PLUS_LC3plusErrToIvasErr( err ), "lc3plus_enc16 failed\n" );
     572             :             }
     573           0 :             if ( 0 == num_bytes )
     574             :             {
     575           0 :                 return IVAS_ERROR( IVAS_ERR_INTERNAL, "lc3plus_enc16 did not produce output\n" );
     576             :             }
     577           0 :             if ( num_bytes != (int32_t) handle->frame_type_descriptors[ftdIndex].frame_data_length )
     578             :             {
     579           0 :                 return IVAS_ERROR( IVAS_ERR_INTERNAL, "payload format and lc3plus enc bitrate are not aligned\n" );
     580             :             }
     581             :         }
     582             :     }
     583             : 
     584           0 :     pop_wmops();
     585             : 
     586           0 :     return IVAS_ERR_OK;
     587             : }

Generated by: LCOV version 1.14