LCOV - code coverage report
Current view: top level - lib_enc - ivas_ism_metadata_enc_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 660 694 95.1 %
Date: 2025-05-03 01:55:50 Functions: 7 7 100.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 <stdint.h>
      34             : #include <stdio.h>
      35             : #include <string.h>
      36             : #include "options.h"
      37             : #include "ivas_cnst.h"
      38             : #include "ivas_prot_fx.h"
      39             : #include "ivas_rom_com.h"
      40             : #include "prot_fx.h"
      41             : #include <math.h>
      42             : #include "wmc_auto.h"
      43             : #include "ivas_prot_fx.h"
      44             : #include "ivas_rom_com_fx.h"
      45             : 
      46             : 
      47             : /*-----------------------------------------------------------------------*
      48             :  * Local constants
      49             :  *-----------------------------------------------------------------------*/
      50             : 
      51             : #define ISM_NUM_PARAM 5 /* number of coded metadata parameters */
      52             : 
      53             : #define ISM_MAX_AZIMUTH_DIFF_IDX   ( ISM_AZIMUTH_NBITS - 1 /*zero*/ - 1 /*sign*/ )
      54             : #define ISM_MAX_ELEVATION_DIFF_IDX ( ISM_ELEVATION_NBITS - 1 /*zero*/ - 1 /*sign*/ )
      55             : #define ISM_MAX_RADIUS_DIFF_IDX    ( ISM_RADIUS_NBITS - 1 /*zero*/ - 1 /*sign*/ )
      56             : 
      57             : #define ISM_FEC_MAX             10
      58             : #define ISM_MD_FEC_DIFF         10
      59             : #define ISM_MD_FEC_DIFF_Q22     41943040
      60             : #define ISM_MD_INC_DIFF_CNT_MAX 6
      61             : #define ISM_MD_FEC_CNT_MAX      25
      62             : #define ISM_MD_RAD_FEC_DIFF     1
      63             : #define ISM_MD_RAD_FEC_DIFF_Q9  ONE_IN_Q9
      64             : 
      65             : #define INTER_OBJECT_PARAM_CHECK ( ( ISM_FEC_MAX / 2 ) - 2 ) /* note: constant must be less than (ISM_FEC_MAX / number of coded parameters)  */
      66             : 
      67             : 
      68             : /*-----------------------------------------------------------------------*
      69             :  * Local function declarations
      70             :  *-----------------------------------------------------------------------*/
      71             : 
      72             : static void encode_angle_indices_fx( BSTR_ENC_HANDLE hBstr, ISM_METADATA_ANGLE_HANDLE angle, const Word16 last_ism_metadata_flag, const Word16 ini_frame, const Word16 idx_angle1_abs, const Word16 idx_angle2_abs, Word16 *flag_abs_angle1, Word16 *flag_abs_angle2 );
      73             : 
      74             : static void encode_radius_fx( BSTR_ENC_HANDLE hBstr, Word16 *last_radius_idx, Word16 *radius_diff_cnt, const Word16 last_ism_metadata_flag, const Word16 idx_radius_abs, Word16 *flag_abs_radius );
      75             : 
      76             : 
      77             : /*-------------------------------------------------------------------------*
      78             :  * ivas_set_ism_metadata()
      79             :  *
      80             :  * Set metadata of one ISM MD handle
      81             :  *-------------------------------------------------------------------------*/
      82      427276 : ivas_error ivas_set_ism_metadata_fx(
      83             :     ISM_METADATA_HANDLE hIsmMeta,  /* o  : ISM metadata handle   */
      84             :     const Word32 azimuth,          /* i  : azimuth value         */
      85             :     const Word32 elevation,        /* i  : elevation           */
      86             :     const Word16 radius_meta,      /* i  : radius              */
      87             :     const Word32 yaw,              /* i  : yaw                 */
      88             :     const Word32 pitch,            /* i  : pitch               */
      89             :     const Word16 non_diegetic_flag /* i  : non-diegetic object flag*/
      90             : )
      91             : {
      92             : 
      93      427276 :     IF( hIsmMeta == NULL )
      94             :     {
      95           0 :         return IVAS_ERR_UNEXPECTED_NULL_POINTER;
      96             :     }
      97             : 
      98      427276 :     hIsmMeta->ism_metadata_flag = 1;
      99      427276 :     move16();
     100             : 
     101             :     /* save read metadata parameters to the internal codec structure */
     102      427276 :     hIsmMeta->azimuth_fx = azimuth; // Q22
     103      427276 :     move32();
     104      427276 :     hIsmMeta->elevation_fx = elevation; // Q22
     105      427276 :     move32();
     106      427276 :     hIsmMeta->radius_fx = radius_meta; // Q9
     107      427276 :     move16();
     108      427276 :     hIsmMeta->yaw_fx = yaw; // Q22
     109      427276 :     move16();
     110      427276 :     hIsmMeta->pitch_fx = pitch; // Q22
     111      427276 :     move16();
     112      427276 :     hIsmMeta->non_diegetic_flag = non_diegetic_flag;
     113      427276 :     move16();
     114             : 
     115      427276 :     return IVAS_ERR_OK;
     116             : }
     117             : 
     118             : /*-------------------------------------------------------------------------*
     119             :  * rate_ism_importance()
     120             :  *
     121             :  * Rate importance of particular ISM streams
     122             :  *-------------------------------------------------------------------------*/
     123             : 
     124      101711 : static void rate_ism_importance_fx(
     125             :     const Word16 nchan_transport,                        /* i  : number of transported channels  */
     126             :     ISM_METADATA_HANDLE hIsmMeta[],                      /* i/o: ISM metadata handles            */
     127             :     SCE_ENC_HANDLE hSCE[],                               /* i/o: SCE encoder handles             */
     128             :     const Word16 lowrate_metadata_flag[MAX_NUM_OBJECTS], /* i  : low-rate MD flag                */
     129             :     Word16 ism_imp[]                                     /* o  : ISM importance flags            */
     130             : )
     131             : {
     132             :     Word16 ch, ctype;
     133             : 
     134      365441 :     FOR( ch = 0; ch < nchan_transport; ch++ )
     135             :     {
     136      263730 :         ctype = hSCE[ch]->hCoreCoder[0]->coder_type_raw;
     137      263730 :         move16();
     138             : 
     139      263730 :         IF( hSCE[ch]->hCoreCoder[0]->tcxonly )
     140             :         {
     141       99976 :             IF( hSCE[ch]->hCoreCoder[0]->localVAD == 0 )
     142             :             {
     143       16985 :                 ctype = INACTIVE;
     144       16985 :                 move16();
     145             :             }
     146       82991 :             ELSE IF( EQ_16( ctype, UNVOICED ) )
     147             :             {
     148        5855 :                 ctype = GENERIC;
     149        5855 :                 move16();
     150             :             }
     151             :         }
     152             : 
     153      263730 :         test();
     154      263730 :         test();
     155      263730 :         test();
     156      263730 :         IF( ( hIsmMeta[ch]->ism_metadata_flag == 0 || EQ_16( lowrate_metadata_flag[ch], 1 ) ) && hSCE[ch]->hCoreCoder[0]->localVAD == 0 )
     157             :         {
     158        8314 :             ism_imp[ch] = ISM_NO_META;
     159        8314 :             move16();
     160             :         }
     161      255416 :         ELSE IF( ctype == INACTIVE || EQ_16( ctype, UNVOICED ) )
     162             :         {
     163       29072 :             ism_imp[ch] = ISM_LOW_IMP;
     164       29072 :             move16();
     165             :         }
     166      226344 :         ELSE IF( EQ_16( ctype, VOICED ) )
     167             :         {
     168       72514 :             ism_imp[ch] = ISM_MEDIUM_IMP;
     169       72514 :             move16();
     170             :         }
     171             :         ELSE /* GENERIC */
     172             :         {
     173      153830 :             ism_imp[ch] = ISM_HIGH_IMP;
     174      153830 :             move16();
     175             :         }
     176             :     }
     177             : 
     178      101711 :     return;
     179             : }
     180             : 
     181             : /*-------------------------------------------------------------------------*
     182             :  * ivas_ism_metadata_enc()
     183             :  *
     184             :  * quantize and encode ISM metadata
     185             :  *-------------------------------------------------------------------------*/
     186             : 
     187      123217 : ivas_error ivas_ism_metadata_enc_fx(
     188             :     Word32 *ism_total_brate,                 /* i/o: ISM total bitrate               */
     189             :     const Word16 nchan_ism,                  /* i  : number of ISM channels          */
     190             :     const Word16 nchan_transport,            /* i  : number of transport channels    */
     191             :     ISM_METADATA_HANDLE hIsmMeta[],          /* i/o: ISM metadata handles            */
     192             :     SCE_ENC_HANDLE hSCE[],                   /* i/o: SCE encoder handles             */
     193             :     BSTR_ENC_HANDLE hBstr,                   /* i/o: bitstream handle                */
     194             :     Word16 nb_bits_metadata[],               /* o  : number of metadata bits         */
     195             :     const Word16 vad_flag[],                 /* i  : VAD flag                        */
     196             :     const Word16 ism_mode,                   /* i  : ISM mode                        */
     197             :     const PARAM_ISM_CONFIG_HANDLE hParamIsm, /* i  : Param ISM Enc Handle            */
     198             :     const Word16 ism_extended_metadata_flag, /* i  : Extended metadata flag          */
     199             :     const Word16 lp_noise_CPE_fx,            /* i  : Q8 */
     200             :     const Word16 flag_omasa_ener_brate,      /* i  : less bitrate for objects in OMASA flag */
     201             :     Word16 *omasa_stereo_sw_cnt,
     202             :     const Word16 ini_frame )
     203             : {
     204      123217 :     Word16 i, ch, nb_bits_start = 0;
     205      123217 :     move16();
     206             :     Word16 flag_abs_azimuth[MAX_NUM_OBJECTS];
     207             :     Word16 flag_abs_elevation[MAX_NUM_OBJECTS];
     208      123217 :     Word16 idx_angle1_abs = 0;
     209      123217 :     move16();
     210      123217 :     Word16 idx_angle2_abs = 0;
     211      123217 :     move16();
     212             :     Word16 flag_abs_yaw[MAX_NUM_OBJECTS];
     213             :     Word16 flag_abs_pitch[MAX_NUM_OBJECTS];
     214      123217 :     Word16 idx_radius_abs = 0, flag_abs_radius[MAX_NUM_OBJECTS];
     215      123217 :     move16();
     216             :     Word32 valQ_fx;
     217             :     ISM_METADATA_HANDLE hIsmMetaData;
     218             :     Word32 element_brate[MAX_NUM_OBJECTS], total_brate[MAX_NUM_OBJECTS];
     219             :     Word16 ism_metadata_flag_global;
     220             :     Word16 non_diegetic_flag_global;
     221             :     Word16 ism_imp[MAX_NUM_OBJECTS];
     222             :     Word16 null_metadata_flag[MAX_NUM_OBJECTS];
     223             :     Word16 lowrate_metadata_flag[MAX_NUM_OBJECTS];
     224             :     Word16 nbands, nblocks;
     225             :     ivas_error error;
     226             : 
     227      123217 :     error = IVAS_ERR_OK;
     228      123217 :     push_wmops( "ism_meta_enc" );
     229             : 
     230             :     /* initialization */
     231      123217 :     ism_metadata_flag_global = 0;
     232      123217 :     non_diegetic_flag_global = 0;
     233      123217 :     move16();
     234      123217 :     move16();
     235      123217 :     set16_fx( nb_bits_metadata, 0, nchan_transport );
     236      123217 :     set16_fx( flag_abs_azimuth, 0, nchan_ism );
     237      123217 :     set16_fx( flag_abs_elevation, 0, nchan_ism );
     238      123217 :     set16_fx( flag_abs_yaw, 0, nchan_ism );
     239      123217 :     set16_fx( flag_abs_pitch, 0, nchan_ism );
     240      123217 :     set16_fx( flag_abs_radius, 0, nchan_ism );
     241      123217 :     set16_fx( null_metadata_flag, 0, nchan_ism );
     242      123217 :     set16_fx( lowrate_metadata_flag, 0, nchan_ism );
     243             : 
     244      123217 :     test();
     245             : 
     246      123217 :     IF( EQ_16( ism_mode, ISM_MASA_MODE_DISC ) || EQ_16( ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) )
     247             :     {
     248             :         /*----------------------------------------------------------------*
     249             :          * Rate importance of particular ISM streams in combined format coding
     250             :          *----------------------------------------------------------------*/
     251        5196 :         ivas_set_ism_importance_interformat_fx( *ism_total_brate, nchan_transport, hIsmMeta, hSCE, lp_noise_CPE_fx, ism_imp );
     252             :     }
     253             :     ELSE
     254             :     {
     255             :         /*----------------------------------------------------------------*
     256             :          * Set Metadata presence / importance flag
     257             :          *----------------------------------------------------------------*/
     258             : 
     259      467219 :         FOR( ch = 0; ch < nchan_ism; ch++ )
     260             :         {
     261      349198 :             test();
     262      349198 :             test();
     263      349198 :             IF( EQ_16( ism_mode, ISM_MODE_PARAM ) )
     264             :             {
     265       74906 :                 hIsmMeta[ch]->ism_metadata_flag = 1;
     266       74906 :                 move16();
     267             :             }
     268      274292 :             ELSE IF( EQ_16( ism_mode, ISM_MODE_DISC ) || EQ_16( ism_mode, ISM_MASA_MODE_DISC ) || EQ_16( ism_mode, ISM_SBA_MODE_DISC ) )
     269             :             {
     270      274292 :                 null_metadata_flag[ch] = !hIsmMeta[ch]->ism_metadata_flag;
     271      274292 :                 move16();
     272             : 
     273      274292 :                 IF( EQ_16( hIsmMeta[ch]->ism_metadata_flag, 1 ) )
     274             :                 {
     275      269622 :                     IF( NE_16( ism_mode, ISM_SBA_MODE_DISC ) )
     276             :                     {
     277             :                         /* In case of low level noise for low bitrate inactive frames, do not sent metadata */
     278      218232 :                         test();
     279      218232 :                         test();
     280      218232 :                         hIsmMeta[ch]->ism_metadata_flag = vad_flag[ch] || GT_16( hSCE[ch]->hCoreCoder[0]->lp_noise_fx, 2560 /*10 Q8*/ ) || hSCE[ch]->hCoreCoder[0]->tcxonly;
     281      218232 :                         move16();
     282             :                     }
     283             : 
     284             :                     /* in inactive frames, send MD 1) in ISM_MD_INC_DIFF_CNT_MAX consecutive frames when MD significantly change, 2) at least every ISM_MD_FEC_DIFF frames */
     285      269622 :                     IF( hIsmMeta[ch]->ism_metadata_flag == 0 )
     286             :                     {
     287        6562 :                         test();
     288        6562 :                         test();
     289        6562 :                         IF( ( GT_32( L_abs( L_sub( hIsmMeta[ch]->azimuth_fx, hIsmMeta[ch]->last_true_azimuth_fx ) ), ISM_MD_FEC_DIFF_Q22 ) ) ||
     290             :                             ( GT_32( L_abs( L_sub( hIsmMeta[ch]->elevation_fx, hIsmMeta[ch]->last_true_elevation_fx ) ), ISM_MD_FEC_DIFF_Q22 ) ) || ( GT_16( abs_s( sub( hIsmMeta[ch]->radius_fx, hIsmMeta[ch]->last_true_radius_fx ) ), ISM_MD_RAD_FEC_DIFF_Q9 ) ) )
     291             :                         {
     292             : 
     293        5831 :                             lowrate_metadata_flag[ch] = 1;
     294        5831 :                             move16();
     295             : 
     296        5831 :                             hIsmMeta[ch]->ism_md_inc_diff_cnt = 0;
     297        5831 :                             move16();
     298             :                         }
     299         731 :                         ELSE IF( LT_16( hIsmMeta[ch]->ism_md_inc_diff_cnt, ISM_MD_INC_DIFF_CNT_MAX ) )
     300             :                         {
     301             : 
     302         498 :                             lowrate_metadata_flag[ch] = 1;
     303         498 :                             move16();
     304         498 :                             IF( hIsmMeta[ch]->ism_md_inc_diff_cnt % 2 == 0 )
     305             :                             {
     306         189 :                                 hIsmMeta[ch]->position_angle.angle1_diff_cnt = ISM_FEC_MAX;
     307         189 :                                 move16();
     308             :                             }
     309             :                             ELSE
     310             :                             {
     311         309 :                                 hIsmMeta[ch]->position_angle.angle2_diff_cnt = ISM_FEC_MAX;
     312         309 :                                 move16();
     313             :                             }
     314             :                         }
     315         233 :                         ELSE IF( EQ_16( hIsmMeta[ch]->ism_md_fec_cnt_enc, ISM_MD_FEC_CNT_MAX ) )
     316             :                         {
     317           6 :                             hIsmMeta[ch]->ism_md_fec_cnt_enc = 0;
     318           6 :                             move16();
     319           6 :                             lowrate_metadata_flag[ch] = 1;
     320           6 :                             move16();
     321           6 :                             hIsmMeta[ch]->position_angle.angle1_diff_cnt = ISM_FEC_MAX;
     322           6 :                             move16();
     323             :                         }
     324             :                     }
     325             :                 }
     326             :             }
     327             :         }
     328             : 
     329             :         /*----------------------------------------------------------------*
     330             :          * Rate importance of particular ISM streams
     331             :          *----------------------------------------------------------------*/
     332             : 
     333      118021 :         IF( NE_16( ism_mode, ISM_SBA_MODE_DISC ) )
     334             :         {
     335      101711 :             rate_ism_importance_fx( nchan_transport, hIsmMeta, hSCE, lowrate_metadata_flag, ism_imp );
     336             :         }
     337             :     }
     338             : 
     339             : #ifdef DEBUG_FORCE_DIR
     340             :     if ( hSCE[0]->hCoreCoder[0]->force_dir[0] != '\0' )
     341             :     {
     342             :         dbgread( ism_imp, sizeof( int16_t ), nchan_ism, fname( hSCE[0]->hCoreCoder[0]->force_dir, "force_ism_imp.enf", -1, -1, -1 ) );
     343             :     }
     344             :     else
     345             :     {
     346             :         dbgwrite( ism_imp, sizeof( int16_t ), nchan_ism, 1, "res/force_ism_imp.enf" );
     347             :     }
     348             : #endif
     349             : 
     350             :     /*----------------------------------------------------------------*
     351             :      * Write ISM common signaling
     352             :      *----------------------------------------------------------------*/
     353      123217 :     test();
     354      123217 :     test();
     355      123217 :     IF( NE_16( ism_mode, ISM_MASA_MODE_DISC ) && NE_16( ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) && NE_16( ism_mode, ISM_SBA_MODE_DISC ) )
     356             :     {
     357             :         /* write number of objects - unary coding */
     358      297808 :         FOR( ch = 1; ch < nchan_ism; ch++ )
     359             :         {
     360      196097 :             push_indice( hBstr, IND_ISM_NUM_OBJECTS, 1, 1 );
     361             :         }
     362      101711 :         push_indice( hBstr, IND_ISM_NUM_OBJECTS, 0, 1 );
     363             :     }
     364             : 
     365      482929 :     FOR( ch = 0; ch < nchan_ism; ch++ )
     366             :     {
     367      359712 :         ism_metadata_flag_global = s_or( ism_metadata_flag_global, hIsmMeta[ch]->ism_metadata_flag );
     368      359712 :         ism_metadata_flag_global = s_or( ism_metadata_flag_global, lowrate_metadata_flag[ch] );
     369      359712 :         non_diegetic_flag_global = s_or( non_diegetic_flag_global, hIsmMeta[ch]->non_diegetic_flag );
     370             :     }
     371             : 
     372             :     /* write extended metadata presence flag */
     373      123217 :     test();
     374      123217 :     test();
     375      123217 :     IF( ( EQ_16( ism_mode, ISM_MODE_DISC ) || EQ_16( ism_mode, ISM_SBA_MODE_DISC ) ) && GE_32( *ism_total_brate, ISM_EXTENDED_METADATA_BRATE ) )
     376             :     {
     377       74215 :         push_indice( hBstr, IND_ISM_EXTENDED_FLAG, ism_extended_metadata_flag, ISM_EXTENDED_METADATA_BITS );
     378             : 
     379             :         /* Write global non-diegetic object flag */
     380       74215 :         IF( ism_extended_metadata_flag )
     381             :         {
     382        8166 :             push_indice( hBstr, IND_ISM_EXTENDED_NDP_FLAG, non_diegetic_flag_global, ISM_EXTENDED_METADATA_BITS );
     383             :         }
     384             :     }
     385             : 
     386             :     /* write ISM metadata flag (one per object) */
     387      448851 :     FOR( ch = 0; ch < nchan_transport; ch++ )
     388             :     {
     389      325634 :         test();
     390      325634 :         IF( EQ_16( ism_mode, ISM_MASA_MODE_DISC ) || EQ_16( ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) )
     391             :         {
     392             :             /* flags will be written in ivas_masa_encode() */
     393       10514 :             hIsmMeta[ch]->ism_imp = ism_imp[ch];
     394       10514 :             move16();
     395       10514 :             hIsmMeta[ch]->ism_md_null_flag = null_metadata_flag[ch];
     396       10514 :             move16();
     397       10514 :             hIsmMeta[ch]->ism_md_lowrate_flag = lowrate_metadata_flag[ch];
     398       10514 :             move16();
     399             :         }
     400             :         ELSE
     401             :         {
     402      315120 :             IF( null_metadata_flag[ch] )
     403             :             {
     404             :                 /* signal NULL metadata frame */
     405        4670 :                 push_indice( hBstr, IND_ISM_MD_NULL_FLAG, 1, ISM_METADATA_MD_FLAG_BITS );
     406             : 
     407             :                 /* write the ISM class to ISM_NO_META and again the true ISM class */
     408        4670 :                 IF( NE_16( ism_mode, ISM_SBA_MODE_DISC ) )
     409             :                 {
     410        4670 :                     push_indice( hBstr, IND_ISM_METADATA_FLAG, ISM_NO_META, ISM_METADATA_FLAG_BITS );
     411        4670 :                     push_indice( hBstr, IND_ISM_MD_INACTIVE_FLAG, ism_imp[ch], ISM_METADATA_FLAG_BITS );
     412             :                 }
     413             :                 ELSE
     414             :                 {
     415           0 :                     push_indice( hBstr, IND_ISM_METADATA_FLAG, ISM_NO_META, 1 );
     416             :                 }
     417             :             }
     418      310450 :             ELSE IF( NE_16( ism_mode, ISM_SBA_MODE_DISC ) )
     419             :             {
     420      259060 :                 push_indice( hBstr, IND_ISM_METADATA_FLAG, ism_imp[ch], ISM_METADATA_FLAG_BITS );
     421             : 
     422      259060 :                 IF( ism_imp[ch] == ISM_NO_META )
     423             :                 {
     424             :                     /* signal low-rate ISM_NO_META frame */
     425        6562 :                     push_indice( hBstr, IND_ISM_MD_NULL_FLAG, 0, ISM_METADATA_MD_FLAG_BITS );
     426             : 
     427             :                     /* signal presence of MD in low-rate ISM_NO_META frame */
     428        6562 :                     push_indice( hBstr, IND_ISM_MD_INACTIVE_FLAG, lowrate_metadata_flag[ch], ISM_METADATA_INACTIVE_FLAG_BITS );
     429             :                 }
     430             :             }
     431             :             ELSE /*ism_mode == ISM_SBA_MODE_DISC*/
     432             :             {
     433             :                 /* all objects are considered active*/
     434       51390 :                 push_indice( hBstr, IND_ISM_METADATA_FLAG, 1, 1 );
     435             :             }
     436             :         }
     437             :     }
     438             : 
     439             : 
     440      123217 :     IF( ism_metadata_flag_global )
     441             :     {
     442             :         /*----------------------------------------------------------------*
     443             :          * Metadata quantization and coding, loop over all objects
     444             :          *----------------------------------------------------------------*/
     445             : 
     446      123208 :         Word16 total_bits_metadata = 0;
     447      123208 :         move16();
     448      123208 :         Word16 bits_metadata_ism = 0;
     449      123208 :         move16();
     450             :         Word16 nb_bits_objcod_written;
     451             : 
     452      123208 :         IF( EQ_16( ism_mode, ISM_MODE_PARAM ) )
     453             :         {
     454       20414 :             nb_bits_start = hBstr->nb_bits_tot;
     455       20414 :             move16();
     456             :         }
     457             : 
     458      482893 :         FOR( ch = 0; ch < nchan_ism; ch++ )
     459             :         {
     460      359685 :             hIsmMetaData = hIsmMeta[ch];
     461      359685 :             test();
     462      359685 :             test();
     463      359685 :             test();
     464      359685 :             if ( EQ_16( ism_mode, ISM_MODE_DISC ) || EQ_16( ism_mode, ISM_MASA_MODE_DISC ) || EQ_16( ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) || EQ_16( ism_mode, ISM_SBA_MODE_DISC ) )
     465             :             {
     466      284779 :                 nb_bits_start = hBstr->nb_bits_tot;
     467      284779 :                 move16();
     468             :             }
     469      359685 :             test();
     470      359685 :             IF( hIsmMeta[ch]->ism_metadata_flag || lowrate_metadata_flag[ch] )
     471             :             {
     472             :                 /*----------------------------------------------------------------*
     473             :                  * Quantize and encode azimuth and elevation
     474             :                  *----------------------------------------------------------------*/
     475      354815 :                 test();
     476      354815 :                 IF( ism_extended_metadata_flag && non_diegetic_flag_global )
     477             :                 {
     478             :                     /* Write non-diegetic flag for each object */
     479        2415 :                     push_indice( hBstr, IND_ISM_NDP_FLAG, hIsmMeta[ch]->non_diegetic_flag, ISM_METADATA_IS_NDP_BITS );
     480             :                 }
     481      354815 :                 test();
     482      354815 :                 IF( hIsmMeta[ch]->non_diegetic_flag && ism_extended_metadata_flag )
     483             :                 {
     484             :                     /* Map azimuth to panning range [-90:90] */
     485         805 :                     IF( GT_32( hIsmMetaData->azimuth_fx, 377487360 /*90.0f Q22*/ ) )
     486             :                     {
     487           0 :                         hIsmMetaData->azimuth_fx = L_sub( 754974720 /*180.0f Q22*/, hIsmMetaData->azimuth_fx ); // Q22
     488           0 :                         move32();
     489             :                     }
     490             : 
     491         805 :                     IF( LT_32( hIsmMetaData->azimuth_fx, L_negate( 377487360 ) /*-90.0f Q22*/ ) )
     492             :                     {
     493           0 :                         hIsmMetaData->azimuth_fx = L_sub( L_negate( 754974720 ) /*-180.0f Q22*/, hIsmMetaData->azimuth_fx ); // Q22
     494           0 :                         move32();
     495             :                     }
     496             : 
     497         805 :                     idx_angle1_abs = ism_quant_meta_fx( hIsmMetaData->azimuth_fx, &valQ_fx, ism_azimuth_borders_fx, ISM_Q_STEP_FX, ISM_Q_STEP_BORDER_FX, 1 << ISM_AZIMUTH_NBITS );
     498         805 :                     encode_angle_indices_fx( hBstr, &( hIsmMetaData->position_angle ), hIsmMetaData->last_ism_metadata_flag, hSCE[0]->hCoreCoder[0]->ini_frame, idx_angle1_abs, 0, &flag_abs_azimuth[ch], NULL );
     499             :                 }
     500             :                 ELSE
     501             :                 {
     502      354010 :                     test();
     503      354010 :                     test();
     504      354010 :                     test();
     505      354010 :                     IF( EQ_16( ism_mode, ISM_MODE_DISC ) || EQ_16( ism_mode, ISM_MASA_MODE_DISC ) || EQ_16( ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) || EQ_16( ism_mode, ISM_SBA_MODE_DISC ) )
     506             :                     {
     507      279104 :                         idx_angle1_abs = ism_quant_meta_fx( hIsmMetaData->azimuth_fx, &valQ_fx, ism_azimuth_borders_fx, ISM_Q_STEP_FX, ISM_Q_STEP_BORDER_FX, 1 << ISM_AZIMUTH_NBITS );
     508      279104 :                         idx_angle2_abs = ism_quant_meta_fx( hIsmMetaData->elevation_fx, &valQ_fx, ism_elevation_borders_fx, ISM_Q_STEP_FX, ISM_Q_STEP_BORDER_FX, 1 << ISM_ELEVATION_NBITS );
     509             :                         // valQ = fixedToFloat( valQ_fx, Q22 );
     510             :                     }
     511             :                     ELSE /* ISM_MODE_PARAM */
     512             :                     {
     513       74906 :                         idx_angle1_abs = hParamIsm->azi_index[ch];
     514       74906 :                         move16();
     515       74906 :                         idx_angle2_abs = hParamIsm->ele_index[ch];
     516       74906 :                         move16();
     517             :                     }
     518      354010 :                     encode_angle_indices_fx( hBstr, &( hIsmMetaData->position_angle ), hIsmMetaData->last_ism_metadata_flag, ini_frame, idx_angle1_abs, idx_angle2_abs, &flag_abs_azimuth[ch], &flag_abs_elevation[ch] );
     519             :                     /*----------------------------------------------------------------*
     520             :                      * Quantize and encode radius, yaw, and pitch
     521             :                      *----------------------------------------------------------------*/
     522      354010 :                     test();
     523      354010 :                     test();
     524      354010 :                     IF( ( EQ_16( ism_mode, ISM_MODE_DISC ) || EQ_16( ism_mode, ISM_SBA_MODE_DISC ) ) && ism_extended_metadata_flag )
     525             :                     {
     526       25625 :                         idx_angle1_abs = ism_quant_meta_fx( hIsmMetaData->yaw_fx, &valQ_fx, ism_azimuth_borders_fx, ISM_Q_STEP_FX, ISM_Q_STEP_BORDER_FX, 1 << ISM_AZIMUTH_NBITS );
     527       25625 :                         idx_angle2_abs = ism_quant_meta_fx( hIsmMetaData->pitch_fx, &valQ_fx, ism_elevation_borders_fx, ISM_Q_STEP_FX, ISM_Q_STEP_BORDER_FX, 1 << ISM_ELEVATION_NBITS );
     528       25625 :                         Word16 valQ_fx_tmp = extract_h( valQ_fx ); // 22 - 16 = 6
     529       25625 :                         idx_radius_abs = usquant_fx( hIsmMetaData->radius_fx, &valQ_fx_tmp, ISM_RADIUS_MIN_Q9, ISM_RADIUS_DELTA_Q8, 1 << ISM_RADIUS_NBITS );
     530       25625 :                         valQ_fx = L_shr( L_deposit_h( valQ_fx_tmp ), 3 ); // Q22
     531             :                                                                           // valQ = fixedToFloat( valQ_fx, Q22 );
     532       25625 :                         encode_angle_indices_fx( hBstr, &( hIsmMetaData->orientation_angle ), hIsmMetaData->last_ism_metadata_flag, ini_frame, idx_angle1_abs, idx_angle2_abs, &flag_abs_yaw[ch], &flag_abs_pitch[ch] );
     533       25625 :                         encode_radius_fx( hBstr, &hIsmMetaData->last_radius_idx, &hIsmMetaData->radius_diff_cnt, hIsmMetaData->last_ism_metadata_flag, idx_radius_abs, &flag_abs_radius[ch] );
     534             :                     }
     535             :                 }
     536             : 
     537             :                 /* save number of metadata bits written */
     538      354815 :                 test();
     539      354815 :                 test();
     540      354815 :                 test();
     541      354815 :                 IF( EQ_16( ism_mode, ISM_MODE_DISC ) || EQ_16( ism_mode, ISM_MASA_MODE_DISC ) || EQ_16( ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) || EQ_16( ism_mode, ISM_SBA_MODE_DISC ) )
     542             :                 {
     543      279909 :                     nb_bits_metadata[ch] = sub( hBstr->nb_bits_tot, nb_bits_start );
     544      279909 :                     move16();
     545             :                 }
     546             : 
     547             :                 /* Updates */
     548      354815 :                 hIsmMeta[ch]->last_true_azimuth_fx = hIsmMeta[ch]->azimuth_fx; // Q22
     549      354815 :                 move32();
     550      354815 :                 hIsmMeta[ch]->last_true_elevation_fx = hIsmMeta[ch]->elevation_fx; // Q22
     551      354815 :                 move32();
     552      354815 :                 hIsmMeta[ch]->last_true_radius_fx = hIsmMeta[ch]->radius_fx; // Q22
     553      354815 :                 move16();
     554             :             }
     555             :         }
     556             : 
     557             :         /*----------------------------------------------------------------*
     558             :          * inter-object logic minimizing the use of several absolutely coded
     559             :          * indexes in the same frame
     560             :          *----------------------------------------------------------------*/
     561             : 
     562      123208 :         i = 0;
     563      123208 :         move16();
     564      123208 :         test();
     565      246416 :         WHILE( i == 0 || i < ( nchan_ism / INTER_OBJECT_PARAM_CHECK ) )
     566             :         {
     567             :             Word16 num, abs_num, abs_first, abs_next, pos_zero;
     568             :             Word16 abs_matrice[INTER_OBJECT_PARAM_CHECK * ISM_NUM_PARAM];
     569             : 
     570      123208 :             num = s_min( INTER_OBJECT_PARAM_CHECK, sub( nchan_ism, imult1616( i, INTER_OBJECT_PARAM_CHECK ) ) );
     571      123208 :             i = add( i, 1 );
     572             : 
     573      123208 :             set16_fx( abs_matrice, 0, INTER_OBJECT_PARAM_CHECK * ISM_NUM_PARAM );
     574             : 
     575      425371 :             FOR( ch = 0; ch < num; ch++ )
     576             :             {
     577      302163 :                 if ( EQ_16( flag_abs_azimuth[ch], 1 ) )
     578             :                 {
     579      104855 :                     abs_matrice[ch * ISM_NUM_PARAM] = 1;
     580      104855 :                     move16();
     581             :                 }
     582             : 
     583      302163 :                 if ( EQ_16( flag_abs_elevation[ch], 1 ) )
     584             :                 {
     585       21065 :                     abs_matrice[ch * ISM_NUM_PARAM + 1] = 1;
     586       21065 :                     move16();
     587             :                 }
     588             :             }
     589      123208 :             abs_num = sum_s( abs_matrice, INTER_OBJECT_PARAM_CHECK * ISM_NUM_PARAM );
     590             : 
     591      123208 :             abs_first = 0;
     592      123208 :             move16();
     593      156807 :             WHILE( abs_num > 1 )
     594             :             {
     595             :                 /* find first "1" entry */
     596      128361 :                 WHILE( abs_matrice[abs_first] == 0 )
     597             :                 {
     598       94762 :                     abs_first = add( abs_first, 1 );
     599             :                 }
     600             : 
     601             :                 /* find next "1" entry */
     602       33599 :                 abs_next = add( abs_first, 1 );
     603      221246 :                 WHILE( abs_matrice[abs_next] == 0 )
     604             :                 {
     605      187647 :                     abs_next = add( abs_next, 1 );
     606             :                 }
     607             : 
     608             :                 /* find "0" position */
     609       33599 :                 pos_zero = 0;
     610       33599 :                 move16();
     611       44655 :                 WHILE( abs_matrice[pos_zero] == 1 )
     612             :                 {
     613       11056 :                     pos_zero = add( pos_zero, 1 );
     614             :                 }
     615             : 
     616       33599 :                 ch = idiv1616( abs_next, ISM_NUM_PARAM );
     617             : 
     618       33599 :                 IF( abs_next % ISM_NUM_PARAM == 0 )
     619             :                 {
     620       31608 :                     hIsmMeta[ch]->position_angle.angle1_diff_cnt = sub( abs_num, 1 );
     621       31608 :                     move16();
     622             :                 }
     623             : 
     624       33599 :                 IF( EQ_16( abs_next % ISM_NUM_PARAM, 1 ) )
     625             :                 {
     626        1991 :                     hIsmMeta[ch]->position_angle.angle2_diff_cnt = sub( abs_num, 1 );
     627        1991 :                     move16();
     628             :                     /*hIsmMeta[ch]->elevation_diff_cnt = min( hIsmMeta[ch]->elevation_diff_cnt, ISM_FEC_MAX );*/
     629             :                 }
     630             : 
     631       33599 :                 abs_first = add( abs_first, 1 );
     632       33599 :                 abs_num = sub( abs_num, 1 );
     633             :             }
     634      123208 :             test();
     635             :         }
     636             : 
     637      123208 :         IF( EQ_16( ism_mode, ISM_SBA_MODE_DISC ) )
     638             :         {
     639             :             Word16 md_diff_flag[MAX_NUM_OBJECTS];
     640             : 
     641       16310 :             set16_fx( md_diff_flag, 1, nchan_ism );
     642       67700 :             FOR( ch = 0; ch < nchan_ism; ch++ )
     643             :             {
     644       51390 :                 hIsmMeta[ch]->last_ism_metadata_flag = hIsmMeta[ch]->ism_metadata_flag;
     645       51390 :                 move16();
     646             : 
     647       51390 :                 IF( hIsmMeta[ch]->ism_metadata_flag == 0 )
     648             :                 {
     649           0 :                     hIsmMeta[ch]->ism_md_fec_cnt_enc = add( hIsmMeta[ch]->ism_md_fec_cnt_enc, 1 );
     650           0 :                     move16();
     651           0 :                     hIsmMeta[ch]->ism_md_fec_cnt_enc = s_min( hIsmMeta[ch]->ism_md_fec_cnt_enc, ISM_MD_FEC_CNT_MAX );
     652           0 :                     move16();
     653             :                 }
     654             :                 ELSE
     655             :                 {
     656       51390 :                     hIsmMeta[ch]->ism_md_fec_cnt_enc = 0;
     657       51390 :                     move16();
     658             :                 }
     659       51390 :                 hIsmMeta[ch]->ism_md_inc_diff_cnt = add( hIsmMeta[ch]->ism_md_inc_diff_cnt, 1 );
     660       51390 :                 move16();
     661       51390 :                 hIsmMeta[ch]->ism_md_inc_diff_cnt = s_min( hIsmMeta[ch]->ism_md_inc_diff_cnt, ISM_MD_INC_DIFF_CNT_MAX );
     662       51390 :                 move16();
     663             :             }
     664             : 
     665       16310 :             update_last_metadata_fx( nchan_ism, hIsmMeta, md_diff_flag );
     666             : 
     667       16310 :             pop_wmops();
     668       16310 :             return error;
     669             :         }
     670      106898 :         IF( EQ_16( ism_mode, ISM_MODE_PARAM ) )
     671             :         {
     672             :             /* Keep the metdata transmission as is during active parts */
     673             :             /* But send the flag with 1 bit */
     674       20414 :             push_next_indice( hBstr, hParamIsm->flag_noisy_speech, 1 );
     675             : 
     676             :             /* Loop over multiwave to write the object indices into bitstream */
     677       61242 :             FOR( ch = 0; ch < MAX_PARAM_ISM_WAVE; ch++ )
     678             :             {
     679      489936 :                 FOR( nbands = 0; nbands < hParamIsm->nbands; nbands++ )
     680             :                 {
     681      898216 :                     FOR( nblocks = 0; nblocks < hParamIsm->nblocks[nbands]; nblocks++ )
     682             :                     {
     683      449108 :                         push_next_indice( hBstr, hParamIsm->obj_indices[nbands][nblocks][ch], PARAM_ISM_OBJ_IND_NBITS );
     684             :                     }
     685             :                 }
     686             :             }
     687             : 
     688             :             /* Loop over bands to write the power ratio's indices into bitstream */
     689      244968 :             FOR( nbands = 0; nbands < hParamIsm->nbands; nbands++ )
     690             :             {
     691      449108 :                 FOR( nblocks = 0; nblocks < hParamIsm->nblocks[nbands]; nblocks++ )
     692             :                 {
     693      224554 :                     push_next_indice( hBstr, hParamIsm->power_ratios_idx[nbands][nblocks], PARAM_ISM_POW_RATIO_NBITS );
     694             :                 }
     695             :             }
     696             : 
     697             :             /* total metadata bits */
     698       20414 :             total_bits_metadata = sub( hBstr->nb_bits_tot, nb_bits_start );
     699             : 
     700             :             /* bits per ISM*/
     701       20414 :             bits_metadata_ism = idiv1616( total_bits_metadata, nchan_transport );
     702             : 
     703             :             /* Divide the metadata bits into n_Isms*/
     704       20414 :             nb_bits_objcod_written = 0;
     705       20414 :             move16();
     706       61242 :             FOR( ch = 0; ch < nchan_transport; ch++ )
     707             :             {
     708       40828 :                 IF( EQ_16( ch, sub( nchan_transport, 1 ) ) )
     709             :                 {
     710       20414 :                     nb_bits_metadata[ch] = sub( total_bits_metadata, nb_bits_objcod_written );
     711       20414 :                     move16();
     712             :                 }
     713             :                 ELSE
     714             :                 {
     715       20414 :                     nb_bits_metadata[ch] = bits_metadata_ism;
     716       20414 :                     move16();
     717       20414 :                     nb_bits_objcod_written = add( nb_bits_objcod_written, bits_metadata_ism );
     718       20414 :                     move16();
     719             :                 }
     720             :             }
     721             :         }
     722             :     }
     723           9 :     ELSE IF( EQ_16( ism_mode, ISM_SBA_MODE_DISC ) )
     724             :     {
     725           0 :         pop_wmops();
     726           0 :         return error;
     727             :     }
     728             : 
     729             :     /*----------------------------------------------------------------*
     730             :      * Take into account the combined format bit-budget distribution
     731             :      *----------------------------------------------------------------*/
     732      106907 :     test();
     733      106907 :     IF( EQ_16( ism_mode, ISM_MASA_MODE_DISC ) || EQ_16( ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) )
     734             :     {
     735             :         Word16 bits_ism, bits_element[MAX_NUM_OBJECTS];
     736             :         Word16 brate_limit_flag;
     737             :         Word32 ism_total_brate_ref;
     738        5196 :         ism_total_brate_ref = *ism_total_brate;
     739        5196 :         move32();
     740        5196 :         brate_limit_flag = calculate_brate_limit_flag_fx( ism_imp, nchan_ism );
     741             : 
     742        5196 :         bits_ism = extract_l( div_l( *ism_total_brate, FRAMES_PER_SEC >> 1 ) );
     743        5196 :         set16_fx( bits_element, idiv1616( bits_ism, nchan_ism ), nchan_ism );
     744        5196 :         bits_element[nchan_ism - 1] = add( bits_element[nchan_ism - 1], bits_ism % nchan_ism );
     745        5196 :         move16();
     746        5196 :         bitbudget_to_brate( bits_element, element_brate, nchan_ism );
     747             : 
     748        5196 :         *ism_total_brate = 0;
     749        5196 :         move32();
     750       15710 :         FOR( ch = 0; ch < nchan_ism; ch++ )
     751             :         {
     752       10514 :             *ism_total_brate = L_add( *ism_total_brate, ivas_interformat_brate_fx( ism_mode, nchan_ism, hSCE[ch]->element_brate, ism_imp[ch], brate_limit_flag ) );
     753       10514 :             move32();
     754       10514 :             test();
     755       10514 :             test();
     756       10514 :             IF( GT_16( ism_imp[ch], 1 ) && EQ_16( flag_omasa_ener_brate, 1 ) && brate_limit_flag >= 0 )
     757             :             {
     758         442 :                 *ism_total_brate = L_sub( *ism_total_brate, ADJUST_ISM_BRATE_NEG );
     759         442 :                 move32();
     760             :             }
     761             : 
     762       10514 :             test();
     763       10514 :             test();
     764       10514 :             test();
     765       10514 :             IF( EQ_16( brate_limit_flag, -1 ) && GE_16( ism_imp[ch], 1 ) && GE_16( nchan_ism, 3 ) && ( GT_32( L_sub( ism_total_brate_ref, *ism_total_brate ), IVAS_48k ) ) )
     766             :             {
     767           0 :                 *ism_total_brate = L_add( *ism_total_brate, ADJUST_ISM_BRATE_POS );
     768           0 :                 move32();
     769             :             }
     770             :         }
     771        5196 :         ism_metadata_flag_global = 1;
     772        5196 :         move16();
     773             : 
     774        5196 :         IF( EQ_16( ism_mode, ISM_MASA_MODE_DISC ) )
     775             :         {
     776        3142 :             brate_limit_flag = 0;
     777        3142 :             move16();
     778       11602 :             FOR( Word16 n = 0; n < nchan_ism; n++ )
     779             :             {
     780        8460 :                 brate_limit_flag = add( brate_limit_flag, ism_imp[n] );
     781             :             }
     782             : 
     783        3142 :             if ( GE_16( brate_limit_flag, sub( imult1616( nchan_ism, ISM_HIGH_IMP ), 2 ) ) )
     784             :             {
     785        2929 :                 *omasa_stereo_sw_cnt = OMASA_STEREO_SW_CNT_MAX;
     786        2929 :                 move16();
     787             :             }
     788             :         }
     789             :     }
     790             : 
     791             :     /*----------------------------------------------------------------*
     792             :      * Configuration and decision about bitrates per channel
     793             :      *----------------------------------------------------------------*/
     794             : 
     795      106907 :     test();
     796      106907 :     IF( EQ_16( ism_mode, ISM_MASA_MODE_DISC ) || EQ_16( ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) )
     797             :     {
     798        5196 :         IF( NE_32( ( error = ivas_ism_config_fx( *ism_total_brate, nchan_transport, nchan_ism, hIsmMeta, ism_extended_metadata_flag, null_metadata_flag, ism_imp, element_brate, total_brate, nb_bits_metadata, 1 ) ), IVAS_ERR_OK ) )
     799             :         {
     800           0 :             return error;
     801             :         }
     802             :     }
     803             :     ELSE
     804             :     {
     805      101711 :         IF( NE_32( ( error = ivas_ism_config_fx( *ism_total_brate, nchan_transport, nchan_ism, hIsmMeta, ism_extended_metadata_flag, null_metadata_flag, ism_imp, element_brate, total_brate, nb_bits_metadata, 0 ) ), IVAS_ERR_OK ) )
     806             :         {
     807           0 :             return error;
     808             :         }
     809             :     }
     810             : 
     811      415229 :     FOR( ch = 0; ch < nchan_ism; ch++ )
     812             :     {
     813      308322 :         hIsmMeta[ch]->last_ism_metadata_flag = hIsmMeta[ch]->ism_metadata_flag;
     814      308322 :         move16();
     815             : 
     816      308322 :         IF( hIsmMeta[ch]->ism_metadata_flag == 0 )
     817             :         {
     818       11232 :             hIsmMeta[ch]->ism_md_fec_cnt_enc = add( hIsmMeta[ch]->ism_md_fec_cnt_enc, 1 );
     819       11232 :             move16();
     820       11232 :             hIsmMeta[ch]->ism_md_fec_cnt_enc = s_min( hIsmMeta[ch]->ism_md_fec_cnt_enc, ISM_MD_FEC_CNT_MAX );
     821       11232 :             move16();
     822             :         }
     823             :         ELSE
     824             :         {
     825      297090 :             hIsmMeta[ch]->ism_md_fec_cnt_enc = 0;
     826      297090 :             move16();
     827             :         }
     828      308322 :         hIsmMeta[ch]->ism_md_inc_diff_cnt = add( hIsmMeta[ch]->ism_md_inc_diff_cnt, 1 );
     829      308322 :         move16();
     830      308322 :         hIsmMeta[ch]->ism_md_inc_diff_cnt = s_min( hIsmMeta[ch]->ism_md_inc_diff_cnt, ISM_MD_INC_DIFF_CNT_MAX );
     831      308322 :         move16();
     832             :     }
     833             : 
     834      381151 :     FOR( ch = 0; ch < nchan_transport; ch++ )
     835             :     {
     836      274244 :         hSCE[ch]->hCoreCoder[0]->low_rate_mode = 0;
     837      274244 :         move16();
     838      274244 :         test();
     839      274244 :         IF( EQ_16( ism_mode, ISM_MODE_DISC ) )
     840             :         {
     841      222902 :             test();
     842      222902 :             test();
     843      222902 :             test();
     844      222902 :             test();
     845      229434 :             if ( EQ_16( ism_imp[ch], ISM_NO_META ) && ( ( LT_32( total_brate[ch], ACELP_8k00 ) && LT_32( element_brate[ch], SCE_CORE_16k_LOW_LIMIT ) ) ||
     846       12345 :                                                         ( LE_32( total_brate[ch], ACELP_16k_LOW_LIMIT ) && GE_32( element_brate[ch], SCE_CORE_16k_LOW_LIMIT ) ) ) )
     847             :             {
     848        7518 :                 hSCE[ch]->hCoreCoder[0]->low_rate_mode = 1;
     849        7518 :                 move16();
     850             :             }
     851             : 
     852      222902 :             hSCE[ch]->element_brate = element_brate[ch];
     853      222902 :             move32();
     854             :         }
     855       51342 :         ELSE IF( EQ_16( ism_mode, ISM_MASA_MODE_DISC ) || EQ_16( ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) )
     856             :         {
     857       10514 :             IF( ism_imp[ch] == ISM_INACTIVE_IMP )
     858             :             {
     859           0 :                 hSCE[ch]->hCoreCoder[0]->low_rate_mode = 1;
     860           0 :                 move16();
     861             :             }
     862             :         }
     863             : 
     864      274244 :         hSCE[ch]->hCoreCoder[0]->total_brate = total_brate[ch];
     865      274244 :         move32();
     866             : 
     867             :         /* write metadata only in active frames */
     868      274244 :         IF( GT_32( hSCE[0]->hCoreCoder[0]->core_brate, SID_2k40 ) )
     869             :         {
     870           0 :             reset_indices_enc_fx( hSCE[ch]->hMetaData, hSCE[ch]->hMetaData->nb_ind_tot );
     871             :         }
     872             :     }
     873             : 
     874      106907 :     pop_wmops();
     875             : 
     876      106907 :     return error;
     877             : }
     878             : 
     879             : /*-------------------------------------------------------------------------
     880             :  * ivas_ism_metadata_enc_create()
     881             :  *
     882             :  * Create, allocate, initialize and configure IVAS encoder ISM metadata handles
     883             :  *-------------------------------------------------------------------------*/
     884             : 
     885         153 : ivas_error ivas_ism_metadata_enc_create_fx(
     886             :     Encoder_Struct *st_ivas,   /* i/o: IVAS encoder structure      */
     887             :     const Word16 n_ISms,       /* i  : number of objects           */
     888             :     Word32 element_brate_tmp[] /* o  : element bitrate per object  */
     889             : )
     890             : {
     891             :     Word16 ch, nchan_transport;
     892             :     ivas_error error;
     893             : 
     894         153 :     nchan_transport = st_ivas->nchan_transport;
     895         153 :     move16();
     896         153 :     IF( EQ_32( st_ivas->hEncoderConfig->ivas_format, MASA_ISM_FORMAT ) )
     897             :     {
     898          44 :         nchan_transport = MAX_PARAM_ISM_WAVE;
     899          44 :         move16();
     900          44 :         ivas_set_omasa_TC_fx( st_ivas->ism_mode, n_ISms, &st_ivas->nSCE, &st_ivas->nCPE );
     901             :     }
     902         109 :     ELSE IF( EQ_32( st_ivas->hEncoderConfig->ivas_format, SBA_ISM_FORMAT ) )
     903             :     {
     904          35 :         nchan_transport = n_ISms;
     905          35 :         move16();
     906             :     }
     907             :     ELSE
     908             :     {
     909          74 :         IF( EQ_32( st_ivas->ism_mode, ISM_MODE_NONE ) )
     910             :         {
     911           0 :             nchan_transport = st_ivas->nchan_transport;
     912           0 :             move16();
     913             : 
     914           0 :             IF( EQ_16( nchan_transport, 1 ) )
     915             :             {
     916           0 :                 st_ivas->nSCE = 1;
     917           0 :                 move16();
     918           0 :                 st_ivas->nCPE = 0;
     919           0 :                 move16();
     920             :             }
     921             :             ELSE
     922             :             {
     923           0 :                 st_ivas->nSCE = 0;
     924           0 :                 move16();
     925           0 :                 st_ivas->nCPE = 1;
     926           0 :                 move16();
     927             :             }
     928             :         }
     929          74 :         ELSE IF( EQ_32( st_ivas->ism_mode, ISM_MODE_PARAM ) )
     930             :         {
     931          17 :             nchan_transport = 2;
     932          17 :             move16();
     933             :         }
     934             :         ELSE
     935             :         {
     936          57 :             nchan_transport = n_ISms;
     937          57 :             move16();
     938             :         }
     939             : 
     940          74 :         st_ivas->nchan_transport = nchan_transport;
     941          74 :         st_ivas->nSCE = nchan_transport;
     942          74 :         st_ivas->nCPE = 0;
     943          74 :         move16();
     944          74 :         move16();
     945          74 :         move16();
     946             :     }
     947             : 
     948             :     /* allocate ISM metadata handles */
     949         612 :     FOR( ch = 0; ch < n_ISms; ch++ )
     950             :     {
     951         459 :         IF( ( st_ivas->hIsmMetaData[ch] = (ISM_METADATA_HANDLE) malloc( sizeof( ISM_METADATA_FRAME ) ) ) == NULL )
     952             :         {
     953           0 :             return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for ISM MetaData\n" ) );
     954             :         }
     955         459 :         st_ivas->hIsmMetaData[ch]->position_angle.last_angle1_idx = 0;
     956         459 :         move16();
     957         459 :         st_ivas->hIsmMetaData[ch]->position_angle.angle1_diff_cnt = ISM_FEC_MAX;
     958         459 :         move16();
     959         459 :         st_ivas->hIsmMetaData[ch]->position_angle.last_angle2_idx = 0;
     960         459 :         move16();
     961         459 :         st_ivas->hIsmMetaData[ch]->position_angle.angle2_diff_cnt = ISM_FEC_MAX - 1;
     962         459 :         move16();
     963         459 :         st_ivas->hIsmMetaData[ch]->orientation_angle.last_angle1_idx = 0;
     964         459 :         move16();
     965         459 :         st_ivas->hIsmMetaData[ch]->orientation_angle.angle1_diff_cnt = ISM_FEC_MAX - 2;
     966         459 :         move16();
     967         459 :         st_ivas->hIsmMetaData[ch]->orientation_angle.last_angle2_idx = 0;
     968         459 :         move16();
     969         459 :         st_ivas->hIsmMetaData[ch]->orientation_angle.angle2_diff_cnt = ISM_FEC_MAX - 2;
     970         459 :         move16();
     971         459 :         st_ivas->hIsmMetaData[ch]->last_radius_idx = 0;
     972         459 :         move16();
     973         459 :         st_ivas->hIsmMetaData[ch]->radius_diff_cnt = ISM_FEC_MAX - 2;
     974         459 :         move16();
     975         459 :         st_ivas->hIsmMetaData[ch]->last_ism_metadata_flag = 0;
     976         459 :         move16();
     977             : 
     978         459 :         st_ivas->hIsmMetaData[ch]->ism_imp = -1;
     979         459 :         move16();
     980         459 :         st_ivas->hIsmMetaData[ch]->ism_md_null_flag = 0;
     981         459 :         move16();
     982         459 :         st_ivas->hIsmMetaData[ch]->ism_md_lowrate_flag = 0;
     983         459 :         move16();
     984             : 
     985         459 :         st_ivas->hIsmMetaData[ch]->q_azimuth_old_fx = 0;
     986         459 :         move16();
     987         459 :         st_ivas->hIsmMetaData[ch]->q_elevation_old_fx = 0;
     988         459 :         move16();
     989             : 
     990         459 :         ivas_ism_reset_metadata_enc( st_ivas->hIsmMetaData[ch] );
     991             : 
     992         459 :         st_ivas->hIsmMetaData[ch]->last_azimuth_fx = 0; // Q22
     993         459 :         move32();
     994         459 :         st_ivas->hIsmMetaData[ch]->last_elevation_fx = 0; // Q22
     995         459 :         move32();
     996             : 
     997         459 :         st_ivas->hIsmMetaData[ch]->last_true_azimuth_fx = 0; // Q22
     998         459 :         move32();
     999         459 :         st_ivas->hIsmMetaData[ch]->last_true_elevation_fx = 0; // Q22
    1000         459 :         move32();
    1001             : 
    1002         459 :         st_ivas->hIsmMetaData[ch]->ism_md_fec_cnt_enc = 0;
    1003         459 :         move16();
    1004         459 :         st_ivas->hIsmMetaData[ch]->ism_md_inc_diff_cnt = ISM_MD_INC_DIFF_CNT_MAX;
    1005         459 :         move16();
    1006         459 :         st_ivas->hIsmMetaData[ch]->last_true_radius_fx = ONE_IN_Q9; // Q9
    1007         459 :         move16();
    1008             :     }
    1009             : 
    1010         153 :     IF( EQ_16( st_ivas->hEncoderConfig->ivas_format, MASA_ISM_FORMAT ) )
    1011             :     {
    1012          44 :         test();
    1013          44 :         IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) || EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) )
    1014             :         {
    1015          20 :             IF( NE_32( ( error = ivas_ism_config_fx( st_ivas->hEncoderConfig->ivas_total_brate, nchan_transport, 1, NULL, 0, NULL, NULL, element_brate_tmp, NULL, NULL, 1 ) ), IVAS_ERR_OK ) )
    1016             :             {
    1017           0 :                 return error;
    1018             :             }
    1019             :         }
    1020          24 :         ELSE IF( EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) )
    1021             :         {
    1022          17 :             IF( NE_32( ( error = ivas_ism_config_fx( st_ivas->hEncoderConfig->ivas_total_brate, nchan_transport, n_ISms, NULL, 0, NULL, NULL, element_brate_tmp, NULL, NULL, 1 ) ), IVAS_ERR_OK ) )
    1023             :             {
    1024           0 :                 return error;
    1025             :             }
    1026             :         }
    1027             :     }
    1028             :     ELSE
    1029             :     {
    1030         109 :         IF( NE_32( ( error = ivas_ism_config_fx( st_ivas->hEncoderConfig->ivas_total_brate, nchan_transport, n_ISms, NULL, 0, NULL, NULL, element_brate_tmp, NULL, NULL, 0 ) ), IVAS_ERR_OK ) )
    1031             :         {
    1032           0 :             return error;
    1033             :         }
    1034             :     }
    1035             : 
    1036         153 :     return IVAS_ERR_OK;
    1037             : }
    1038             : 
    1039             : /*-------------------------------------------------------------------------
    1040             :  * encode_radius()
    1041             :  *
    1042             :  * Radius index encoding
    1043             :  *-------------------------------------------------------------------------*/
    1044       25625 : static void encode_radius_fx(
    1045             :     BSTR_ENC_HANDLE hBstr,               /* i/o: bitstream handle           */
    1046             :     Word16 *last_radius_idx,             /* i/o: last radius index          */
    1047             :     Word16 *radius_diff_cnt,             /* i/o: radius diff coding counter */
    1048             :     const Word16 last_ism_metadata_flag, /* last frame ism_metadata_flag    */
    1049             :     const Word16 idx_radius_abs,         /* i  : Azimuth index              */
    1050             :     Word16 *flag_abs_radius              /* o  : Radius encoding mode       */
    1051             : )
    1052             : {
    1053             :     Word16 idx_radius, nbits_diff_radius, diff;
    1054             : 
    1055       25625 :     idx_radius = idx_radius_abs;
    1056       25625 :     nbits_diff_radius = 0;
    1057       25625 :     move16();
    1058       25625 :     *flag_abs_radius = 0; /* differential coding by default */
    1059       25625 :     move16();
    1060             : 
    1061       25625 :     test();
    1062       25625 :     if ( EQ_16( *radius_diff_cnt, ISM_FEC_MAX ) /* make differential encoding in ISM_FEC_MAX consecutive frames at maximum (in order to control the decoding in FEC) */
    1063       23793 :          || last_ism_metadata_flag == 0         /* If last frame had no metadata coded, do not use differential coding */
    1064             :     )
    1065             :     {
    1066        2190 :         *flag_abs_radius = 1;
    1067        2190 :         move16();
    1068             :     }
    1069             : 
    1070       25625 :     diff = sub( idx_radius_abs, *last_radius_idx );
    1071             : 
    1072             :     /* try differential coding */
    1073       25625 :     IF( *flag_abs_radius == 0 )
    1074             :     {
    1075       23435 :         IF( diff == 0 )
    1076             :         {
    1077       15312 :             idx_radius = 0;
    1078       15312 :             move16();
    1079       15312 :             nbits_diff_radius = 1;
    1080       15312 :             move16();
    1081             :         }
    1082        8123 :         ELSE IF( LE_16( ABSVAL( diff ), ISM_MAX_RADIUS_DIFF_IDX ) )
    1083             :         {
    1084        3096 :             idx_radius = 2; // shl( 1, 1 );
    1085        3096 :             move16();
    1086        3096 :             nbits_diff_radius = 1;
    1087        3096 :             move16();
    1088             : 
    1089        3096 :             IF( diff < 0 )
    1090             :             {
    1091        1428 :                 idx_radius = add( idx_radius, 1 ); /* negative sign */
    1092        1428 :                 diff = imult1616( diff, -1 );
    1093             :             }
    1094             :             ELSE
    1095             :             {
    1096        1668 :                 idx_radius = add( idx_radius, 0 ); /* positive sign */
    1097             :             }
    1098             : 
    1099        3096 :             idx_radius = shl( idx_radius, diff );
    1100        3096 :             nbits_diff_radius = add( nbits_diff_radius, 1 );
    1101             : 
    1102             :             /* unary coding of "diff */
    1103        3096 :             idx_radius = add( idx_radius, sub( shl( 1, diff ), 1 ) );
    1104        3096 :             nbits_diff_radius = add( nbits_diff_radius, diff );
    1105             : 
    1106        3096 :             IF( LT_16( nbits_diff_radius, ISM_RADIUS_NBITS ) )
    1107             :             {
    1108             :                 /* add stop bit */
    1109        2910 :                 idx_radius = shl( idx_radius, 1 );
    1110        2910 :                 nbits_diff_radius = add( nbits_diff_radius, 1 );
    1111             :             }
    1112             :         }
    1113             :         ELSE
    1114             :         {
    1115        5027 :             *flag_abs_radius = 1;
    1116        5027 :             move16();
    1117             :         }
    1118             :     }
    1119             : 
    1120             :     /* update counter */
    1121       25625 :     IF( *flag_abs_radius == 0 )
    1122             :     {
    1123       18408 :         *radius_diff_cnt = add( *radius_diff_cnt, 1 );
    1124       18408 :         move16();
    1125       18408 :         *radius_diff_cnt = s_min( *radius_diff_cnt, ISM_FEC_MAX );
    1126       18408 :         move16();
    1127             :     }
    1128             :     ELSE
    1129             :     {
    1130        7217 :         *radius_diff_cnt = 0;
    1131        7217 :         move16();
    1132             :     }
    1133             : 
    1134             :     /* Write radius */
    1135       25625 :     push_indice( hBstr, IND_ISM_RADIUS_DIFF_FLAG, *flag_abs_radius, 1 );
    1136             : 
    1137       25625 :     IF( *flag_abs_radius )
    1138             :     {
    1139        7217 :         push_indice( hBstr, IND_ISM_RADIUS, idx_radius, ISM_RADIUS_NBITS );
    1140             :     }
    1141             :     ELSE
    1142             :     {
    1143       18408 :         push_indice( hBstr, IND_ISM_RADIUS, idx_radius, nbits_diff_radius );
    1144             :     }
    1145             : 
    1146             :     /* Updates */
    1147       25625 :     *last_radius_idx = idx_radius_abs;
    1148       25625 :     move16();
    1149             : 
    1150       25625 :     return;
    1151             : }
    1152             : 
    1153             : /*----------------------------------------------------------------*
    1154             :  * encode_angle_indices()
    1155             :  *
    1156             :  * Encoding of an angle
    1157             :  *----------------------------------------------------------------*/
    1158             : 
    1159      380440 : static void encode_angle_indices_fx(
    1160             :     BSTR_ENC_HANDLE hBstr,               /* i/o: bitstream handle              */
    1161             :     ISM_METADATA_ANGLE_HANDLE angle,     /* i/o: angle handle                  */
    1162             :     const Word16 last_ism_metadata_flag, /* i  : last frame ism_metadata_flag  */
    1163             :     const Word16 ini_frame,              /* i  : initialization frames counter */
    1164             :     const Word16 idx_angle1_abs,         /* i  : Azimuth index                 */
    1165             :     const Word16 idx_angle2_abs,         /* i  : Elevation index               */
    1166             :     Word16 *flag_abs_angle1,             /* o  : Azimuth/yaw encoding mode     */
    1167             :     Word16 *flag_abs_angle2              /* o  : Elevation/pitch encoding mode */
    1168             : )
    1169             : {
    1170             :     Word16 idx_angle1, nbits_diff_angle1, diff;
    1171             :     Word16 idx_angle2, nbits_diff_angle2;
    1172             : 
    1173             :     /*----------------------------------------------------------------*
    1174             :      * Azimuth/yaw index encoding
    1175             :      *----------------------------------------------------------------*/
    1176             : 
    1177      380440 :     idx_angle1 = idx_angle1_abs;
    1178      380440 :     move16();
    1179             : 
    1180      380440 :     nbits_diff_angle1 = 0;
    1181      380440 :     move16();
    1182      380440 :     *flag_abs_angle1 = 0; /* differential coding by default */
    1183      380440 :     test();
    1184      380440 :     IF( EQ_16( angle->angle1_diff_cnt, ISM_FEC_MAX ) /* make differential encoding in ISM_FEC_MAX consecutive frames at maximum (in order to control the decoding in FEC) */
    1185             :         || last_ism_metadata_flag == 0               /* If last frame had no metadata coded, do not use differential coding */
    1186             :     )
    1187             :     {
    1188       32275 :         *flag_abs_angle1 = 1;
    1189       32275 :         move16();
    1190             :     }
    1191             : 
    1192             :     /* try differential coding */
    1193      380440 :     IF( *flag_abs_angle1 == 0 )
    1194             :     {
    1195      348165 :         diff = sub( idx_angle1_abs, angle->last_angle1_idx );
    1196             : 
    1197             :         /* azimuth is on a circle - check for diff coding for -180° -> 180° and vice versa changes */
    1198      348165 :         IF( GT_16( abs_s( diff ), ( ( 1 << ISM_AZIMUTH_NBITS ) - 1 ) - ISM_MAX_AZIMUTH_DIFF_IDX ) )
    1199             :         {
    1200        3859 :             IF( diff > 0 )
    1201             :             {
    1202        1376 :                 diff = sub( diff, ( 1 << ISM_AZIMUTH_NBITS ) - 1 );
    1203             :             }
    1204             :             ELSE
    1205             :             {
    1206        2483 :                 diff = add( diff, ( 1 << ISM_AZIMUTH_NBITS ) - 1 );
    1207             :             }
    1208             :         }
    1209             : 
    1210      348165 :         IF( diff == 0 )
    1211             :         {
    1212       60108 :             idx_angle1 = 0;
    1213       60108 :             move16();
    1214       60108 :             nbits_diff_angle1 = 1;
    1215       60108 :             move16();
    1216             :         }
    1217      288057 :         ELSE IF( LT_16( abs_s( diff ), ISM_MAX_AZIMUTH_DIFF_IDX ) ) /* when diff bits >= abs bits, prefer abs */
    1218             :         {
    1219      201103 :             idx_angle1 = 2; // shl( 1, 1 );
    1220      201103 :             move16();
    1221      201103 :             nbits_diff_angle1 = 1;
    1222      201103 :             move16();
    1223             : 
    1224      201103 :             IF( diff < 0 )
    1225             :             {
    1226       65134 :                 idx_angle1 = add( idx_angle1, 1 ); /* negative sign */
    1227       65134 :                 diff = imult1616( diff, -1 );
    1228             :             }
    1229             :             ELSE
    1230             :             {
    1231      135969 :                 idx_angle1 = add( idx_angle1, 0 ); /* positive sign */
    1232             :             }
    1233             : 
    1234      201103 :             idx_angle1 = shl( idx_angle1, diff );
    1235      201103 :             nbits_diff_angle1 = add( nbits_diff_angle1, 1 );
    1236             : 
    1237             :             /* unary coding of "diff */
    1238      201103 :             idx_angle1 = add( idx_angle1, sub( shl( 1, diff ), 1 ) );
    1239      201103 :             nbits_diff_angle1 = add( nbits_diff_angle1, diff );
    1240             : 
    1241      201103 :             IF( LT_16( nbits_diff_angle1, ( ISM_AZIMUTH_NBITS - 1 ) ) )
    1242             :             {
    1243             :                 /* add stop bit - only for codewords shorter than ISM_AZIMUTH_NBITS */
    1244      184150 :                 idx_angle1 = shl( idx_angle1, 1 );
    1245      184150 :                 nbits_diff_angle1 = add( nbits_diff_angle1, 1 );
    1246             :             }
    1247             :         }
    1248             :         ELSE
    1249             :         {
    1250       86954 :             *flag_abs_angle1 = 1;
    1251       86954 :             move16();
    1252             :         }
    1253             :     }
    1254             : 
    1255             :     /* update counter */
    1256      380440 :     IF( *flag_abs_angle1 == 0 )
    1257             :     {
    1258      261211 :         angle->angle1_diff_cnt = add( angle->angle1_diff_cnt, 1 );
    1259      261211 :         move16();
    1260      261211 :         angle->angle1_diff_cnt = s_min( angle->angle1_diff_cnt, ISM_FEC_MAX );
    1261      261211 :         move16();
    1262             :     }
    1263             :     ELSE
    1264             :     {
    1265      119229 :         angle->angle1_diff_cnt = 0;
    1266      119229 :         move16();
    1267             :     }
    1268             : 
    1269             :     /* Write azimuth/yaw */
    1270      380440 :     push_indice( hBstr, IND_ISM_AZIMUTH_DIFF_FLAG, *flag_abs_angle1, 1 );
    1271             : 
    1272      380440 :     IF( *flag_abs_angle1 )
    1273             :     {
    1274      119229 :         push_indice( hBstr, IND_ISM_AZIMUTH, idx_angle1, ISM_AZIMUTH_NBITS );
    1275             :     }
    1276             :     ELSE
    1277             :     {
    1278      261211 :         push_indice( hBstr, IND_ISM_AZIMUTH, idx_angle1, nbits_diff_angle1 );
    1279             :     }
    1280             : 
    1281             :     /*----------------------------------------------------------------*
    1282             :      * Elevation/pitch index encoding
    1283             :      *----------------------------------------------------------------*/
    1284             : 
    1285      380440 :     IF( flag_abs_angle2 )
    1286             :     {
    1287      379635 :         idx_angle2 = idx_angle2_abs;
    1288      379635 :         move16();
    1289      379635 :         nbits_diff_angle2 = 0;
    1290      379635 :         move16();
    1291      379635 :         *flag_abs_angle2 = 0; /* differential coding by default */
    1292      379635 :         move16();
    1293      379635 :         if ( EQ_16( angle->angle2_diff_cnt, ISM_FEC_MAX ) /* make differential encoding in ISM_FEC_MAX consecutive frames at maximum (in order to control the decoding in FEC) */
    1294      270977 :              || last_ism_metadata_flag == 0               /* If last frame had no metadata coded, do not use differential coding */
    1295             :         )
    1296             :         {
    1297      109216 :             *flag_abs_angle2 = 1;
    1298      109216 :             move16();
    1299             :         }
    1300             : 
    1301             :         /* note: elevation/pitch is coded starting from the second frame only (it is meaningless in the init_frame) */
    1302      379635 :         IF( ini_frame == 0 )
    1303             :         {
    1304        1135 :             *flag_abs_angle2 = 1;
    1305        1135 :             move16();
    1306        1135 :             angle->last_angle2_idx = idx_angle2_abs;
    1307        1135 :             move16();
    1308             :         }
    1309             : 
    1310      379635 :         diff = sub( idx_angle2_abs, angle->last_angle2_idx );
    1311             : 
    1312             :         /* avoid absolute coding of elevation/pitch if absolute coding was already used for azimuth/yaw */
    1313      379635 :         IF( EQ_16( *flag_abs_angle1, 1 ) )
    1314             :         {
    1315      119154 :             Word16 diff_orig = diff;
    1316             : 
    1317      119154 :             *flag_abs_angle2 = 0;
    1318      119154 :             move16();
    1319             : 
    1320             : 
    1321      119154 :             IF( diff >= 0 )
    1322             :             {
    1323       74487 :                 diff = s_min( diff, ISM_MAX_ELEVATION_DIFF_IDX );
    1324             :             }
    1325             :             ELSE
    1326             :             {
    1327       44667 :                 diff = imult1616( -1, s_min( -diff, ISM_MAX_ELEVATION_DIFF_IDX ) );
    1328             :             }
    1329             : 
    1330      119154 :             test();
    1331      119154 :             if ( last_ism_metadata_flag == 0 || GT_16( abs_s( sub( diff_orig, diff ) ), ISM_MAX_ELEVATION_DIFF_IDX ) )
    1332             :             {
    1333       46226 :                 angle->angle2_diff_cnt = ISM_FEC_MAX - 1;
    1334       46226 :                 move16();
    1335             :             }
    1336             :         }
    1337             : 
    1338             :         /* try differential coding */
    1339      379635 :         IF( *flag_abs_angle2 == 0 )
    1340             :         {
    1341      351903 :             IF( diff == 0 )
    1342             :             {
    1343      143070 :                 idx_angle2 = 0;
    1344      143070 :                 move16();
    1345      143070 :                 nbits_diff_angle2 = 1;
    1346      143070 :                 move16();
    1347             :             }
    1348      208833 :             ELSE IF( LE_16( abs_s( diff ), ISM_MAX_ELEVATION_DIFF_IDX ) )
    1349             :             {
    1350      204402 :                 idx_angle2 = 2; // shl( 1, 1 );
    1351      204402 :                 move16();
    1352      204402 :                 nbits_diff_angle2 = 1;
    1353      204402 :                 move16();
    1354             : 
    1355      204402 :                 IF( diff < 0 )
    1356             :                 {
    1357      102469 :                     idx_angle2 = add( idx_angle2, 1 ); /* negative sign */
    1358      102469 :                     diff = imult1616( diff, -1 );
    1359             :                 }
    1360             :                 ELSE
    1361             :                 {
    1362      101933 :                     idx_angle2 = add( idx_angle2, 0 ); /* positive sign */
    1363             :                 }
    1364             : 
    1365      204402 :                 idx_angle2 = shl( idx_angle2, diff );
    1366      204402 :                 nbits_diff_angle2 = add( nbits_diff_angle2, 1 );
    1367             : 
    1368             :                 /* unary coding of "diff */
    1369      204402 :                 idx_angle2 = add( idx_angle2, sub( shl( 1, diff ), 1 ) );
    1370      204402 :                 nbits_diff_angle2 = add( nbits_diff_angle2, diff );
    1371             : 
    1372      204402 :                 IF( LT_16( nbits_diff_angle2, ISM_ELEVATION_NBITS ) )
    1373             :                 {
    1374             :                     /* add stop bit */
    1375      136562 :                     idx_angle2 = shl( idx_angle2, 1 );
    1376      136562 :                     nbits_diff_angle2 = add( nbits_diff_angle2, 1 );
    1377             :                 }
    1378             :             }
    1379             :             ELSE
    1380             :             {
    1381        4431 :                 *flag_abs_angle2 = 1;
    1382        4431 :                 move16();
    1383             :             }
    1384             :         }
    1385             : 
    1386             :         /* update counter */
    1387      379635 :         IF( *flag_abs_angle2 == 0 )
    1388             :         {
    1389      347472 :             angle->angle2_diff_cnt = add( angle->angle2_diff_cnt, 1 );
    1390      347472 :             move16();
    1391      347472 :             angle->angle2_diff_cnt = s_min( angle->angle2_diff_cnt, ISM_FEC_MAX );
    1392      347472 :             move16();
    1393             :         }
    1394             :         ELSE
    1395             :         {
    1396       32163 :             angle->angle2_diff_cnt = 0;
    1397       32163 :             move16();
    1398             :         }
    1399             : 
    1400             :         /* Write elevation */
    1401      379635 :         IF( *flag_abs_angle1 == 0 ) /* do not write "flag_abs_elevation/pitch" if "flag_abs_azimuth/yaw == 1" */
    1402             :         {
    1403      260481 :             push_indice( hBstr, IND_ISM_ELEVATION_DIFF_FLAG, *flag_abs_angle2, 1 );
    1404             :         }
    1405             : 
    1406      379635 :         IF( *flag_abs_angle2 )
    1407             :         {
    1408       32163 :             push_indice( hBstr, IND_ISM_ELEVATION, idx_angle2, ISM_ELEVATION_NBITS );
    1409             :         }
    1410             :         ELSE
    1411             :         {
    1412      347472 :             push_indice( hBstr, IND_ISM_ELEVATION, idx_angle2, nbits_diff_angle2 );
    1413             :         }
    1414             :     }
    1415             : 
    1416             :     /*----------------------------------------------------------------*
    1417             :      * Updates
    1418             :      *----------------------------------------------------------------*/
    1419             : 
    1420      380440 :     angle->last_angle1_idx = idx_angle1_abs;
    1421      380440 :     move16();
    1422      380440 :     angle->last_angle2_idx = idx_angle2_abs;
    1423      380440 :     move16();
    1424             : 
    1425      380440 :     return;
    1426             : }
    1427             : 
    1428             : /*-------------------------------------------------------------------*
    1429             :  * ivas_ism_metadata_sid_enc()
    1430             :  *
    1431             :  * Quantize and encode ISM metadata in SID frame
    1432             :  *-------------------------------------------------------------------*/
    1433             : 
    1434        2115 : void ivas_ism_metadata_sid_enc_fx(
    1435             :     ISM_DTX_HANDLE hISMDTX,         /* i/o: ISM DTX handle                 */
    1436             :     const Word16 flag_noisy_speech, /* i  : noisy speech flag              */
    1437             :     const Word16 nchan_ism,         /* i  : number of objects              */
    1438             :     const Word16 nchan_transport,   /* i  : number of transport channels   */
    1439             :     const ISM_MODE ism_mode,        /* i  : ISM mode                       */
    1440             :     ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handles           */
    1441             :     const Word16 sid_flag,          /* i  : indication of SID frame        */
    1442             :     const Word16 md_diff_flag[],    /* i  : metadata differental flag      */
    1443             :     BSTR_ENC_HANDLE hBstr,          /* i/o: bitstream handle               */
    1444             :     Word16 nb_bits_metadata[]       /* o  : number of metadata bits        */
    1445             : )
    1446             : {
    1447             :     Word16 i, ch, nBits, nBits_start, nBits_unused;
    1448             :     Word32 q_step_fx, q_step_border_fx;
    1449             :     Word16 idx, idx_azimuth, idx_elevation;
    1450             :     Word16 nBits_azimuth, nBits_elevation, nBits_coh, nBits_sce_id;
    1451             :     Word32 valQ_fx;
    1452             : 
    1453             :     ISM_METADATA_HANDLE hIsmMetaData;
    1454             : 
    1455        2115 :     IF( sid_flag )
    1456             :     {
    1457         535 :         nBits = ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC;
    1458         535 :         move16();
    1459         535 :         nBits = sub( nBits, SID_FORMAT_NBITS );
    1460         535 :         nBits_start = hBstr->nb_bits_tot;
    1461         535 :         move16();
    1462             : 
    1463             :         /*----------------------------------------------------------------*
    1464             :          * Write ISm common signaling
    1465             :          *----------------------------------------------------------------*/
    1466             : 
    1467             :         /* write number of objects - unary coding */
    1468        1765 :         FOR( ch = 1; ch < nchan_ism; ch++ )
    1469             :         {
    1470        1230 :             push_indice( hBstr, IND_ISM_NUM_OBJECTS, 1, 1 );
    1471             :         }
    1472         535 :         push_indice( hBstr, IND_ISM_NUM_OBJECTS, 0, 1 );
    1473             : 
    1474             :         /* write SID metadata flag (one per object) */
    1475        2300 :         FOR( ch = 0; ch < nchan_ism; ch++ )
    1476             :         {
    1477        1765 :             push_indice( hBstr, IND_ISM_METADATA_FLAG, md_diff_flag[ch], 1 );
    1478             :         }
    1479             : 
    1480             :         /*----------------------------------------------------------------*
    1481             :          * Set quantization bits based on the number of coded objects
    1482             :          *----------------------------------------------------------------*/
    1483             : 
    1484         535 :         ivas_get_ism_sid_quan_bitbudget_fx( nchan_ism, &nBits_azimuth, &nBits_elevation, &q_step_fx, &q_step_border_fx, &nBits_coh, &nBits_sce_id );
    1485             : 
    1486             :         /*----------------------------------------------------------------*
    1487             :          * Spatial parameters, loop over TCs - 1
    1488             :          *----------------------------------------------------------------*/
    1489             : 
    1490             :         /* write ISM mode flag to explicitly signal number of spatial parameters */
    1491         535 :         IF( GT_16( nchan_ism, 2 ) )
    1492             :         {
    1493         375 :             IF( EQ_16( ism_mode, ISM_MODE_DISC ) )
    1494             :             {
    1495         282 :                 push_indice( hBstr, IND_ISM_MD_INACTIVE_FLAG, 0, 1 );
    1496             :             }
    1497             :             ELSE
    1498             :             {
    1499          93 :                 push_indice( hBstr, IND_ISM_MD_INACTIVE_FLAG, 1, 1 );
    1500             :             }
    1501             : 
    1502         375 :             IF( EQ_16( ism_mode, ISM_MODE_PARAM ) )
    1503             :             {
    1504             :                 /* write noisy speech flag */
    1505          93 :                 push_indice( hBstr, IND_ISM_NOISY_SPEECH_FLAG, flag_noisy_speech, 1 );
    1506          93 :                 nBits_sce_id = 1;
    1507          93 :                 move16();
    1508             :             }
    1509             :         }
    1510             : 
    1511         535 :         IF( GT_16( nchan_transport, 1 ) )
    1512             :         {
    1513             :             /* write sce id */
    1514         480 :             push_indice( hBstr, IND_ISM_SCE_ID_DTX, hISMDTX->sce_id_dtx, nBits_sce_id );
    1515             : 
    1516             :             /* quantize and write coherence */
    1517        2004 :             FOR( ch = 0; ch < nchan_transport; ch++ )
    1518             :             {
    1519        1524 :                 IF( EQ_16( ch, hISMDTX->sce_id_dtx ) )
    1520             :                 {
    1521         480 :                     CONTINUE;
    1522             :                 }
    1523        1044 :                 Word32 tmp = Mpy_32_32( L_shr( L_deposit_h( hISMDTX->coh_fx[ch] ), 1 ) /*Q30*/, L_deposit_h( sub( shl( 1, nBits_coh ), 1 ) ) ); // Q15
    1524        1044 :                 Word32 tmp_2 = L_add( tmp, 16384 /*0.5f in Q15*/ );
    1525        1044 :                 idx = extract_l( L_shr( tmp_2, Q15 ) );
    1526             :                 // idx = (Word16) ( hISMDTX->coh[ch] * sub( shl( 1, nBits_coh ), 1 ) + 0.5f );
    1527        1044 :                 assert( ( idx >= 0 ) && ( idx <= ( ( 1 << nBits_coh ) - 1 ) ) );
    1528        1044 :                 push_indice( hBstr, IND_ISM_DTX_COH_SCA, idx, nBits_coh );
    1529             :             }
    1530             :         }
    1531             : 
    1532             :         /*----------------------------------------------------------------*
    1533             :          * Metadata quantization and coding, loop over all objects
    1534             :          *----------------------------------------------------------------*/
    1535             : 
    1536        2300 :         FOR( ch = 0; ch < nchan_ism; ch++ )
    1537             :         {
    1538        1765 :             IF( EQ_16( md_diff_flag[ch], 1 ) )
    1539             :             {
    1540         631 :                 hIsmMetaData = hIsmMeta[ch];
    1541             : 
    1542         631 :                 idx_azimuth = ism_quant_meta_fx( hIsmMetaData->azimuth_fx, &valQ_fx, ism_azimuth_borders_fx, q_step_fx, q_step_border_fx, shl( 1, nBits_azimuth ) );
    1543         631 :                 idx_elevation = ism_quant_meta_fx( hIsmMetaData->elevation_fx, &valQ_fx, ism_elevation_borders_fx, q_step_fx, q_step_border_fx, shl( 1, nBits_elevation ) );
    1544         631 :                 push_indice( hBstr, IND_ISM_AZIMUTH, idx_azimuth, nBits_azimuth );
    1545         631 :                 push_indice( hBstr, IND_ISM_ELEVATION, idx_elevation, nBits_elevation );
    1546             : 
    1547             :                 /* update last indexes to correspond to active frames coding */
    1548         631 :                 IF( GT_16( nBits_azimuth, ISM_AZIMUTH_NBITS ) )
    1549             :                 {
    1550         210 :                     hIsmMetaData->position_angle.last_angle1_idx = shr( idx_azimuth, sub( nBits_azimuth, ISM_AZIMUTH_NBITS ) );
    1551         210 :                     move16();
    1552         210 :                     hIsmMetaData->position_angle.last_angle2_idx = shr( idx_elevation, sub( nBits_elevation, ISM_ELEVATION_NBITS ) );
    1553         210 :                     move16();
    1554             :                 }
    1555             :                 ELSE
    1556             :                 {
    1557         421 :                     hIsmMetaData->position_angle.last_angle1_idx = shl( idx_azimuth, sub( ISM_AZIMUTH_NBITS, nBits_azimuth ) );
    1558         421 :                     move16();
    1559         421 :                     hIsmMetaData->position_angle.last_angle2_idx = shl( idx_elevation, sub( ISM_ELEVATION_NBITS, nBits_elevation ) );
    1560         421 :                     move16();
    1561             :                 }
    1562             : 
    1563         631 :                 hIsmMetaData->ism_md_fec_cnt_enc = 0;
    1564         631 :                 move16();
    1565         631 :                 hIsmMeta[ch]->ism_md_inc_diff_cnt = ISM_MD_INC_DIFF_CNT_MAX;
    1566         631 :                 move16();
    1567             :             }
    1568             :         }
    1569             : 
    1570             :         /* Write unused (padding) bits */
    1571         535 :         nBits_unused = sub( nBits, hBstr->nb_bits_tot );
    1572        1550 :         WHILE( nBits_unused > 0 )
    1573             :         {
    1574        1015 :             i = s_min( nBits_unused, 16 );
    1575        1015 :             push_indice( hBstr, IND_UNUSED, 0, i );
    1576        1015 :             nBits_unused = sub( nBits_unused, i );
    1577             :         }
    1578             : 
    1579         535 :         nb_bits_metadata[0] = sub( hBstr->nb_bits_tot, nBits_start );
    1580         535 :         move16();
    1581             :     }
    1582             : 
    1583        2115 :     return;
    1584             : }

Generated by: LCOV version 1.14