LCOV - code coverage report
Current view: top level - lib_enc - ivas_ism_param_enc_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 277 286 96.9 %
Date: 2025-05-03 01:55:50 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /******************************************************************************************************
       2             : 
       3             :    (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
       4             :    Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
       5             :    Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
       6             :    Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
       7             :    contributors to this repository. All Rights Reserved.
       8             : 
       9             :    This software is protected by copyright law and by international treaties.
      10             :    The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
      11             :    Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
      12             :    Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
      13             :    Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
      14             :    contributors to this repository retain full ownership rights in their respective contributions in
      15             :    the software. This notice grants no license of any kind, including but not limited to patent
      16             :    license, nor is any license granted by implication, estoppel or otherwise.
      17             : 
      18             :    Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
      19             :    contributions.
      20             : 
      21             :    This software is provided "AS IS", without any express or implied warranties. The software is in the
      22             :    development stage. It is intended exclusively for experts who have experience with such software and
      23             :    solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
      24             :    and fitness for a particular purpose are hereby disclaimed and excluded.
      25             : 
      26             :    Any dispute, controversy or claim arising under or in relation to providing this software shall be
      27             :    submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
      28             :    accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
      29             :    the United Nations Convention on Contracts on the International Sales of Goods.
      30             : 
      31             : *******************************************************************************************************/
      32             : 
      33             : #include <stdint.h>
      34             : #include <math.h>
      35             : #include <assert.h>
      36             : #include "options.h"
      37             : #include "ivas_prot_fx.h"
      38             : #include "prot_fx.h"
      39             : #include "cnst.h"
      40             : #include "ivas_cnst.h"
      41             : #include "ivas_rom_com.h"
      42             : #include "wmc_auto.h"
      43             : #include "ivas_rom_com_fx.h"
      44             : 
      45             : /*-------------------------------------------------------------------------
      46             :  * Local function definitions
      47             :  *------------------------------------------------------------------------*/
      48             : 
      49       20720 : static void ivas_param_ism_compute_obj_parameters_fx(
      50             :     const Word16 nchan_ism,                                                                      /* i  : number of ISM channels     */
      51             :     Word64 reference_power_obj[MAX_NUM_OBJECTS][PARAM_ISM_MDFT_NO_SLOTS][DIRAC_NO_FB_BANDS_MAX], /* i  : Reference power         Qx */
      52             :     PARAM_ISM_CONFIG_HANDLE hParamIsm                                                            /* i/o: Param ISM Enc Handle       */
      53             : )
      54             : {
      55             :     Word16 i, b, m, br, mr;
      56             :     Word16 brange_start, brange_end, mrange_start, mrange_end, time_merge_fac;
      57             :     Word16 power_ratios_m[MAX_PARAM_ISM_NBANDS][MAX_PARAM_ISM_NBLOCKS];
      58             :     Word64 ref_power_local_frame[MAX_NUM_OBJECTS];
      59             :     Word64 tmp_ratio;
      60             :     Word16 e_tmp, tmp1, tmp2;
      61             :     Word64 Wtmp;
      62             : 
      63       20720 :     set64_fx( ref_power_local_frame, 0, MAX_NUM_OBJECTS );
      64             : 
      65       20720 :     assert( nchan_ism == 3 || nchan_ism == 4 );
      66             : 
      67      248640 :     FOR( b = 0; b < hParamIsm->nbands; b++ )
      68             :     {
      69             :         /* current frequency band borders */
      70      227920 :         brange_start = hParamIsm->band_grouping[b];
      71      227920 :         brange_end = hParamIsm->band_grouping[b + 1];
      72      227920 :         move16();
      73      227920 :         move16();
      74             : 
      75             :         /* time slots to aggregate for current block */
      76      227920 :         time_merge_fac = idiv1616( PARAM_ISM_MDFT_NO_SLOTS, hParamIsm->nblocks[b] );
      77             : 
      78      455840 :         FOR( m = 0; m < hParamIsm->nblocks[b]; m++ )
      79             :         {
      80             :             Word16 index_1, index_2;
      81             :             Word64 ref_power_local[MAX_NUM_OBJECTS];
      82             : 
      83             :             /* initialize to 0 so unused entries are not considered later */
      84      227920 :             set64_fx( ref_power_local, 0, MAX_NUM_OBJECTS );
      85             : 
      86             :             /* current block borders */
      87      227920 :             mrange_start = i_mult( m, time_merge_fac );
      88      227920 :             mrange_end = i_mult( add( m, 1 ), time_merge_fac );
      89             : 
      90             :             /* for each object, sum up reference power within current T/F tile */
      91             : 
      92     1065350 :             FOR( i = 0; i < nchan_ism; i++ )
      93             :             {
      94     4187150 :                 FOR( mr = mrange_start; mr < mrange_end; mr++ )
      95             :                 {
      96    76130000 :                     FOR( br = brange_start; br < brange_end; br++ )
      97             :                     {
      98    72780280 :                         ref_power_local[i] = W_add( ref_power_local[i], reference_power_obj[i][mr][br] ); // Qx
      99    72780280 :                         move64();
     100             :                     }
     101             :                 }
     102             :                 /* Sum up T/F tiles per object */
     103      837430 :                 ref_power_local_frame[i] = W_add( ref_power_local[i], ref_power_local_frame[i] ); // Qx
     104      837430 :                 move64();
     105             :             }
     106             : 
     107             :             /* find two dominant objects and derive object indices for current T/F tile */
     108      227920 :             IF( GE_64( ref_power_local[0], ref_power_local[1] ) )
     109             :             {
     110      108008 :                 index_1 = 0;
     111      108008 :                 index_2 = 1;
     112      108008 :                 move16();
     113      108008 :                 move16();
     114             :             }
     115             :             ELSE
     116             :             {
     117      119912 :                 index_1 = 1;
     118      119912 :                 index_2 = 0;
     119      119912 :                 move16();
     120      119912 :                 move16();
     121             :             }
     122             : 
     123      609510 :             FOR( i = MAX_PARAM_ISM_WAVE; i < nchan_ism; i++ )
     124             :             {
     125      381590 :                 IF( GT_64( ref_power_local[i], ref_power_local[index_1] ) )
     126             :                 {
     127       71885 :                     index_2 = index_1;
     128       71885 :                     index_1 = i;
     129       71885 :                     move16();
     130       71885 :                     move16();
     131             :                 }
     132      309705 :                 ELSE IF( GT_64( ref_power_local[i], ref_power_local[index_2] ) )
     133             :                 {
     134      107924 :                     index_2 = i;
     135      107924 :                     move16();
     136             :                 }
     137             :             }
     138             : 
     139             :             /* Copy the quantized indices */
     140      227920 :             hParamIsm->obj_indices[b][m][0] = index_1;
     141      227920 :             hParamIsm->obj_indices[b][m][1] = index_2;
     142      227920 :             move16();
     143      227920 :             move16();
     144             : 
     145             :             /* Compute power ratios */
     146      227920 :             IF( W_add( ref_power_local[index_1], ref_power_local[index_2] ) == 0 )
     147             :             {
     148           0 :                 power_ratios_m[b][m] = ONE_IN_Q14 /* 0.5 in Q15 */;
     149           0 :                 move16();
     150             :             }
     151             :             ELSE
     152             :             {
     153      227920 :                 tmp1 = W_norm( ref_power_local[index_1] );
     154      227920 :                 Wtmp = W_add( ref_power_local[index_1], ref_power_local[index_2] );
     155      227920 :                 tmp2 = W_norm( Wtmp );
     156      227920 :                 power_ratios_m[b][m] = BASOP_Util_Divide3232_Scale( W_extract_h( W_shl( ref_power_local[index_1], tmp1 ) ), W_extract_h( W_shl( Wtmp, tmp2 ) ), &e_tmp ); // ((Qx + tmp1) - 16) - ((Qx + tmp2) - 16) + 15 - e_tmp = 15 + tmp1 - tmp2 - e_tmp
     157      227920 :                 power_ratios_m[b][m] = shl_sat( power_ratios_m[b][m], sub( e_tmp, sub( tmp1, tmp2 ) ) );                                                                  // Q15
     158      227920 :                 move16();
     159      227920 :                 move16();
     160             :             }
     161      227920 :             assert( ( power_ratios_m[b][m] >= ONE_IN_Q14 /* 0.5 in Q15 */ ) && ( power_ratios_m[b][m] <= MAX_16 /* 1 in Q15 */ ) );
     162             : 
     163             :             /* Quantize power ratios */
     164             :             /* Power ratio range [0.5,1] is mapped to [0,1] first, rounding via truncation float->integer */
     165      227920 :             hParamIsm->power_ratios_idx[b][m] = extract_h( L_add( L_mult( shl( sub( power_ratios_m[b][m], ONE_IN_Q14 /* 0.5 in Q15 */ ), 1 ), ( ( 1 << PARAM_ISM_POW_RATIO_NBITS ) - 1 ) ), ONE_IN_Q15 /* 0.5f in Q16 */ ) ); // Q0
     166      227920 :             move16();
     167      227920 :             assert( ( hParamIsm->power_ratios_idx[b][m] >= 0 ) && ( hParamIsm->power_ratios_idx[b][m] <= ( ( 1 << PARAM_ISM_POW_RATIO_NBITS ) - 1 ) ) );
     168             :         }
     169             :     }
     170             : 
     171             :     /* Check if objects have roughly equal power by comparing reference power of first object against all others*/
     172       20720 :     hParamIsm->flag_equal_energy = 1;
     173       20720 :     move16();
     174       20917 :     FOR( i = 1; i < nchan_ism; i++ )
     175             :     {
     176       20916 :         IF( ref_power_local_frame[i] != 0 )
     177             :         {
     178       20916 :             tmp1 = W_norm( ref_power_local_frame[0] );
     179       20916 :             tmp2 = W_norm( ref_power_local_frame[i] );
     180       20916 :             tmp_ratio = BASOP_Util_Divide3232_Scale( W_extract_h( W_shl( ref_power_local_frame[0], tmp1 ) ), W_extract_h( W_shl( ref_power_local_frame[i], tmp2 ) ), &e_tmp ); // ((Qx + tmp1) - 16) - ((Qx + tmp2) - 16) + 15 - e_tmp = 15 + tmp1 - tmp2 - e_tmp
     181       20916 :             tmp_ratio = W_shl( tmp_ratio, sub( sub( e_tmp, 1 ), sub( tmp1, tmp2 ) ) );                                                                                         // Q14                                                                                        // Q14
     182             : 
     183       20916 :             test();
     184       20916 :             IF( GT_64( tmp_ratio, 15974 /* 0.975f in Q14 */ ) && LT_64( tmp_ratio, 16794 /* 1.025f in Q14*/ ) )
     185             :             {
     186         197 :                 hParamIsm->flag_equal_energy = s_and( hParamIsm->flag_equal_energy, 1 );
     187         197 :                 move16();
     188             :             }
     189             :             ELSE
     190             :             {
     191       20719 :                 hParamIsm->flag_equal_energy = s_and( hParamIsm->flag_equal_energy, 0 );
     192       20719 :                 move16();
     193       20719 :                 break;
     194             :             }
     195             :         }
     196             :     }
     197             : 
     198       20720 :     return;
     199             : }
     200             : 
     201             : 
     202       20720 : static void ivas_param_ism_enc_quantize_DOA_fx(
     203             :     const Word16 nchan_ism,                            /* i  : number of ISM channels                      */
     204             :     ISM_METADATA_HANDLE hIsmMetaData[MAX_NUM_OBJECTS], /* i  : ISM metadata             */
     205             :     PARAM_ISM_CONFIG_HANDLE hParamIsm                  /* i/o: Param ISM encoder handle */
     206             : )
     207             : {
     208             :     Word16 i, azi_idx, ele_idx;
     209             :     Word32 valQ_fx;
     210             : 
     211             :     /* Loop over objects */
     212       96850 :     FOR( i = 0; i < nchan_ism; i++ )
     213             :     {
     214             :         /* Quantize the elevation and obtain quantized elevation value and index */
     215       76130 :         ele_idx = ism_quant_meta_fx( hIsmMetaData[i]->elevation_fx, &valQ_fx, ism_elevation_borders_fx, ISM_Q_STEP_FX, ISM_Q_STEP_BORDER_FX, 1 << ISM_ELEVATION_NBITS );
     216             : 
     217             :         /* Obtain the index of quantized azimuth values */
     218       76130 :         azi_idx = ism_quant_meta_fx( hIsmMetaData[i]->azimuth_fx, &valQ_fx, ism_azimuth_borders_fx, ISM_Q_STEP_FX, ISM_Q_STEP_BORDER_FX, 1 << ISM_AZIMUTH_NBITS );
     219             : 
     220             :         /*Replace azimuth with quantized values */
     221       76130 :         hIsmMetaData[i]->azimuth_fx = valQ_fx; // Q22
     222       76130 :         move32();
     223             : 
     224             :         /* Copy the quantized indices */
     225       76130 :         hParamIsm->azi_index[i] = azi_idx;
     226       76130 :         move16();
     227       76130 :         hParamIsm->ele_index[i] = ele_idx;
     228       76130 :         move16();
     229             :     }
     230             : 
     231       20720 :     return;
     232             : }
     233             : 
     234             : 
     235             : /*-------------------------------------------------------------------------*
     236             :  * ivas_param_ism_stereo_dmx()
     237             :  *
     238             :  * Downmix input channels to stereo
     239             :  *-------------------------------------------------------------------------*/
     240       20720 : void ivas_param_ism_stereo_dmx_fx(
     241             :     Encoder_Struct *st_ivas,       /* i  : IVAS encoder structure     */
     242             :     Word32 *data[MAX_NUM_OBJECTS], /* i/o: input signal/stereo dmx Qx */
     243             :     const Word16 input_frame       /* i  : Length of input frame      */
     244             : )
     245             : {
     246             :     Word16 i, j;
     247             :     Word32 tmp;
     248             :     Word16 alpha, azi_shift;
     249             :     Word16 tmp_1, tmp_2, one_by_input_frame;
     250             :     Word16 cardioid_left[MAX_NUM_OBJECTS], cardioid_right[MAX_NUM_OBJECTS]; // Q14
     251             :     Word32 stereo_dmx[2][L_FRAME48k];
     252             :     Word16 dmx_gain, dmx_gain_e;
     253             :     Word64 ene_data, ene_dmx;
     254             :     Word16 grad;
     255             :     Word16 last_dmx_gain, last_dmx_gain_e;
     256             :     Word16 last_cardioid_left; // Q14
     257             :     ISM_METADATA_HANDLE hIsmMetaData;
     258             : 
     259       20720 :     push_wmops( "ivas_param_ism_st_dmx" );
     260             : 
     261             :     /*Initialization*/
     262       20720 :     alpha = ONE_IN_Q14 /* 0.5 in Q15 */;
     263       20720 :     move16();
     264       20720 :     azi_shift = 0; // Q13
     265       20720 :     move16();
     266       20720 :     dmx_gain = 0;
     267       20720 :     move16();
     268       20720 :     ene_dmx = 0;
     269       20720 :     move64();
     270       20720 :     ene_data = 0;
     271       20720 :     move64();
     272       20720 :     last_dmx_gain = st_ivas->hParamIsm->last_dmx_gain_fx;
     273       20720 :     move16();
     274       20720 :     last_dmx_gain_e = st_ivas->hParamIsm->last_dmx_gain_e;
     275       20720 :     move16();
     276             : 
     277             :     /* Set the stereo dmx to zero */
     278       20720 :     set_zero_fx( stereo_dmx[0], L_FRAME48k );
     279       20720 :     set_zero_fx( stereo_dmx[1], L_FRAME48k );
     280             : 
     281       20720 :     one_by_input_frame = BASOP_Util_Divide1616_Scale( 1, input_frame, &tmp_1 );
     282       20720 :     one_by_input_frame = shl( one_by_input_frame, tmp_1 ); // Q15
     283             : 
     284             :     /* Loop over all objects */
     285       96850 :     FOR( i = 0; i < st_ivas->hEncoderConfig->nchan_ism; i++ )
     286             :     {
     287       76130 :         hIsmMetaData = st_ivas->hIsmMetaData[i];
     288       76130 :         last_cardioid_left = st_ivas->hParamIsm->last_cardioid_left_fx[i];
     289       76130 :         move16();
     290             :         /*Compute the Cardioids for the corresponding object direction */
     291       76130 :         tmp = Mpy_32_32( hIsmMetaData->azimuth_fx, PI_OVER_180_FX ); // Q22
     292       76130 :         tmp_1 = add( EVS_PI_BY_2_FX, azi_shift );                    // Q13
     293       76130 :         tmp = L_sub( L_shr( tmp, Q22 - Q13 ), L_deposit_l( tmp_1 ) );
     294       76130 :         IF( LT_32( tmp, -EVS_PI_FX ) )
     295             :         {
     296       18065 :             tmp = L_add( tmp, 2 * EVS_PI_FX );
     297             :         }
     298       76130 :         cardioid_left[i] = add( shr( alpha, 1 ), mult( sub( ONE_IN_Q15 - 1, alpha ), getCosWord16( extract_l( tmp ) ) ) ); // Q14
     299       76130 :         move16();
     300             : 
     301       76130 :         IF( st_ivas->hSCE[0]->hCoreCoder[0]->ini_frame > 0 )
     302             :         {
     303             :             Word16 last_cardioid_right;
     304       76066 :             last_cardioid_right = sub( ONE_IN_Q14 /* 1.0f in Q14 */, last_cardioid_left );
     305             :             /* Smoothing */
     306       76066 :             cardioid_left[i] = add( mult( 24576 /* 0.75f in Q15 */, cardioid_left[i] ), mult( 8192 /* 0.25f in Q15 */, last_cardioid_left ) ); // Q14
     307       76066 :             move16();
     308       76066 :             Word32 grad_32 = L_mult( sub( cardioid_left[i], last_cardioid_left ), shl( one_by_input_frame, 1 ) /* 2.0f / (float) input_frame*/ ); /* Q14+Q16 = Q30 */ /* for the right cardioid, multiply with -1 */
     309             :             /* Cardioids sum up to 1 */
     310       76066 :             cardioid_right[i] = sub( ONE_IN_Q14 /* 1.0f in Q14 */, cardioid_left[i] ); /* corresponds to: alpha + ( 1 - alpha ) * cosf( tmp + tmp_1 ); */
     311       76066 :             move16();
     312             :             /* Loop over all samples */
     313    36587746 :             FOR( j = 0; j < input_frame >> 1; j++ )
     314             :             {
     315    36511680 :                 tmp = data[i][j];
     316    36511680 :                 move32();
     317    36511680 :                 tmp = W_extract_l( W_shr( W_mult_32_32( tmp, L_add( last_cardioid_left, L_shr( Mpy_32_32( L_shl( j, 22 ), grad_32 ), 7 ) ) ), 15 ) ); /* Qx DMX Left */
     318    36511680 :                 stereo_dmx[0][j] = L_add( stereo_dmx[0][j], tmp );                                                                                    /* Qx DMX Left */
     319    36511680 :                 move32();
     320    36511680 :                 tmp = data[i][j];
     321    36511680 :                 move32();
     322    36511680 :                 tmp = W_extract_l( W_shr( W_mult_32_32( tmp, L_add( last_cardioid_right, L_shr( L_negate( Mpy_32_32( L_shl( j, 22 ), grad_32 ) ), 7 ) ) ), 15 ) ); /* Qx DMX Right */
     323    36511680 :                 stereo_dmx[1][j] = L_add( stereo_dmx[1][j], tmp );                                                                                                 /* Qx DMX Right */
     324    36511680 :                 move32();
     325    36511680 :                 ene_data = W_add( ene_data, W_mult_32_32( data[i][j], data[i][j] ) ); /* 2 * Qx + 1 energy of all objects combined */
     326             :             }
     327    36587746 :             FOR( ; j < input_frame; j++ )
     328             :             {
     329    36511680 :                 tmp = data[i][j];
     330    36511680 :                 move32();
     331    36511680 :                 tmp = W_extract_l( W_shr( W_mult_32_16( tmp, cardioid_left[i] ), 15 ) ); /* Qx DMX Left  */
     332    36511680 :                 stereo_dmx[0][j] = L_add( stereo_dmx[0][j], tmp );                       /* Qx DMX Left  */
     333    36511680 :                 move32();
     334    36511680 :                 tmp = data[i][j];
     335    36511680 :                 move32();
     336    36511680 :                 tmp = W_extract_l( W_shr( W_mult_32_16( tmp, cardioid_right[i] ), 15 ) ); /* Qx DMX Right */
     337    36511680 :                 stereo_dmx[1][j] = L_add( stereo_dmx[1][j], tmp );                        /* Qx DMX Right */
     338    36511680 :                 move32();
     339    36511680 :                 ene_data = W_add( ene_data, W_mult_32_32( data[i][j], data[i][j] ) ); /* 2 * Qx + 1 energy of all objects combined */
     340             :             }
     341             :         }
     342             :         ELSE
     343             :         {
     344             :             /* Cardioids sum up to 1 */
     345          64 :             cardioid_right[i] = sub( ONE_IN_Q14 /* 1.0f in Q14 */, cardioid_left[i] ); /* corresponds to: alpha + ( 1 - alpha ) * cosf( tmp + tmp_1 ); */
     346          64 :             move16();
     347             :             /* Loop over all samples */
     348       61504 :             FOR( j = 0; j < input_frame; j++ )
     349             :             {
     350       61440 :                 tmp = data[i][j];
     351       61440 :                 move32();
     352       61440 :                 tmp = W_extract_l( W_shr( W_mult_32_16( tmp, cardioid_left[i] ), 15 ) ); /* Qx DMX Left  */
     353       61440 :                 stereo_dmx[0][j] = L_add( stereo_dmx[0][j], tmp );                       /* Qx DMX Left  */
     354       61440 :                 move32();
     355       61440 :                 tmp = data[i][j];
     356       61440 :                 move32();
     357       61440 :                 tmp = W_extract_l( W_shr( W_mult_32_16( tmp, cardioid_right[i] ), 15 ) ); /* Qx DMX Right */
     358       61440 :                 stereo_dmx[1][j] = L_add( stereo_dmx[1][j], tmp );                        /* Qx DMX Right */
     359       61440 :                 move32();
     360       61440 :                 ene_data = W_add( ene_data, W_mult_32_32( data[i][j], data[i][j] ) ); /* 2 * Qx + 1  energy of all objects combined */
     361             :             }
     362             :         }
     363       76130 :         st_ivas->hParamIsm->last_cardioid_left_fx[i] = cardioid_left[i]; // Q14
     364       76130 :         move16();
     365             :     }
     366             : 
     367             :     /* Energy compensation */
     368    19911920 :     FOR( j = 0; j < input_frame; j++ )
     369             :     {
     370    19891200 :         ene_dmx = W_mac_32_32( W_mac_32_32( ene_dmx, stereo_dmx[0][j], stereo_dmx[0][j] ), stereo_dmx[1][j], stereo_dmx[1][j] ); /* 2 * Qx + 1 */
     371             :     }
     372       20720 :     tmp_1 = W_norm( ene_data );
     373       20720 :     tmp_2 = W_norm( ene_dmx );
     374       20720 :     ene_data = W_shl( ene_data, tmp_1 );
     375       20720 :     ene_dmx = W_shl( ene_dmx, tmp_2 );
     376       20720 :     dmx_gain = BASOP_Util_Divide3232_Scale( W_extract_h( ene_data ), L_add_sat( W_extract_h( ene_dmx ), 1 ), &dmx_gain_e );
     377       20720 :     dmx_gain_e = sub( dmx_gain_e, sub( tmp_1, tmp_2 ) );
     378       20720 :     dmx_gain = Sqrt16( dmx_gain, &dmx_gain_e );
     379             : 
     380             :     /* Smoothing */
     381       20720 :     IF( st_ivas->hSCE[0]->hCoreCoder[0]->ini_frame > 0 )
     382             :     {
     383       20703 :         dmx_gain_e = BASOP_Util_Add_MantExp( mult( 24576 /* 0.75f */, dmx_gain ), dmx_gain_e, mult( 8192 /* 0.25f */, last_dmx_gain ), last_dmx_gain_e, &dmx_gain );
     384             :         /* 10ms ramp */
     385       20703 :         tmp = L_shl( last_dmx_gain, last_dmx_gain_e );                                                                                                          // Q15
     386       20703 :         grad = extract_l( Mpy_32_16_r( L_sub( L_shl( dmx_gain, dmx_gain_e ), tmp ), shl( one_by_input_frame, 1 ) /* 2.0f / (float) input_frame*/ ) ); /* Q15 */ /* slope between two consecutive gains, 480 samples length */
     387             : 
     388       20703 :         tmp_1 = 15 + 1;
     389       20703 :         move16();
     390     9958143 :         FOR( i = 0; i < input_frame >> 1; i++ )
     391             :         {
     392     9937440 :             stereo_dmx[0][i] = W_extract_l( W_shr( W_mult_32_32( stereo_dmx[0][i], L_add( tmp, mult0( i, grad ) ) ), tmp_1 ) ); // Qx
     393     9937440 :             move32();
     394     9937440 :             stereo_dmx[1][i] = W_extract_l( W_shr( W_mult_32_32( stereo_dmx[1][i], L_add( tmp, mult0( i, grad ) ) ), tmp_1 ) ); // Qx
     395     9937440 :             move32();
     396             :         }
     397       20703 :         tmp_1 = add( sub( 15, dmx_gain_e ), 1 );
     398     9958143 :         FOR( ; i < input_frame; i++ )
     399             :         {
     400     9937440 :             stereo_dmx[0][i] = W_extract_l( W_shr( W_mult_32_16( stereo_dmx[0][i], dmx_gain ), tmp_1 ) ); // Qx
     401     9937440 :             move32();
     402     9937440 :             stereo_dmx[1][i] = W_extract_l( W_shr( W_mult_32_16( stereo_dmx[1][i], dmx_gain ), tmp_1 ) ); // Qx
     403     9937440 :             move32();
     404             :         }
     405             :     }
     406             :     ELSE
     407             :     {
     408          17 :         tmp_1 = add( sub( 15, dmx_gain_e ), 1 );
     409       16337 :         FOR( j = 0; j < input_frame; j++ )
     410             :         {
     411       16320 :             stereo_dmx[0][j] = W_extract_l( W_shr( W_mult_32_16( stereo_dmx[0][j], dmx_gain ), tmp_1 ) ); // Qx
     412       16320 :             move32();
     413       16320 :             stereo_dmx[1][j] = W_extract_l( W_shr( W_mult_32_16( stereo_dmx[1][j], dmx_gain ), tmp_1 ) ); // Qx
     414       16320 :             move32();
     415             :         }
     416             :     }
     417       20720 :     st_ivas->hParamIsm->last_dmx_gain_fx = dmx_gain;
     418       20720 :     move16();
     419       20720 :     st_ivas->hParamIsm->last_dmx_gain_e = dmx_gain_e;
     420       20720 :     move16();
     421             : 
     422             :     /* Copy the stereo dmx to data variable */
     423       20720 :     Copy32( stereo_dmx[0], data[0], input_frame ); // Qx
     424       20720 :     Copy32( stereo_dmx[1], data[1], input_frame ); // Qx
     425             : 
     426       20720 :     pop_wmops();
     427             : 
     428       20720 :     return;
     429             : }
     430             : 
     431             : 
     432             : /*-------------------------------------------------------------------------*
     433             :  * ivas_param_ism_enc_open()
     434             :  *
     435             :  * Open Param ISM handle
     436             :  *-------------------------------------------------------------------------*/
     437             : 
     438         320 : ivas_error ivas_param_ism_enc_open_fx(
     439             :     Encoder_Struct *st_ivas /* i/o: IVAS encoder structure     */
     440             : )
     441             : {
     442             :     Word16 i;
     443             :     IVAS_FB_CFG *fb_cfg;
     444             :     PARAM_ISM_CONFIG_HANDLE hParamIsm;
     445             :     Word16 max_bins;
     446             :     Word32 input_Fs;
     447             :     ivas_error error;
     448             : 
     449         320 :     error = IVAS_ERR_OK;
     450         320 :     move32();
     451             : 
     452             :     /* Assign memory to Param Object handle */
     453         320 :     if ( ( hParamIsm = (PARAM_ISM_CONFIG_HANDLE) malloc( sizeof( PARAM_ISM_CONFIG_DATA ) ) ) == NULL )
     454             :     {
     455           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Param ISM\n" ) );
     456             :     }
     457             : 
     458         320 :     input_Fs = st_ivas->hEncoderConfig->input_Fs;
     459         320 :     move32();
     460             : 
     461             : 
     462             :     /* set FB config. */
     463         320 :     IF( NE_32( ( error = ivas_fb_set_cfg( &fb_cfg, ISM_FORMAT, st_ivas->hEncoderConfig->nchan_inp, 0, 0, input_Fs, 0 ) ), IVAS_ERR_OK ) )
     464             :     {
     465           0 :         return error;
     466             :     }
     467             : 
     468             :     /* Allocate and initialize FB mixer handle */
     469         320 :     IF( NE_32( ( error = ivas_FB_mixer_open_fx( &( hParamIsm->hFbMixer ), input_Fs, fb_cfg, 0 ) ), IVAS_ERR_OK ) )
     470             :     {
     471           0 :         return error;
     472             :     }
     473             : 
     474         320 :     ivas_param_ism_config_fx( hParamIsm, st_ivas->hEncoderConfig->nchan_inp );
     475             : 
     476             :     /* Assign memories for Band and Block grouping  */
     477         320 :     hParamIsm->nbands = MAX_PARAM_ISM_NBANDS;
     478         320 :     move16();
     479             : 
     480         320 :     max_bins = extract_l( Mpy_32_32( input_Fs, 10737418 /*240/48000.Q31*/ ) ); // (int16_t) ( ( MDFT_FB_BANDS_240 * input_Fs ) / 48000 );
     481        4160 :     FOR( i = 0; i < ( hParamIsm->nbands + 1 ); i++ )
     482             :     {
     483        3840 :         hParamIsm->band_grouping[i] = CLDFB_TO_MDFT_FAC * Param_ISM_band_grouping[i];
     484        3840 :         move16();
     485        3840 :         IF( GT_16( i_mult( Param_ISM_band_grouping[i], CLDFB_TO_MDFT_FAC ), max_bins ) )
     486             :         {
     487         320 :             hParamIsm->band_grouping[i] = max_bins;
     488         320 :             move16();
     489             :         }
     490             :     }
     491             : 
     492         320 :     set16_fx( hParamIsm->noisy_speech_buffer, 0, PARAM_ISM_HYS_BUF_SIZE );
     493             : 
     494         320 :     st_ivas->hParamIsm = hParamIsm;
     495             : 
     496         320 :     return error;
     497             : }
     498             : 
     499             : 
     500             : /*-------------------------------------------------------------------------*
     501             :  * ivas_param_ism_enc_close()
     502             :  *
     503             :  * Close Param ISM encoder handle
     504             :  *-------------------------------------------------------------------------*/
     505             : 
     506         930 : void ivas_param_ism_enc_close_fx(
     507             :     PARAM_ISM_CONFIG_HANDLE *hParamIsm, /* i/o: ParamISM handle   */
     508             :     const Word32 input_Fs               /* i  : input sampling_rate       */
     509             : )
     510             : {
     511         930 :     test();
     512         930 :     IF( hParamIsm == NULL || *hParamIsm == NULL )
     513             :     {
     514         610 :         return;
     515             :     }
     516             : 
     517         320 :     ivas_FB_mixer_close_fx( &( *hParamIsm )->hFbMixer, input_Fs, 0 );
     518             : 
     519         320 :     free( ( *hParamIsm ) );
     520         320 :     ( *hParamIsm ) = NULL;
     521             : 
     522         320 :     return;
     523             : }
     524             : 
     525             : 
     526             : /*-------------------------------------------------------------------------*
     527             :  * ivas_param_ism_enc()
     528             :  *
     529             :  * Parametric ISM encoder
     530             :  *-------------------------------------------------------------------------*/
     531             : 
     532       20720 : void ivas_param_ism_enc_fx(
     533             :     Encoder_Struct *st_ivas,       /* i/o: IVAS encoder structure          */
     534             :     Word32 *data[MAX_NUM_OBJECTS], /* i  : input signal           q_pcm_in */
     535             :     const Word16 input_frame       /* i  : input frame length per channel  */
     536             : )
     537             : {
     538             :     Word16 i, j, ts, l_ts;
     539             :     Word16 nchan_ism;
     540             :     Word16 num_time_slots;
     541             :     Word16 q_p_fb_Buffer;
     542             :     Word32 *pcm_in[MAX_NUM_OBJECTS];
     543             :     Word32 fb_RealBuffer[MAX_NUM_OBJECTS][DIRAC_NO_FB_BANDS_MAX];
     544             :     Word32 fb_ImagBuffer[MAX_NUM_OBJECTS][DIRAC_NO_FB_BANDS_MAX];
     545             :     Word32 *p_fb_RealBuffer[MAX_NUM_OBJECTS];
     546             :     Word32 *p_fb_ImagBuffer[MAX_NUM_OBJECTS];
     547             :     Word64 reference_power_obj[MAX_NUM_OBJECTS][PARAM_ISM_MDFT_NO_SLOTS][DIRAC_NO_FB_BANDS_MAX];
     548             :     PARAM_ISM_CONFIG_HANDLE hParamIsm;
     549             : 
     550       20720 :     nchan_ism = st_ivas->hEncoderConfig->nchan_ism;
     551       20720 :     move16();
     552       20720 :     hParamIsm = st_ivas->hParamIsm;
     553             : 
     554       20720 :     push_wmops( "ivas_param_ism_enc" );
     555             : 
     556       20720 :     l_ts = shr( input_frame, 2 ); /* input_frame / PARAM_ISM_MDFT_NO_SLOTS */
     557       20720 :     num_time_slots = PARAM_ISM_MDFT_NO_SLOTS;
     558       20720 :     move16();
     559             : 
     560       96850 :     FOR( i = 0; i < nchan_ism; i++ )
     561             :     {
     562       76130 :         pcm_in[i] = data[i];
     563             : 
     564       76130 :         set_zero_fx( fb_RealBuffer[i], DIRAC_NO_FB_BANDS_MAX );
     565       76130 :         set_zero_fx( fb_ImagBuffer[i], DIRAC_NO_FB_BANDS_MAX );
     566       76130 :         p_fb_RealBuffer[i] = &fb_RealBuffer[i][0];
     567       76130 :         p_fb_ImagBuffer[i] = &fb_ImagBuffer[i][0];
     568             :     }
     569             : 
     570       20720 :     Word16 gb = find_guarded_bits_fx( l_ts );
     571       20720 :     q_p_fb_Buffer = sub( st_ivas->q_data_fx, gb );
     572             : 
     573      103600 :     FOR( ts = 0; ts < num_time_slots; ts++ )
     574             :     {
     575       82880 :         ivas_fb_mixer_get_windowed_fr_fx( hParamIsm->hFbMixer, pcm_in, p_fb_RealBuffer, p_fb_ImagBuffer, l_ts, l_ts, hParamIsm->hFbMixer->fb_cfg->num_in_chans, gb );
     576             : 
     577       82880 :         ivas_fb_mixer_update_prior_input_fx( hParamIsm->hFbMixer, pcm_in, l_ts, hParamIsm->hFbMixer->fb_cfg->num_in_chans );
     578             : 
     579      387400 :         FOR( i = 0; i < nchan_ism; i++ )
     580             :         {
     581      304520 :             pcm_in[i] += l_ts;
     582    73389320 :             FOR( j = 0; j < DIRAC_NO_FB_BANDS_MAX; j++ )
     583             :             {
     584    73084800 :                 reference_power_obj[i][ts][j] = W_shr( W_add( W_mult0_32_32( fb_RealBuffer[i][j], fb_RealBuffer[i][j] ), W_mult0_32_32( fb_ImagBuffer[i][j], fb_ImagBuffer[i][j] ) ), shl( q_p_fb_Buffer, 1 ) ); // Q0
     585    73084800 :                 move64();
     586             :             }
     587             :         }
     588             :     }
     589             : 
     590       20720 :     ivas_param_ism_enc_quantize_DOA_fx( nchan_ism, st_ivas->hIsmMetaData, hParamIsm );
     591             : 
     592       20720 :     ivas_param_ism_compute_obj_parameters_fx( nchan_ism, reference_power_obj, hParamIsm );
     593             : 
     594       20720 :     pop_wmops();
     595       20720 :     return;
     596             : }
     597             : 
     598             : 
     599             : /*-------------------------------------------------------------------*
     600             :  * ivas_param_ism_compute_noisy_speech_flag()
     601             :  *
     602             :  *
     603             :  *-------------------------------------------------------------------*/
     604             : 
     605       20720 : void ivas_param_ism_compute_noisy_speech_flag_fx(
     606             :     Encoder_Struct *st_ivas /* i/o: IVAS encoder structure          */
     607             : )
     608             : {
     609             :     Word16 i;
     610             : 
     611             :     /* Move the Noisy speech buffer */
     612      207200 :     FOR( i = 0; i < ( PARAM_ISM_HYS_BUF_SIZE - 1 ); i++ )
     613             :     {
     614      186480 :         st_ivas->hParamIsm->noisy_speech_buffer[i] = st_ivas->hParamIsm->noisy_speech_buffer[i + 1];
     615      186480 :         move16();
     616             :     }
     617             : 
     618             :     /* Set flag_noisy_speech to 0 for cases where object energies are not roughly equal */
     619       20720 :     IF( !st_ivas->hParamIsm->flag_equal_energy )
     620             :     {
     621       20719 :         st_ivas->hParamIsm->noisy_speech_buffer[i] = 0;
     622       20719 :         st_ivas->hParamIsm->flag_noisy_speech = 0;
     623       20719 :         move16();
     624       20719 :         move16();
     625             :     }
     626             :     ELSE
     627             :     {
     628             :         /* For the current frame, make a decision based on some core-coder flags */
     629           1 :         test();
     630           1 :         IF( st_ivas->hSCE[0]->hCoreCoder[0]->flag_noisy_speech_snr && st_ivas->hSCE[1]->hCoreCoder[0]->flag_noisy_speech_snr )
     631             :         {
     632           1 :             test();
     633           1 :             IF( st_ivas->hSCE[0]->hCoreCoder[0]->vad_flag || st_ivas->hSCE[1]->hCoreCoder[0]->vad_flag )
     634             :             {
     635           0 :                 st_ivas->hParamIsm->noisy_speech_buffer[i] = 0;
     636           0 :                 move16();
     637             :             }
     638             :             ELSE
     639             :             {
     640           1 :                 st_ivas->hParamIsm->noisy_speech_buffer[i] = 1;
     641           1 :                 move16();
     642             :             }
     643             :         }
     644             :         ELSE
     645             :         {
     646           0 :             st_ivas->hParamIsm->noisy_speech_buffer[i] = 0;
     647           0 :             move16();
     648             :         }
     649             : 
     650             :         /* Do a decision based on hysteresis */
     651           1 :         st_ivas->hParamIsm->flag_noisy_speech = 1;
     652           1 :         move16();
     653          11 :         FOR( i = 0; i < PARAM_ISM_HYS_BUF_SIZE; i++ )
     654             :         {
     655          10 :             test();
     656          10 :             st_ivas->hParamIsm->flag_noisy_speech = st_ivas->hParamIsm->flag_noisy_speech && st_ivas->hParamIsm->noisy_speech_buffer[i];
     657             :         }
     658             :     }
     659             : 
     660       20720 :     return;
     661             : }

Generated by: LCOV version 1.14