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

Generated by: LCOV version 1.14